16 from subprocess
import Popen, PIPE, STDOUT
17 from fnmatch
import fnmatch
23 Simple wrapper to execute a command and return standard output and standard error.
25 d = {
"stdout": PIPE,
"stderr": PIPE}
27 cmd = [cmd] + list(args)
28 logging.debug(
"Execute command: %r %r",
" ".join(cmd), kwargs)
29 proc = Popen(cmd, **d)
30 return proc.communicate()
33 cmt =
lambda *args, **kwargs:
command(
"cmt", *args, **kwargs)
34 cvs =
lambda *args, **kwargs:
command(
"cvs", *args, **kwargs)
35 svn =
lambda *args, **kwargs:
command(
"svn", *args, **kwargs)
40 Find the local packages the current one depends on (using 'cmt broadcast').
41 Returns a list of pairs ("package name","path to the cmt directory").
44 if not sys.platform.startswith(
"win"):
45 pkg_dirs =
"[\n" +
cmt(
"broadcast",
46 r'echo "(\"<package>\", \"$PWD\"),"')[0] +
']'
48 pkg_dirs =
"[\n" +
cmt(
50 r'echo ("<package>", r"%<package>root%\cmt"),')[0] +
']'
53 [l.strip()
for l
in pkg_dirs.splitlines()
if not l.startswith(
"#")])
59 Returns True if any of the specified glob patterns (list of strings) matched
60 the string 'filename'.
63 if fnmatch(filename, p):
64 logging.debug(
"Excluding file: %r", filename)
71 Replace the entries in files that correspond to directories with the list of
72 files in those directories.
75 lb = len(basepath) + 1
80 base = os.path.join(basepath, f)
81 if os.path.isdir(base):
82 for root, ds, fs
in os.walk(base):
84 newlist.append(os.path.join(root, ff)[lb:])
91 if os.path.isdir(os.path.join(cwd,
"CVS")):
92 return cvs(
"diff",
"-upN", cwd=cwd)
95 out, err =
svn(
"status", cwd=cwd)
97 newfiles = [l
for l
in out.splitlines()
if l.startswith(
"? ")]
98 out, err =
svn(
"diff", cwd=cwd)
100 out =
"\n".join(newfiles) +
"\n" + out
106 Return the patch data for a package.
108 rootdir = os.path.dirname(cmtdir)
112 l.split(
None, 1)[1]
for l
in out.splitlines()
if l.startswith(
"? ")
115 new_files = [f
for f
in new_files
if not matches(f, exclusions)]
118 logging.info(
"Added file %r", f)
122 out +=
"Index: %s\n" % f
123 out +=
"===================================================================\n"
124 out +=
command(
"diff",
"-upN",
"/dev/null", f, cwd=rootdir)[0]
127 l.split()[-1]
for l
in err.splitlines()
if "cannot find" in l
129 removed_files = [f
for f
in removed_files
if not matches(f, exclusions)]
131 for f
in removed_files:
132 logging.info(
"Removed file %r", f)
134 orig =
cvs(
"up",
"-p", f, cwd=rootdir)[0]
135 out +=
"diff -u -p -N %s\n" % os.path.basename(f)
136 out +=
"--- %s\t1 Jan 1970 00:00:00 -0000\n" % f
137 out +=
"+++ /dev/null\t1 Jan 1970 00:00:00 -0000\n"
138 lines = orig.splitlines()
139 out +=
"@@ -1,%d +0,0 @@\n" % len(lines)
143 rex = re.compile(
r"^(Index: |\? |\+\+\+ |--- (?!/dev/null))", re.MULTILINE)
144 out = rex.sub(
r"\1%s/" % name, out)
149 from optparse
import OptionParser
150 parser = OptionParser(
151 description=
"Produce a patch file from a CMT project. "
152 "The patch contains the changes with respect "
153 "to the CVS repository, including new files "
154 "that are present only locally. Run the script "
155 "from the cmt directory of a package.")
163 help=
"Pattern to exclude new files from the patch")
169 help=
"Name of the file to send the output to. Standard "
170 "output is used if not specified")
175 help=
"Print some progress information on standard error")
179 help=
"Print debug information on standard error")
180 parser.set_defaults(exclusions=[])
182 opts, args = parser.parse_args()
185 logging.basicConfig(level=logging.DEBUG)
187 logging.basicConfig(level=logging.INFO)
200 "cmt/install*.history",
209 "i686-slc[34567]-[ig]cc*",
210 "i686-slc[34567]-clang*",
211 "x86_64-slc[34567]-[ig]cc*",
212 "x86_64-slc[34567]-clang*",
215 if "CMTCONFIG" in os.environ:
216 opts.exclusions.append(os.environ[
"CMTCONFIG"])
219 if not (os.path.basename(os.getcwd()) ==
"cmt"
220 and os.path.exists(
"requirements")):
222 "This script must be executed from the cmt directory of a package."
231 for name, path
in pkgs:
233 logging.info(
"Processing %s from %s (%d/%d)", name,
234 os.path.dirname(path), count, num_pkgs)
235 patch +=
diff_pkg(name, path, opts.exclusions)
237 if sys.platform.startswith(
"win"):
239 patch = patch.replace(
"\r",
"")
242 logging.info(
"Writing patch file %r", opts.output)
243 open(opts.output,
"w").write(patch)
245 sys.stdout.write(patch)
249 if __name__ ==
"__main__":