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(
"broadcast",
39 r'echo ("<package>", r"%<package>root%\cmt"),')[0] +
']' 42 [l.strip()
for l
in pkg_dirs.splitlines()
if not l.startswith(
"#")])
48 Returns True if any of the specified glob patterns (list of strings) matched 49 the string 'filename'. 52 if fnmatch(filename, p):
53 logging.debug(
"Excluding file: %r", filename)
60 Replace the entries in files that correspond to directories with the list of 61 files in those directories. 64 lb = len(basepath) + 1
69 base = os.path.join(basepath, f)
70 if os.path.isdir(base):
71 for root, ds, fs
in os.walk(base):
73 newlist.append(os.path.join(root, ff)[lb:])
80 if os.path.isdir(os.path.join(cwd,
"CVS")):
81 return cvs(
"diff",
"-upN", cwd=cwd)
84 out, err =
svn(
"status", cwd=cwd)
87 for l
in out.splitlines()
88 if l.startswith(
"? ")]
89 out, err =
svn(
"diff", cwd=cwd)
91 out =
"\n".join(newfiles) +
"\n" + out
97 Return the patch data for a package. 99 rootdir = os.path.dirname(cmtdir)
102 new_files = [l.split(
None, 1)[1]
103 for l
in out.splitlines()
104 if l.startswith(
"? ")]
111 logging.info(
"Added file %r", f)
115 out +=
"Index: %s\n" % f
116 out +=
"===================================================================\n" 117 out +=
command(
"diff",
"-upN",
"/dev/null", f,
120 removed_files = [l.split()[-1]
121 for l
in err.splitlines()
122 if "cannot find" in l]
124 for f
in removed_files
127 for f
in removed_files:
128 logging.info(
"Removed file %r", f)
130 orig =
cvs(
"up",
"-p", f,
132 out +=
"diff -u -p -N %s\n" % os.path.basename(f)
133 out +=
"--- %s\t1 Jan 1970 00:00:00 -0000\n" % f
134 out +=
"+++ /dev/null\t1 Jan 1970 00:00:00 -0000\n" 135 lines = orig.splitlines()
136 out +=
"@@ -1,%d +0,0 @@\n" % len(lines)
140 rex = re.compile(
r"^(Index: |\? |\+\+\+ |--- (?!/dev/null))", re.MULTILINE)
141 out = rex.sub(
r"\1%s/" % name, out)
146 from optparse
import OptionParser
147 parser = OptionParser(description=
"Produce a patch file from a CMT project. " 148 "The patch contains the changes with respect " 149 "to the CVS repository, including new files " 150 "that are present only locally. Run the script " 151 "from the cmt directory of a package.")
152 parser.add_option(
"-x",
"--exclude", action=
"append", type=
"string",
153 metavar=
"PATTERN", dest=
"exclusions",
154 help=
"Pattern to exclude new files from the patch")
155 parser.add_option(
"-o",
"--output", action=
"store", type=
"string",
156 help=
"Name of the file to send the output to. Standard " 157 "output is used if not specified")
158 parser.add_option(
"-v",
"--verbose", action=
"store_true",
159 help=
"Print some progress information on standard error")
160 parser.add_option(
"--debug", action=
"store_true",
161 help=
"Print debug information on standard error")
162 parser.set_defaults(exclusions=[])
164 opts, args = parser.parse_args()
167 logging.basicConfig(level=logging.DEBUG)
169 logging.basicConfig(level=logging.INFO)
172 opts.exclusions += [
"*.py[co]",
181 "cmt/install*.history",
190 "i686-slc[34567]-[ig]cc*",
191 "i686-slc[34567]-clang*",
192 "x86_64-slc[34567]-[ig]cc*",
193 "x86_64-slc[34567]-clang*",
196 if "CMTCONFIG" in os.environ:
197 opts.exclusions.append(os.environ[
"CMTCONFIG"])
200 if not (os.path.basename(os.getcwd()) ==
"cmt" and os.path.exists(
"requirements")):
202 "This script must be executed from the cmt directory of a package.")
210 for name, path
in pkgs:
212 logging.info(
"Processing %s from %s (%d/%d)",
213 name, os.path.dirname(path), count, num_pkgs)
214 patch +=
diff_pkg(name, path, opts.exclusions)
216 if sys.platform.startswith(
"win"):
218 patch = patch.replace(
"\r",
"")
221 logging.info(
"Writing patch file %r", opts.output)
222 open(opts.output,
"w").
write(patch)
224 sys.stdout.write(patch)
228 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=[])