6 from subprocess
import Popen, PIPE, STDOUT
7 from fnmatch
import fnmatch
13 Simple wrapper to execute a command and return standard output and standard error. 15 d = {
"stdout": PIPE,
"stderr": PIPE}
17 cmd = [cmd] + list(args)
18 logging.debug(
"Execute command: %r %r",
" ".join(cmd), kwargs)
19 proc =
apply(Popen, (cmd, ), d)
20 return proc.communicate()
23 cmt =
lambda *args, **kwargs:
apply(command, (
"cmt", ) + args, kwargs)
24 cvs =
lambda *args, **kwargs:
apply(command, (
"cvs", ) + args, kwargs)
25 svn =
lambda *args, **kwargs:
apply(command, (
"svn", ) + args, kwargs)
30 Find the local packages the current one depends on (using 'cmt broadcast'). 31 Returns a list of pairs ("package name","path to the cmt directory"). 34 if not sys.platform.startswith(
"win"):
35 pkg_dirs =
"[\n" +
cmt(
"broadcast",
36 r'echo "(\"<package>\", \"$PWD\"),"')[0] +
']' 38 pkg_dirs =
"[\n" +
cmt(
40 r'echo ("<package>", r"%<package>root%\cmt"),')[0] +
']' 43 [l.strip()
for l
in pkg_dirs.splitlines()
if not l.startswith(
"#")])
49 Returns True if any of the specified glob patterns (list of strings) matched 50 the string 'filename'. 53 if fnmatch(filename, p):
54 logging.debug(
"Excluding file: %r", filename)
61 Replace the entries in files that correspond to directories with the list of 62 files in those directories. 65 lb = len(basepath) + 1
70 base = os.path.join(basepath, f)
71 if os.path.isdir(base):
72 for root, ds, fs
in os.walk(base):
74 newlist.append(os.path.join(root, ff)[lb:])
81 if os.path.isdir(os.path.join(cwd,
"CVS")):
82 return cvs(
"diff",
"-upN", cwd=cwd)
85 out, err =
svn(
"status", cwd=cwd)
87 newfiles = [l
for l
in out.splitlines()
if l.startswith(
"? ")]
88 out, err =
svn(
"diff", cwd=cwd)
90 out =
"\n".join(newfiles) +
"\n" + out
96 Return the patch data for a package. 98 rootdir = os.path.dirname(cmtdir)
102 l.split(
None, 1)[1]
for l
in out.splitlines()
if l.startswith(
"? ")
105 new_files = [f
for f
in new_files
if not matches(f, exclusions)]
108 logging.info(
"Added file %r", f)
112 out +=
"Index: %s\n" % f
113 out +=
"===================================================================\n" 114 out +=
command(
"diff",
"-upN",
"/dev/null", f, cwd=rootdir)[0]
117 l.split()[-1]
for l
in err.splitlines()
if "cannot find" in l
119 removed_files = [f
for f
in removed_files
if not matches(f, exclusions)]
121 for f
in removed_files:
122 logging.info(
"Removed file %r", f)
124 orig =
cvs(
"up",
"-p", f, cwd=rootdir)[0]
125 out +=
"diff -u -p -N %s\n" % os.path.basename(f)
126 out +=
"--- %s\t1 Jan 1970 00:00:00 -0000\n" % f
127 out +=
"+++ /dev/null\t1 Jan 1970 00:00:00 -0000\n" 128 lines = orig.splitlines()
129 out +=
"@@ -1,%d +0,0 @@\n" % len(lines)
133 rex = re.compile(
r"^(Index: |\? |\+\+\+ |--- (?!/dev/null))", re.MULTILINE)
134 out = rex.sub(
r"\1%s/" % name, out)
139 from optparse
import OptionParser
140 parser = OptionParser(
141 description=
"Produce a patch file from a CMT project. " 142 "The patch contains the changes with respect " 143 "to the CVS repository, including new files " 144 "that are present only locally. Run the script " 145 "from the cmt directory of a package.")
153 help=
"Pattern to exclude new files from the patch")
159 help=
"Name of the file to send the output to. Standard " 160 "output is used if not specified")
165 help=
"Print some progress information on standard error")
169 help=
"Print debug information on standard error")
170 parser.set_defaults(exclusions=[])
172 opts, args = parser.parse_args()
175 logging.basicConfig(level=logging.DEBUG)
177 logging.basicConfig(level=logging.INFO)
190 "cmt/install*.history",
199 "i686-slc[34567]-[ig]cc*",
200 "i686-slc[34567]-clang*",
201 "x86_64-slc[34567]-[ig]cc*",
202 "x86_64-slc[34567]-clang*",
205 if "CMTCONFIG" in os.environ:
206 opts.exclusions.append(os.environ[
"CMTCONFIG"])
209 if not (os.path.basename(os.getcwd()) ==
"cmt" 210 and os.path.exists(
"requirements")):
212 "This script must be executed from the cmt directory of a package." 221 for name, path
in pkgs:
223 logging.info(
"Processing %s from %s (%d/%d)", name,
224 os.path.dirname(path), count, num_pkgs)
225 patch +=
diff_pkg(name, path, opts.exclusions)
227 if sys.platform.startswith(
"win"):
229 patch = patch.replace(
"\r",
"")
232 logging.info(
"Writing patch file %r", opts.output)
233 open(opts.output,
"w").write(patch)
235 sys.stdout.write(patch)
239 if __name__ ==
"__main__":
def command(cmd, args, kwargs)
def expand_dirs(files, basepath="")
decltype(auto) constexpr apply(F &&f, Tuple &&t) noexcept(noexcept( detail::apply_impl(std::forward< F >(f), std::forward< Tuple >(t), std::make_index_sequence< std::tuple_size< std::remove_reference_t< Tuple >>::value >{})))
def revision_diff_cmd(cwd)
def matches(filename, patterns)
def diff_pkg(name, cmtdir, exclusions=[])