Files
cef/tools/file_util.py
Marshall Greenblatt e88e98f061 tools: Add VSCode setup (fixes #3906)
Add tooling to set up a Visual Studio Code development environment
for CEF. See script output for usage.

Run: python3 tools/setup_vscode.py
2025-03-20 13:53:33 -04:00

277 lines
7.2 KiB
Python

# Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights
# reserved. Use of this source code is governed by a BSD-style license that
# can be found in the LICENSE file.
from __future__ import absolute_import
import codecs
import fnmatch
from glob import iglob
from io import open
import json
import os
import shutil
import sys
import time
def read_file(path, normalize=True):
""" Read a file. """
if os.path.isfile(path):
try:
with open(path, 'r', encoding='utf-8') as f:
# read the data
data = f.read()
if normalize:
# normalize line endings
data = data.replace("\r\n", "\n")
return data
except IOError as e:
(errno, strerror) = e.args
sys.stderr.write('ERROR: Failed to read file ' + path + ': ' + strerror)
raise
return None
def write_file(path, data, overwrite=True, quiet=True):
""" Write a file. """
if not overwrite and os.path.exists(path):
return False
if not quiet:
print('Writing %s file.' % path)
try:
with open(path, 'w', encoding='utf-8', newline='\n') as f:
# write the data
if sys.version_info.major == 2:
f.write(data.decode('utf-8'))
else:
f.write(data)
except IOError as e:
(errno, strerror) = e.args
sys.stderr.write('ERROR: Failed to write file ' + path + ': ' + strerror)
raise
return True
def path_exists(path):
""" Returns true if the path currently exists. """
return os.path.exists(path)
def write_file_if_changed(path, data, quiet=True):
""" Write a file if the contents have changed. Returns True if the file was written. """
if path_exists(path):
old_contents = read_file(path)
assert not old_contents is None, path
else:
old_contents = ''
if (data != old_contents):
write_file(path, data, quiet=quiet)
return True
return False
def backup_file(path):
""" Rename the file to a name that includes the current time stamp. """
move_file(path, path + '.' + time.strftime('%Y-%m-%d-%H-%M-%S'))
def copy_file(src, dst, quiet=True):
""" Copy a file. """
if not os.path.isfile(src):
return False
try:
if not quiet:
sys.stdout.write('Transferring ' + src + ' file.\n')
shutil.copy2(src, dst)
except IOError as e:
(errno, strerror) = e.args
sys.stderr.write('ERROR: Failed to copy file from ' + src + ' to ' + dst +
': ' + strerror)
raise
return True
def move_file(src, dst, quiet=True):
""" Move a file. """
if not os.path.isfile(src):
return False
try:
if not quiet:
print('Moving ' + src + ' file.')
shutil.move(src, dst)
except IOError as e:
(errno, strerror) = e.args
sys.stderr.write('ERROR: Failed to move file from ' + src + ' to ' + dst +
': ' + strerror)
raise
return True
def copy_files(src_glob, dst_folder, quiet=True):
""" Copy multiple files. """
for fname in iglob(src_glob):
dst = os.path.join(dst_folder, os.path.basename(fname))
if os.path.isdir(fname):
copy_dir(fname, dst, quiet)
else:
copy_file(fname, dst, quiet)
def remove_file(path, quiet=True):
""" Remove the specified file. """
try:
if path_exists(path):
if not quiet:
print('Removing ' + path + ' file.')
os.remove(path)
return True
except IOError as e:
(errno, strerror) = e.args
sys.stderr.write('ERROR: Failed to remove file ' + path + ': ' + strerror)
raise
return False
def copy_dir(src, dst, quiet=True):
""" Copy a directory tree. """
try:
remove_dir(dst, quiet)
if not quiet:
print('Transferring ' + src + ' directory.')
shutil.copytree(src, dst)
except IOError as e:
(errno, strerror) = e.args
sys.stderr.write('ERROR: Failed to copy directory from ' + src + ' to ' +
dst + ': ' + strerror)
raise
def remove_dir(path, quiet=True):
""" Remove the specified directory. """
try:
if path_exists(path):
if not quiet:
print('Removing ' + path + ' directory.')
shutil.rmtree(path)
return True
except IOError as e:
(errno, strerror) = e.args
sys.stderr.write('ERROR: Failed to remove directory ' + path + ': ' +
strerror)
raise
return False
def make_dir(path, quiet=True):
""" Create the specified directory. """
try:
if not path_exists(path):
if not quiet:
print('Creating ' + path + ' directory.')
os.makedirs(path)
except IOError as e:
(errno, strerror) = e.args
sys.stderr.write('ERROR: Failed to create directory ' + path + ': ' +
strerror)
raise
def get_files(search_glob):
""" Returns all files matching |search_glob|. """
recursive_glob = '**' + os.path.sep
if recursive_glob in search_glob:
if sys.version_info >= (3, 5):
result = iglob(search_glob, recursive=True)
else:
# Polyfill for recursive glob pattern matching added in Python 3.5.
result = get_files_recursive(*search_glob.split(recursive_glob))
else:
result = iglob(search_glob)
# Sort the result for consistency across platforms.
return sorted(result)
def get_files_recursive(directory, pattern):
""" Returns all files in |directory| matching |pattern| recursively. """
for root, dirs, files in os.walk(directory):
for basename in files:
if fnmatch.fnmatch(basename, pattern):
filename = os.path.join(root, basename)
yield filename
def read_version_file(path, args):
""" Read and parse a version file (key=value pairs, one per line). """
contents = read_file(path)
if contents is None:
return False
lines = contents.split("\n")
for line in lines:
parts = line.split('=', 1)
if len(parts) == 2:
args[parts[0]] = parts[1]
return True
def eval_file(src):
""" Loads and evaluates the contents of the specified file. """
return eval(read_file(src), {'__builtins__': None}, None)
def normalize_path(path):
""" Normalizes the path separator to match the Unix standard. """
if sys.platform == 'win32':
return path.replace('\\', '/')
return path
def read_json_file(path):
""" Read and parse a JSON file. Returns a list/dictionary or None. """
if os.path.isfile(path):
try:
with codecs.open(path, 'r', encoding='utf-8') as fp:
return json.load(fp)
except IOError as e:
(errno, strerror) = e.args
sys.stderr.write('ERROR: Failed to read file ' + path + ': ' + strerror)
raise
return None
def _bytes_encoder(z):
if isinstance(z, bytes):
return str(z, 'utf-8')
else:
type_name = z.__class__.__name__
raise TypeError(f"Object of type {type_name} is not serializable")
def write_json_file(path, data, overwrite=True, quiet=True):
""" Serialize and write a JSON file. Returns True on success. """
if not overwrite and os.path.exists(path):
return False
if not quiet:
print('Writing file %s' % path)
try:
with open(path, 'w', encoding='utf-8') as fp:
json.dump(
data,
fp,
ensure_ascii=False,
indent=2,
sort_keys=True,
default=_bytes_encoder)
except IOError as e:
(errno, strerror) = e.args
sys.stderr.write('ERROR: Failed to write file ' + path + ': ' + strerror)
raise
return True