mirror of
https://gerrit.googlesource.com/git-repo
synced 2025-07-04 20:17:16 +00:00
Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
a2cd6aeae8 | |||
70d861fa29 | |||
9100f7fadd | |||
01d6c3c0c5 | |||
4c263b52e7 | |||
60fdc5cad1 |
17
progress.py
17
progress.py
@ -21,6 +21,11 @@ from repo_trace import IsTrace
|
|||||||
|
|
||||||
_NOT_TTY = not os.isatty(2)
|
_NOT_TTY = not os.isatty(2)
|
||||||
|
|
||||||
|
# This will erase all content in the current line (wherever the cursor is).
|
||||||
|
# It does not move the cursor, so this is usually followed by \r to move to
|
||||||
|
# column 0.
|
||||||
|
CSI_ERASE_LINE = '\x1b[2K'
|
||||||
|
|
||||||
class Progress(object):
|
class Progress(object):
|
||||||
def __init__(self, title, total=0, units='', print_newline=False,
|
def __init__(self, title, total=0, units='', print_newline=False,
|
||||||
always_print_percentage=False):
|
always_print_percentage=False):
|
||||||
@ -47,7 +52,8 @@ class Progress(object):
|
|||||||
return
|
return
|
||||||
|
|
||||||
if self._total <= 0:
|
if self._total <= 0:
|
||||||
sys.stderr.write('\r%s: %d, ' % (
|
sys.stderr.write('%s\r%s: %d,' % (
|
||||||
|
CSI_ERASE_LINE,
|
||||||
self._title,
|
self._title,
|
||||||
self._done))
|
self._done))
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
@ -56,7 +62,8 @@ class Progress(object):
|
|||||||
|
|
||||||
if self._lastp != p or self._always_print_percentage:
|
if self._lastp != p or self._always_print_percentage:
|
||||||
self._lastp = p
|
self._lastp = p
|
||||||
sys.stderr.write('\r%s: %3d%% (%d%s/%d%s)%s' % (
|
sys.stderr.write('%s\r%s: %3d%% (%d%s/%d%s)%s' % (
|
||||||
|
CSI_ERASE_LINE,
|
||||||
self._title,
|
self._title,
|
||||||
p,
|
p,
|
||||||
self._done, self._units,
|
self._done, self._units,
|
||||||
@ -69,13 +76,15 @@ class Progress(object):
|
|||||||
return
|
return
|
||||||
|
|
||||||
if self._total <= 0:
|
if self._total <= 0:
|
||||||
sys.stderr.write('\r%s: %d, done. \n' % (
|
sys.stderr.write('%s\r%s: %d, done.\n' % (
|
||||||
|
CSI_ERASE_LINE,
|
||||||
self._title,
|
self._title,
|
||||||
self._done))
|
self._done))
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
else:
|
else:
|
||||||
p = (100 * self._done) / self._total
|
p = (100 * self._done) / self._total
|
||||||
sys.stderr.write('\r%s: %3d%% (%d%s/%d%s), done. \n' % (
|
sys.stderr.write('%s\r%s: %3d%% (%d%s/%d%s), done.\n' % (
|
||||||
|
CSI_ERASE_LINE,
|
||||||
self._title,
|
self._title,
|
||||||
p,
|
p,
|
||||||
self._done, self._units,
|
self._done, self._units,
|
||||||
|
20
project.py
20
project.py
@ -39,6 +39,7 @@ from error import GitError, HookError, UploadError, DownloadError
|
|||||||
from error import ManifestInvalidRevisionError
|
from error import ManifestInvalidRevisionError
|
||||||
from error import NoManifestException
|
from error import NoManifestException
|
||||||
import platform_utils
|
import platform_utils
|
||||||
|
import progress
|
||||||
from repo_trace import IsTrace, Trace
|
from repo_trace import IsTrace, Trace
|
||||||
|
|
||||||
from git_refs import GitRefs, HEAD, R_HEADS, R_TAGS, R_PUB, R_M
|
from git_refs import GitRefs, HEAD, R_HEADS, R_TAGS, R_PUB, R_M
|
||||||
@ -1697,7 +1698,7 @@ class Project(object):
|
|||||||
|
|
||||||
# Branch Management ##
|
# Branch Management ##
|
||||||
|
|
||||||
def StartBranch(self, name, branch_merge=''):
|
def StartBranch(self, name, branch_merge='', revision=None):
|
||||||
"""Create a new branch off the manifest's revision.
|
"""Create a new branch off the manifest's revision.
|
||||||
"""
|
"""
|
||||||
if not branch_merge:
|
if not branch_merge:
|
||||||
@ -1718,7 +1719,11 @@ class Project(object):
|
|||||||
branch.merge = branch_merge
|
branch.merge = branch_merge
|
||||||
if not branch.merge.startswith('refs/') and not ID_RE.match(branch_merge):
|
if not branch.merge.startswith('refs/') and not ID_RE.match(branch_merge):
|
||||||
branch.merge = R_HEADS + branch_merge
|
branch.merge = R_HEADS + branch_merge
|
||||||
revid = self.GetRevisionId(all_refs)
|
|
||||||
|
if revision is None:
|
||||||
|
revid = self.GetRevisionId(all_refs)
|
||||||
|
else:
|
||||||
|
revid = self.work_git.rev_parse(revision)
|
||||||
|
|
||||||
if head.startswith(R_HEADS):
|
if head.startswith(R_HEADS):
|
||||||
try:
|
try:
|
||||||
@ -2181,12 +2186,15 @@ class Project(object):
|
|||||||
cmd.append('--update-head-ok')
|
cmd.append('--update-head-ok')
|
||||||
cmd.append(name)
|
cmd.append(name)
|
||||||
|
|
||||||
|
spec = []
|
||||||
|
|
||||||
# If using depth then we should not get all the tags since they may
|
# If using depth then we should not get all the tags since they may
|
||||||
# be outside of the depth.
|
# be outside of the depth.
|
||||||
if no_tags or depth:
|
if no_tags or depth:
|
||||||
cmd.append('--no-tags')
|
cmd.append('--no-tags')
|
||||||
else:
|
else:
|
||||||
cmd.append('--tags')
|
cmd.append('--tags')
|
||||||
|
spec.append(str((u'+refs/tags/*:') + remote.ToLocal('refs/tags/*')))
|
||||||
|
|
||||||
if force_sync:
|
if force_sync:
|
||||||
cmd.append('--force')
|
cmd.append('--force')
|
||||||
@ -2197,12 +2205,9 @@ class Project(object):
|
|||||||
if submodules:
|
if submodules:
|
||||||
cmd.append('--recurse-submodules=on-demand')
|
cmd.append('--recurse-submodules=on-demand')
|
||||||
|
|
||||||
spec = []
|
|
||||||
if not current_branch_only:
|
if not current_branch_only:
|
||||||
# Fetch whole repo
|
# Fetch whole repo
|
||||||
spec.append(str((u'+refs/heads/*:') + remote.ToLocal('refs/heads/*')))
|
spec.append(str((u'+refs/heads/*:') + remote.ToLocal('refs/heads/*')))
|
||||||
if not (no_tags or depth):
|
|
||||||
spec.append(str((u'+refs/tags/*:') + remote.ToLocal('refs/tags/*')))
|
|
||||||
elif tag_name is not None:
|
elif tag_name is not None:
|
||||||
spec.append('tag')
|
spec.append('tag')
|
||||||
spec.append(tag_name)
|
spec.append(tag_name)
|
||||||
@ -3109,6 +3114,11 @@ class SyncBuffer(object):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def _PrintMessages(self):
|
def _PrintMessages(self):
|
||||||
|
if self._messages or self._failures:
|
||||||
|
if os.isatty(2):
|
||||||
|
self.out.write(progress.CSI_ERASE_LINE)
|
||||||
|
self.out.write('\r')
|
||||||
|
|
||||||
for m in self._messages:
|
for m in self._messages:
|
||||||
m.Print(self)
|
m.Print(self)
|
||||||
for m in self._failures:
|
for m in self._failures:
|
||||||
|
13
repo
13
repo
@ -443,7 +443,7 @@ def _CheckGitVersion():
|
|||||||
raise CloneFailure()
|
raise CloneFailure()
|
||||||
|
|
||||||
if ver_act is None:
|
if ver_act is None:
|
||||||
print('error: "%s" unsupported' % ver_str, file=sys.stderr)
|
print('fatal: unable to detect git version', file=sys.stderr)
|
||||||
raise CloneFailure()
|
raise CloneFailure()
|
||||||
|
|
||||||
if ver_act < MIN_GIT_VERSION:
|
if ver_act < MIN_GIT_VERSION:
|
||||||
@ -505,7 +505,7 @@ def SetupGnuPG(quiet):
|
|||||||
print(file=sys.stderr)
|
print(file=sys.stderr)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
proc.stdin.write(MAINTAINER_KEYS)
|
proc.stdin.write(MAINTAINER_KEYS.encode('utf-8'))
|
||||||
proc.stdin.close()
|
proc.stdin.close()
|
||||||
|
|
||||||
if proc.wait() != 0:
|
if proc.wait() != 0:
|
||||||
@ -584,6 +584,7 @@ def _DownloadBundle(url, local, quiet):
|
|||||||
cwd=local,
|
cwd=local,
|
||||||
stdout=subprocess.PIPE)
|
stdout=subprocess.PIPE)
|
||||||
for line in proc.stdout:
|
for line in proc.stdout:
|
||||||
|
line = line.decode('utf-8')
|
||||||
m = re.compile(r'^url\.(.*)\.insteadof (.*)$').match(line)
|
m = re.compile(r'^url\.(.*)\.insteadof (.*)$').match(line)
|
||||||
if m:
|
if m:
|
||||||
new_url = m.group(1)
|
new_url = m.group(1)
|
||||||
@ -676,7 +677,7 @@ def _Verify(cwd, branch, quiet):
|
|||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
cwd=cwd)
|
cwd=cwd)
|
||||||
cur = proc.stdout.read().strip()
|
cur = proc.stdout.read().strip().decode('utf-8')
|
||||||
proc.stdout.close()
|
proc.stdout.close()
|
||||||
|
|
||||||
proc.stderr.read()
|
proc.stderr.read()
|
||||||
@ -708,10 +709,10 @@ def _Verify(cwd, branch, quiet):
|
|||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
cwd=cwd,
|
cwd=cwd,
|
||||||
env=env)
|
env=env)
|
||||||
out = proc.stdout.read()
|
out = proc.stdout.read().decode('utf-8')
|
||||||
proc.stdout.close()
|
proc.stdout.close()
|
||||||
|
|
||||||
err = proc.stderr.read()
|
err = proc.stderr.read().decode('utf-8')
|
||||||
proc.stderr.close()
|
proc.stderr.close()
|
||||||
|
|
||||||
if proc.wait() != 0:
|
if proc.wait() != 0:
|
||||||
@ -861,7 +862,7 @@ def _SetDefaultsTo(gitdir):
|
|||||||
'HEAD'],
|
'HEAD'],
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE)
|
stderr=subprocess.PIPE)
|
||||||
REPO_REV = proc.stdout.read().strip()
|
REPO_REV = proc.stdout.read().strip().decode('utf-8')
|
||||||
proc.stdout.close()
|
proc.stdout.close()
|
||||||
|
|
||||||
proc.stderr.read()
|
proc.stderr.read()
|
||||||
|
@ -40,6 +40,10 @@ revision specified in the manifest.
|
|||||||
p.add_option('--all',
|
p.add_option('--all',
|
||||||
dest='all', action='store_true',
|
dest='all', action='store_true',
|
||||||
help='begin branch in all projects')
|
help='begin branch in all projects')
|
||||||
|
p.add_option('-r', '--rev', '--revision', dest='revision',
|
||||||
|
help='point branch at this revision instead of upstream')
|
||||||
|
p.add_option('--head', dest='revision', action='store_const', const='HEAD',
|
||||||
|
help='abbreviation for --rev HEAD')
|
||||||
|
|
||||||
def ValidateOptions(self, opt, args):
|
def ValidateOptions(self, opt, args):
|
||||||
if not args:
|
if not args:
|
||||||
@ -108,7 +112,8 @@ revision specified in the manifest.
|
|||||||
else:
|
else:
|
||||||
branch_merge = self.manifest.default.revisionExpr
|
branch_merge = self.manifest.default.revisionExpr
|
||||||
|
|
||||||
if not project.StartBranch(nb, branch_merge=branch_merge):
|
if not project.StartBranch(
|
||||||
|
nb, branch_merge=branch_merge, revision=opt.revision):
|
||||||
err.append(project)
|
err.append(project)
|
||||||
pm.end()
|
pm.end()
|
||||||
|
|
||||||
|
196
subcmds/sync.py
196
subcmds/sync.py
@ -739,6 +739,103 @@ later is required to fix a server side protocol bug.
|
|||||||
fd.close()
|
fd.close()
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
def _SmartSyncSetup(self, opt, smart_sync_manifest_path):
|
||||||
|
if not self.manifest.manifest_server:
|
||||||
|
print('error: cannot smart sync: no manifest server defined in '
|
||||||
|
'manifest', file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
manifest_server = self.manifest.manifest_server
|
||||||
|
if not opt.quiet:
|
||||||
|
print('Using manifest server %s' % manifest_server)
|
||||||
|
|
||||||
|
if not '@' in manifest_server:
|
||||||
|
username = None
|
||||||
|
password = None
|
||||||
|
if opt.manifest_server_username and opt.manifest_server_password:
|
||||||
|
username = opt.manifest_server_username
|
||||||
|
password = opt.manifest_server_password
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
info = netrc.netrc()
|
||||||
|
except IOError:
|
||||||
|
# .netrc file does not exist or could not be opened
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
parse_result = urllib.parse.urlparse(manifest_server)
|
||||||
|
if parse_result.hostname:
|
||||||
|
auth = info.authenticators(parse_result.hostname)
|
||||||
|
if auth:
|
||||||
|
username, _account, password = auth
|
||||||
|
else:
|
||||||
|
print('No credentials found for %s in .netrc'
|
||||||
|
% parse_result.hostname, file=sys.stderr)
|
||||||
|
except netrc.NetrcParseError as e:
|
||||||
|
print('Error parsing .netrc file: %s' % e, file=sys.stderr)
|
||||||
|
|
||||||
|
if (username and password):
|
||||||
|
manifest_server = manifest_server.replace('://', '://%s:%s@' %
|
||||||
|
(username, password),
|
||||||
|
1)
|
||||||
|
|
||||||
|
transport = PersistentTransport(manifest_server)
|
||||||
|
if manifest_server.startswith('persistent-'):
|
||||||
|
manifest_server = manifest_server[len('persistent-'):]
|
||||||
|
|
||||||
|
try:
|
||||||
|
server = xmlrpc.client.Server(manifest_server, transport=transport)
|
||||||
|
if opt.smart_sync:
|
||||||
|
p = self.manifest.manifestProject
|
||||||
|
b = p.GetBranch(p.CurrentBranch)
|
||||||
|
branch = b.merge
|
||||||
|
if branch.startswith(R_HEADS):
|
||||||
|
branch = branch[len(R_HEADS):]
|
||||||
|
|
||||||
|
env = os.environ.copy()
|
||||||
|
if 'SYNC_TARGET' in env:
|
||||||
|
target = env['SYNC_TARGET']
|
||||||
|
[success, manifest_str] = server.GetApprovedManifest(branch, target)
|
||||||
|
elif 'TARGET_PRODUCT' in env and 'TARGET_BUILD_VARIANT' in env:
|
||||||
|
target = '%s-%s' % (env['TARGET_PRODUCT'],
|
||||||
|
env['TARGET_BUILD_VARIANT'])
|
||||||
|
[success, manifest_str] = server.GetApprovedManifest(branch, target)
|
||||||
|
else:
|
||||||
|
[success, manifest_str] = server.GetApprovedManifest(branch)
|
||||||
|
else:
|
||||||
|
assert(opt.smart_tag)
|
||||||
|
[success, manifest_str] = server.GetManifest(opt.smart_tag)
|
||||||
|
|
||||||
|
if success:
|
||||||
|
manifest_name = os.path.basename(smart_sync_manifest_path)
|
||||||
|
try:
|
||||||
|
f = open(smart_sync_manifest_path, 'w')
|
||||||
|
try:
|
||||||
|
f.write(manifest_str)
|
||||||
|
finally:
|
||||||
|
f.close()
|
||||||
|
except IOError as e:
|
||||||
|
print('error: cannot write manifest to %s:\n%s'
|
||||||
|
% (smart_sync_manifest_path, e),
|
||||||
|
file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
self._ReloadManifest(manifest_name)
|
||||||
|
else:
|
||||||
|
print('error: manifest server RPC call failed: %s' %
|
||||||
|
manifest_str, file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
except (socket.error, IOError, xmlrpc.client.Fault) as e:
|
||||||
|
print('error: cannot connect to manifest server %s:\n%s'
|
||||||
|
% (self.manifest.manifest_server, e), file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
except xmlrpc.client.ProtocolError as e:
|
||||||
|
print('error: cannot connect to manifest server %s:\n%d %s'
|
||||||
|
% (self.manifest.manifest_server, e.errcode, e.errmsg),
|
||||||
|
file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
return manifest_name
|
||||||
|
|
||||||
def ValidateOptions(self, opt, args):
|
def ValidateOptions(self, opt, args):
|
||||||
if opt.force_broken:
|
if opt.force_broken:
|
||||||
print('warning: -f/--force-broken is now the default behavior, and the '
|
print('warning: -f/--force-broken is now the default behavior, and the '
|
||||||
@ -768,105 +865,12 @@ later is required to fix a server side protocol bug.
|
|||||||
self.manifest.Override(opt.manifest_name)
|
self.manifest.Override(opt.manifest_name)
|
||||||
|
|
||||||
manifest_name = opt.manifest_name
|
manifest_name = opt.manifest_name
|
||||||
smart_sync_manifest_name = "smart_sync_override.xml"
|
|
||||||
smart_sync_manifest_path = os.path.join(
|
smart_sync_manifest_path = os.path.join(
|
||||||
self.manifest.manifestProject.worktree, smart_sync_manifest_name)
|
self.manifest.manifestProject.worktree, 'smart_sync_override.xml')
|
||||||
|
|
||||||
if opt.smart_sync or opt.smart_tag:
|
if opt.smart_sync or opt.smart_tag:
|
||||||
if not self.manifest.manifest_server:
|
manifest_name = self._SmartSyncSetup(opt, smart_sync_manifest_path)
|
||||||
print('error: cannot smart sync: no manifest server defined in '
|
else:
|
||||||
'manifest', file=sys.stderr)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
manifest_server = self.manifest.manifest_server
|
|
||||||
if not opt.quiet:
|
|
||||||
print('Using manifest server %s' % manifest_server)
|
|
||||||
|
|
||||||
if not '@' in manifest_server:
|
|
||||||
username = None
|
|
||||||
password = None
|
|
||||||
if opt.manifest_server_username and opt.manifest_server_password:
|
|
||||||
username = opt.manifest_server_username
|
|
||||||
password = opt.manifest_server_password
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
info = netrc.netrc()
|
|
||||||
except IOError:
|
|
||||||
# .netrc file does not exist or could not be opened
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
parse_result = urllib.parse.urlparse(manifest_server)
|
|
||||||
if parse_result.hostname:
|
|
||||||
auth = info.authenticators(parse_result.hostname)
|
|
||||||
if auth:
|
|
||||||
username, _account, password = auth
|
|
||||||
else:
|
|
||||||
print('No credentials found for %s in .netrc'
|
|
||||||
% parse_result.hostname, file=sys.stderr)
|
|
||||||
except netrc.NetrcParseError as e:
|
|
||||||
print('Error parsing .netrc file: %s' % e, file=sys.stderr)
|
|
||||||
|
|
||||||
if (username and password):
|
|
||||||
manifest_server = manifest_server.replace('://', '://%s:%s@' %
|
|
||||||
(username, password),
|
|
||||||
1)
|
|
||||||
|
|
||||||
transport = PersistentTransport(manifest_server)
|
|
||||||
if manifest_server.startswith('persistent-'):
|
|
||||||
manifest_server = manifest_server[len('persistent-'):]
|
|
||||||
|
|
||||||
try:
|
|
||||||
server = xmlrpc.client.Server(manifest_server, transport=transport)
|
|
||||||
if opt.smart_sync:
|
|
||||||
p = self.manifest.manifestProject
|
|
||||||
b = p.GetBranch(p.CurrentBranch)
|
|
||||||
branch = b.merge
|
|
||||||
if branch.startswith(R_HEADS):
|
|
||||||
branch = branch[len(R_HEADS):]
|
|
||||||
|
|
||||||
env = os.environ.copy()
|
|
||||||
if 'SYNC_TARGET' in env:
|
|
||||||
target = env['SYNC_TARGET']
|
|
||||||
[success, manifest_str] = server.GetApprovedManifest(branch, target)
|
|
||||||
elif 'TARGET_PRODUCT' in env and 'TARGET_BUILD_VARIANT' in env:
|
|
||||||
target = '%s-%s' % (env['TARGET_PRODUCT'],
|
|
||||||
env['TARGET_BUILD_VARIANT'])
|
|
||||||
[success, manifest_str] = server.GetApprovedManifest(branch, target)
|
|
||||||
else:
|
|
||||||
[success, manifest_str] = server.GetApprovedManifest(branch)
|
|
||||||
else:
|
|
||||||
assert(opt.smart_tag)
|
|
||||||
[success, manifest_str] = server.GetManifest(opt.smart_tag)
|
|
||||||
|
|
||||||
if success:
|
|
||||||
manifest_name = smart_sync_manifest_name
|
|
||||||
try:
|
|
||||||
f = open(smart_sync_manifest_path, 'w')
|
|
||||||
try:
|
|
||||||
f.write(manifest_str)
|
|
||||||
finally:
|
|
||||||
f.close()
|
|
||||||
except IOError as e:
|
|
||||||
print('error: cannot write manifest to %s:\n%s'
|
|
||||||
% (smart_sync_manifest_path, e),
|
|
||||||
file=sys.stderr)
|
|
||||||
sys.exit(1)
|
|
||||||
self._ReloadManifest(manifest_name)
|
|
||||||
else:
|
|
||||||
print('error: manifest server RPC call failed: %s' %
|
|
||||||
manifest_str, file=sys.stderr)
|
|
||||||
sys.exit(1)
|
|
||||||
except (socket.error, IOError, xmlrpc.client.Fault) as e:
|
|
||||||
print('error: cannot connect to manifest server %s:\n%s'
|
|
||||||
% (self.manifest.manifest_server, e), file=sys.stderr)
|
|
||||||
sys.exit(1)
|
|
||||||
except xmlrpc.client.ProtocolError as e:
|
|
||||||
print('error: cannot connect to manifest server %s:\n%d %s'
|
|
||||||
% (self.manifest.manifest_server, e.errcode, e.errmsg),
|
|
||||||
file=sys.stderr)
|
|
||||||
sys.exit(1)
|
|
||||||
else: # Not smart sync or smart tag mode
|
|
||||||
if os.path.isfile(smart_sync_manifest_path):
|
if os.path.isfile(smart_sync_manifest_path):
|
||||||
try:
|
try:
|
||||||
platform_utils.remove(smart_sync_manifest_path)
|
platform_utils.remove(smart_sync_manifest_path)
|
||||||
|
Reference in New Issue
Block a user