Index: ChangeLog from Akim Demaille akim@epita.fr
Rationalize the invocation of traditional Unix commands. It should be possible to redo what prcs2svn did by grepping "prcs2svn $". The test suite fails, I have no idea why...
* prcs2svn/prcs2svn.py (error): Fix >> use. (trace): New. (xsystem, xtee): Use it. (xcopy, xrm, xpopen, xcat, xchdir, xmkdir, xmove): New. Use them where ever their low level implementation was used. * prcs2svn/prcs2svn.py (Svn.changes_apply_files_rename): Don't rm files you just mv'ed.
Index: prcs2svn/prcs2svn.py --- prcs2svn/prcs2svn.py (revision 89) +++ prcs2svn/prcs2svn.py (working copy) @@ -80,7 +80,7 @@ sys.stdout.flush()
def error(status, msg): - print "prcs2svn: ***" + msg >>sys.stderr + print >> sys.stderr, "prcs2svn:", msg sys.stderr.flush () if status: sys.exit (status) @@ -95,14 +95,59 @@ ## ------------------------------------- ## Misc.
-## Print cmd on debug stream and execute it through os.system. +def trace (cmd): + "Announce we are about to run the cmd." + debug ("prcs2svn $ " + cmd) + + def xsystem(cmd, ignErr=False): - debug ("os.system("" + cmd + "")") + "Print cmd on debug stream and execute it through os.system." + + trace (cmd) if infos.trace_level < 2: cmd += "> /dev/null 2> /dev/null" status = os.system(cmd) if status: + error (int (ignErr), + cmd + ": returned an error (" + status.__str__ () + ")") + +def xpopen(cmd, ignErr=False): + "Verbose and error proof wrapper around os.popen." + + trace (cmd) + if infos.trace_level < 2: + cmd += "> /dev/null 2> /dev/null" + return os.popen(cmd) + +def xcat (cmd, ignErr=False): + "Return the content of running cmd." + pipe = xpopen(cmd, ignErr) + res = "" + for line in pipe: + sys.__stdout__.write(line) + res += line + # What is this supposed to return? There is nothing in the doc! --akim + status = pipe.close () + if status: error (int (ignErr), cmd + ": returned an error (" + status + ")") + return res + +def xtee (cmd, ignErr=False): + "Print cmd on debug stream, tee it, return the number of printed chars." + return len (xcat (cmd, ignErr)) + + +def xchdir (dir): + trace ("cd " + dir) + os.chdir (dir) + +def xmkdir (dir): + trace ("mkdir " + dir) + os.mkdir (dir) + +def xrm (dir): + trace ("rm -rf " + dir) + shutil.rmtree (dir, True)
## Add quote for filename, directory's name, ... def quote(path): @@ -114,28 +159,14 @@ r = string.replace(r, "\\", "\") return r
-## Print cmd on debug stream, tee it, return the number of printed chars. -def xtee (cmd, ignErr=False): - debug ("os.popen("" + cmd + "")") - pipe = os.popen(cmd) - res = 0 - for line in pipe: - res += len(line) - sys.__stdout__.write(line) - # What is this supposed to return? There is nothing in the doc! --akim - status = pipe.close () - if status: - error (int (ignErr), cmd + ": returned an error (" + status + ")") - return res - ## Print copy on debug stream and copy a file. -def copy(src, dst): - debug("cp --force " + src + " " + dst) +def xcopy(src, dst): + trace ("cp --force " + src + " " + dst) shutil.copy(src, dst)
## Print move on debug stream and move a file. -def move(src, dst): - debug("mv --force " + src + " " + dst) +def xmove(src, dst): + trace ("mv --force " + src + " " + dst) dst_dirname = os.path.dirname(dst) if (len(dst_dirname) > 0 and (not os.path.exists(dst_dirname))): os.makedirs(dst_dirname) @@ -331,7 +362,7 @@ return self.prcs_project + ".prj"
def __del__(self): - shutil.rmtree(self.tmp, True) + xrm(self.tmp)
# Remove keyword to compare repositories. def keywords_clean(self, line): @@ -345,7 +376,7 @@
# Compare two directories. def compare(self, path_svn, path_prcs): - os.chdir(self.tmp) + xchdir(self.tmp) dircmp = dirCmp() result = dircmp.cmp(os.path.join(os.getcwd(), path_prcs), os.path.join(os.getcwd(), path_svn), @@ -354,20 +385,20 @@ if not result: dircmp.report() raise RepositoriesDifferent() - os.chdir(self.tmp) + xchdir(self.tmp)
# Compare trunk of the project. def cmp_trunk(self, prcs_revision=""): info("> Comparing trunk.") if prcs_revision != "": prcs_revision = " -r " + prcs_revision + " " - os.mkdir(self.prcs_project + "_prcs") - os.chdir(self.prcs_project + "_prcs") + xmkdir(self.prcs_project + "_prcs") + xchdir(self.prcs_project + "_prcs") xsystem("prcs checkout -f " + prcs_revision + self.prjname ()) # PRCS sometimes lacks a \n after the messages emitted by checkout -f. if 2 <= infos.trace_level: print - svn_repo = os.path.join(self.svn_project, os.path.join(infos.subdir, "trunk")) + svn_repo = os.path.join(self.svn_project, infos.subdir, "trunk") if len(infos.prcs_projects) > 1: svn_repo = os.path.join(svn_repo, self.prcs_project) self.compare(svn_repo, self.prcs_project + "_prcs") @@ -383,11 +414,11 @@
# Compare a branch of a project. def cmp_branch(self, prcs_revision): - os.mkdir(self.prcs_project + prcs_revision + "_prcs") - os.chdir(self.prcs_project + prcs_revision + "_prcs") + xmkdir(self.prcs_project + prcs_revision + "_prcs") + xchdir(self.prcs_project + prcs_revision + "_prcs") xsystem("prcs checkout -f -r" + prcs_revision + " " + self.prjname ()) svn_repo = self.svn_project + "/" + os.path.join(infos.subdir, "branches") - svn_repo = os.path.join(self.svn_project, os.path.join(infos.subdir, "branches")) + svn_repo = os.path.join(self.svn_project, infos.subdir, "branches") if len(infos.prcs_projects) > 1: svn_repo = os.path.join(svn_repo, self.prcs_project) svn_repo = os.path.join(svn_repo, prcs_revision.split(".")[0]) @@ -399,7 +430,7 @@ self.prcs_project = prcs_project self.svn_project = svn_project self.tmp = tempfile.mkdtemp(".diff", "prcs2svn") - os.chdir(self.tmp) + xchdir(self.tmp) if svn_revision != "": svn_revision = " -r " + svn_revision + " " xsystem("svn checkout " + svn_revision + svn_repo) @@ -489,7 +520,7 @@
# Rewrite each file exchanging prcs and svn keywords. def change_keywords_(self, path): - os.chdir(path) + xchdir(path) files = glob.glob(path + os.sep + "*") for f in files: st = os.stat(f) @@ -499,10 +530,10 @@ tmp = tempfile.mkdtemp(".keywords", "prcs2svn") atime = st[stat.ST_ATIME] mtime = st[stat.ST_MTIME] - shutil.copy(f, tmp) + xcopy(f, tmp) fd_tmp = open(tmp + os.sep + os.path.basename(f), "r") # FIXME: in python, we should have that. - os.system("chmod +w " + f) + xsystem("chmod +w " + f) fd_f = open(f, "w+") for l in fd_tmp: l = self.change_keywords_line(f, l) @@ -510,13 +541,13 @@ fd_tmp.close() fd_f.close() os.utime(f, (atime, mtime)) - shutil.rmtree(tmp) + xrm(tmp)
# Just a garbage function because change_keywords_ is recursive. def change_keywords(self, path): pwd = os.getcwd() self.change_keywords_(path) - os.chdir(pwd) + xchdir(pwd)
# Commit Subversion changes. @@ -550,7 +581,7 @@ # Refresh local copy (should be useless, may be a bug of svn). if update: xsystem("svn update") - os.remove(log_path) + xrm(log_path)
# Replace symbolic links with the files they point to. def changes_apply_links_replace(self, diffs): @@ -564,7 +595,7 @@ if os.path.dirname(l): ref = os.path.normpath(os.path.dirname(l) + "/" + ref) if os.path.isfile(ref): - copy(ref, l) + xcopy(ref, l) else: f = file(l, "w") f.write("Symbolic link to: " + ref + "\n") @@ -614,10 +645,10 @@ # Destination exists: PRCS renamed then added an homonym file. bak_fd, bak_path = tempfile.mkstemp(".bak", "prcs2svn") os.close(bak_fd) - move(diffs.renamed[i][0], bak_path) + xmove(diffs.renamed[i][0], bak_path) backup[diffs.renamed[i][0]] = bak_path # FIXED: was copy(). - move(diffs.renamed[i][1], diffs.renamed[i][0]) + xmove(diffs.renamed[i][1], diffs.renamed[i][0]) # Do Subversion rename. for r in diffs.renamed: # Delete files that may be overwritten (--force is a joke). @@ -636,12 +667,11 @@ break if must_delete: if backup.has_key(r[0]): - copy(backup[r[0]], r[0]) - xtee("svn delete --force " + quote(r[0])) + xcopy(backup[r[0]], r[0]) + xsystem("svn delete --force " + quote(r[0])) # Restore backuped files. for b in backup.keys(): - move(backup[b], b) - shutil.rmtree(backup[b], True) + xmove(backup[b], b)
# Add files. # Hard to explain, see movement of "Makefile.am" in oln 0_7_reconf.1.prj. @@ -670,10 +700,10 @@ ".svn"): args = args + " " + quote(e) if infos.action and len(args) > 0: - xtee("svn delete --force " + args) + xsystem ("svn delete --force " + args)
# Apply changes to Subversion repository. - # Be careful: order is very important ! + # Be careful: the order is very important! def changes_apply(self, diffs, checkin_login, version_log, checkin_time): self.changes_apply_links_replace(diffs) self.changes_apply_directories_add(diffs) @@ -720,7 +750,7 @@ info("> Get versions of the project named `" + self.name + "'") re_DELETED = re.compile(".*DELETED*$") prcs_versions = [] - pipe = os.popen("prcs info --plain-format -f --sort=date " +\ + pipe = xpopen("prcs info --plain-format -f --sort=date " +\ self.prjname ()) for line in pipe: prcs_desc = line.split(" ") @@ -781,7 +811,7 @@ re_DELETED = re.compile(".*DELETED*$") prcs_versions = [] # FIXME: should use python features instead of sed. - prcs_info = os.popen("prcs info --plain-format -f --sort=date " +\ + prcs_info = xpopen("prcs info --plain-format -f --sort=date " +\ project + ".prj | sed -ne "1p;$p"" +\ " | sed -e "s/.*, (.*) +[0-9]* by .*/\1/"" ) f_date = "" @@ -812,13 +842,13 @@ self.topdir = tempfile.mkdtemp(".migrate", "prcs2svn") self.workdir = os.path.join(self.topdir, infos.subdir) debug("> Create working directory: " + self.topdir) - os.chdir(self.topdir) + xchdir(self.topdir) self.svn.repository_init(self.topdir)
# Clean workspace. def convert_desinit(self): self.svn.repository_desinit() - shutil.rmtree(self.topdir, True) + xrm(self.topdir)
# Convert prcs -> svn. def convert(self): @@ -833,7 +863,7 @@
# Convert a project. def convert_project(self, project): - os.chdir(self.topdir) + xchdir(self.topdir) # if several prcs projects -> # trunk/proj1, trunk/proj2, branches/proj1, ... # else trunk/ and branches/ @@ -910,7 +940,7 @@ self.svn.branch = svn_new_branch if self.svn.branches.has_key(self.svn.branch): info(" > Return to branch: " + self.svn.branch) - os.chdir(self.workdir + os.sep + self.svn.branch) + xchdir(self.workdir + os.sep + self.svn.branch) # FIXME: may be a comparison with svn branches. if prcsProject.prj.parent_version.major != \ prcsProject.prj.version.major: @@ -920,7 +950,7 @@ else: if prcsProject.prj.parent_version.major == "-*-": info(" > Initial revision") - os.chdir(self.workdir + os.sep + self.svn.branch) + xchdir(self.workdir + os.sep + self.svn.branch) xsystem("svn checkout " + self.svn.repository + " " +\ quote(self.workdir)) else: @@ -929,7 +959,7 @@ self.prcs_to_svn[prcsProject.prj.parent_version.name()] xsystem("svn copy -r " + str(svn_parent[1]) + \ " " + svn_parent[0] + " " + self.svn.branch) - os.chdir(self.workdir + os.sep + self.svn.branch) + xchdir(self.workdir + os.sep + self.svn.branch) self.svn.changes_commit("prcs2svn", "Make a new branch.", prcsProject.create_date) self.svn.branches[self.svn.branch] = [self.svn.revision, @@ -937,7 +967,7 @@
# Merge with parents. def merge(self, prcsProject): - os.chdir(self.workdir + os.sep + self.svn.branch) + xchdir(self.workdir + os.sep + self.svn.branch) prcs_merged_parents = [] for prcs_merge_parent in prcsProject.prj.merge_parents: # Skip already merged parents (complete/incomplete repetition). @@ -979,7 +1009,7 @@ # Synchronize PRCS and Subversion repositories def synchronize(self, prcsProject): info(" > Checkout whole revision from PRCS repository") - os.chdir(self.workdir + os.sep + self.svn.branch) + xchdir(self.workdir + os.sep + self.svn.branch) xsystem("prcs checkout -f -r " + prcsProject.prj.version.name() + \ " " + prcsProject.name + ".prj") # Make a diff between previous and current prj's file. @@ -994,7 +1024,7 @@ # Convert a revision of a project. def convert_project_of_revision(self, prcsProject, prcs_version): info("> Consider PRCS revision " + prcs_version.name()) - os.chdir(self.workdir) + xchdir(self.workdir) xsystem("prcs checkout -f -r " + prcs_version.name() + " " + \ prcsProject.name + ".prj " + prcsProject.name + ".prj") prcsProject.parse() @@ -1043,7 +1073,7 @@ else: globs_local_bypath[path] = [g] for path in globs_local_bypath.keys(): - shutil.copy(".svnignore", ".svnignore_local") + xcopy(".svnignore", ".svnignore_local") fd = open(".svnignore_local", "a") for g in globs_local_bypath[path]: fd.write(g + "\n") @@ -1083,7 +1113,7 @@
def desinit_repositories(self): if infos.copy_prcs: - shutil.rmtree(os.environ["PRCS_REPOSITORY"], True) + xrm(os.environ["PRCS_REPOSITORY"])
# Make the 'svnadmin create'. def create_svn_repository(self): @@ -1102,14 +1132,14 @@ info("> Copy prcs repository") tmp = tempfile.mkdtemp(".prcs", "prcs2svn") pwd = os.getcwd() - os.chdir(tmp) + xchdir(tmp) for proj in infos.prcs_projects: xsystem("prcs package -f " + proj + " " + proj + ".pkg") os.environ["PRCS_REPOSITORY"] = tmp for proj in infos.prcs_projects: xsystem("prcs unpackage -f ./" + proj + ".pkg") - os.remove(proj + ".pkg") - os.chdir(pwd) + xrm(proj + ".pkg") + xchdir(pwd)
# Copy the svn repository to work on a copy. def copy_svn_repository(self): @@ -1118,9 +1148,9 @@ tmp = tempfile.mkdtemp(".svn", "prcs2svn") info("> Copy svn repository to " + tmp) new_repo = os.path.join(tmp, infos.svn_project) - os.mkdir(new_repo) + xmkdir(new_repo) if infos.svn_root[0] != "f": - shutil.rmtree(tmp, True) + xrm (tmp) raise SvnCopyForbidden() xsystem("svnadmin hotcopy " + os.path.join(infos.svn_root[7:], infos.svn_project) + \ @@ -1128,11 +1158,9 @@ infos.svn_root = urlparse.urljoin("file://", urllib.pathname2url(tmp))
def initialize_svn_revision(self): - pipe = os.popen("svnlook youngest " + os.path.join(infos.svn_root[7:], - infos.svn_project)) - for line in pipe: - infos.initial_svn_revision = int(line) - pipe.close() + infos.initial_svn_revision = \ + int (xcat("svnlook youngest " + os.path.join(infos.svn_root[7:], + infos.svn_project)))
def test_environment(self): if not os.environ.has_key('LANG') or os.environ['LANG'] == 'C':