in tools/client-side/svn-vendor.py [0:0]
def do_apply(self, arg):
'''
apply : Perform copies/renames; then copy imported sources into
the working copy. Modifies working copy. Exits after
completion.
'''
self.info(1, "Copying imported sources into working copy...")
# Perform the recorded copies/moves/removals
self.info(2, " Preparatory operations (copies/renames/removals)")
to_be_diffed = []
for o in self.prepare_ops:
op = o[0]
if op == "mv":
self.run_svn(["mv", "--parents", o[1], o[2]])
to_be_diffed.append(o[2])
elif op == "cp":
self.run_svn(["cp", "--parents", o[1], o[2]])
to_be_diffed.append(o[2])
elif op == "rm":
# --force, as the removed path is likely created as a result
# of previous copy/rename
self.run_svn(["rm", "--force", o[1]])
dirs_added = []
dirs_removed = []
files_added = []
files_removed = []
files_set_exec = []
files_clear_exec = []
self.info(2, " Creating dirs and copying files...")
def copyfile_helper(i, nk_wc):
'''Helper: copy a file and optionally, transfer permissions.'''
f = os.path.join(self.importdir, i)
t = os.path.join(self.wcdir, i)
shutil.copyfile(f, t)
# If exec-permission is 'clear', we don't need to do anything:
# shutil.copyfile will create the file as non-executable.
if self.config.get('exec-permission') == 'preserve':
# If the file is new, just copying the mode is enough:
# svn will set the svn:executable upon adding it.
if nk_wc == "F":
# Existing file, check what the setting shall be
if os.access(f, os.X_OK) and not os.access(t, os.X_OK):
files_set_exec.append(i)
elif not os.access(f, os.X_OK) and os.access(t, os.X_OK):
files_clear_exec.append(i)
shutil.copymode(f, t)
for i in sorted(self.items.keys()):
e = self.items[i]
nk_wc = e.state[S_WC]
nk_im = e.state[S_IM]
flg = None
if nk_wc == "-":
# Absent in working copy
if nk_im == "D":
# Directory added
os.mkdir(os.path.join(self.wcdir, i))
dirs_added.append(i)
flg = "(added dir)"
elif nk_im == "F":
# New file added
copyfile_helper(i, nk_wc);
files_added.append(i)
flg = "(added file)"
elif nk_im == "L":
tim = os.readlink(os.path.join(self.importdir, i))
os.symlink(tim, os.path.join(self.wcdir, i))
files_added.append(i)
flg = "(added symlink)"
else:
# Not in imported sources, not in WC (moved
# away/removed) - nothing to do
pass
elif nk_wc == "L":
# Symbolic link in a working copy
if nk_im == "L":
# Symbolic link in both. If the same target, do nothing. Otherwise,
# replace.
twc = os.readlink(os.path.join(self.wcdir, i))
tim = os.readlink(os.path.join(self.importdir, i))
if tim != twc:
self.run_svn(["rm", "--force", i])
os.symlink(tim, os.path.join(self.wcdir, i))
files_added.append(i)
flg = "(replaced symlink)"
elif nk_im == "D":
# Was a symlink, now a directory. Replace.
self.run_svn(["rm", "--force", i])
os.mkdir(os.path.join(self.wcdir, i))
dirs_added.append(i)
flg = "(replaced symlink with dir)"
elif nk_im == "F":
# Symlink replaced with file.
self.run_svn(["rm", "--force", i])
copyfile_helper(i, nk_wc);
files_added.append(i)
flg = "(replaced symlink with file)"
else:
# Was a symlink, removed
files_removed.append(i)
flg = "(removed symlink)"
elif nk_wc == "F":
# File in a working copy
if nk_im == "D":
# File replaced with a directory. See comment above.
self.run_svn(["rm", "--force", i])
os.mkdir(os.path.join(self.wcdir, i))
dirs_added.append(i)
flg = "(replaced file with dir)"
elif nk_im == "F":
# Was a file, is a file - just copy contents
copyfile_helper(i, nk_wc);
flg = "(copied)"
elif nk_im == "L":
# Was a file, now a symlink. Replace.
self.run_svn(["rm", "--force", i])
tim = os.readlink(os.path.join(self.importdir, i))
os.symlink(tim, os.path.join(self.wcdir, i))
files_added.append(i)
flg = "(replaced file with symlink)"
else:
# Was a file, removed
files_removed.append(i)
flg = "(removed file)"
elif nk_wc == "D":
# Directory in a working copy
if nk_im == "D":
# Was a directory, is a directory - nothing to do
pass
elif nk_im == "F":
# Directory replaced with file. Need to remove dir
# immediately, as bulk removals/additions assume new files
# and dirs already in place. Also, removing a directory
# removes all its descendants - mark them as removed.
self.run_svn(["rm", "--force", i])
self.items.wc_remove(i)
copyfile_helper(i, nk_wc);
files_added.append(i)
flg = "(replaced dir with file)"
elif nk_im == "L":
# Was a directory, now a symlink. Replace.
self.run_svn(["rm", "--force", i])
self.items.wc_remove(i)
tim = os.readlink(os.path.join(self.importdir, i))
os.symlink(tim, os.path.join(self.wcdir, i))
files_added.append(i)
flg = "(replaced dir with symlink)"
else:
# Directory removed
dirs_removed.append(i)
flg = "(removed dir)"
if flg is not None:
self.info(4, " %s %s %s" % (e.status(), i, flg))
# Filter files/directories removed as a part of parent directory
files_removed = list(filter(lambda x: os.path.dirname(x) not in
dirs_removed, files_removed))
dirs_removed = list(filter(lambda x: os.path.dirname(x) not in
dirs_removed, dirs_removed))
files_added = list(filter(lambda x: os.path.dirname(x) not in
dirs_added, files_added))
dirs_added = list(filter(lambda x: os.path.dirname(x) not in
dirs_added, dirs_added))
self.info(2, " Running SVN add/rm/propset/propdel commands");
if len(dirs_added):
self.run_svn(["add"], dirs_added)
if len(files_added):
self.run_svn(["add"], files_added)
if len(dirs_removed):
self.run_svn(["rm"], dirs_removed)
if len(files_removed):
self.run_svn(["rm"], files_removed)
if len(files_set_exec):
self.run_svn(["propset", "svn:executable", "*"], files_set_exec)
if len(files_clear_exec):
self.run_svn(["propdel", "svn:executable"], files_clear_exec)
# Save the diff for the copied/moved items
diff_save = self.config.get('save-diff-copied')
if diff_save is not None:
self.info(2, " Saving 'svn diff' on copied files/dirs to `%s'" %
diff_save)
to_be_diffed = list(filter(lambda x: os.path.dirname(x) not in
to_be_diffed, to_be_diffed))
if len(to_be_diffed):
try:
rv, out = self.run_svn(["diff"], to_be_diffed)
except UnicodeDecodeError:
# Some binary files not marked with appropriate MIME type,
# or broken text files
rv, out = (True, "WARNING: diff contained binary files\n")
else:
rv, out = (True, "")
if rv:
f = open(diff_save, "w")
f.write(out)
f.close()
# Exiting, as the resulting working copy can no longer be used
# for move analysis
self.info(1, "Done. Exiting; please examine the working copy " +
"and commit.")
return True