Mercurial > hg > config
annotate python/hg-merge.py @ 207:7bad4b7281f2
add a file to merge hg repositories
author | Jeff Hammel <jhammel@mozilla.com> |
---|---|
date | Mon, 13 Feb 2012 16:22:59 -0800 |
parents | |
children |
rev | line source |
---|---|
207
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
1 #!/usr/bin/env python |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
2 |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
3 """ |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
4 merge mercurial repositories |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
5 |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
6 Example: |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
7 hg-merge.py --master http://hg.mozilla.org/build/talos http://hg.mozilla.org/build/pageloader#talos/pageloader |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
8 """ |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
9 |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
10 import optparse |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
11 import os |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
12 import shutil |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
13 import subprocess |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
14 import sys |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
15 import tempfile |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
16 import urlparse |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
17 try: |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
18 from subprocess import check_call as call |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
19 except: |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
20 from subprocess import call |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
21 |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
22 def url2filename(url): |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
23 """gets a filename from a url""" |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
24 scheme, netloc, path, query, fragment = urlparse.urlsplit(url) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
25 path = path.rstrip('/') |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
26 assert path and '/' in path |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
27 return path.split('/')[-1] |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
28 |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
29 def manifest(hgrepo): |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
30 """manifest of a local hg repository""" |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
31 process = subprocess.Popen(['hg', 'manifest'], cwd=hgrepo, stdout=subprocess.PIPE) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
32 stdout, stderr = process.communicate() |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
33 assert not process.returncode |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
34 manifest = stdout.strip().splitlines() |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
35 return set(manifest) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
36 |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
37 def merge(hgroot, repo, subpath=None): |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
38 """merge repo to hgroot at subpath (None for repository root)""" |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
39 |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
40 # get a manifest of the current repository |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
41 root_manifest = manifest(hgroot) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
42 toplevel_contents = os.listdir(hgroot) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
43 |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
44 # staging area |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
45 tempdir = tempfile.mkdtemp() |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
46 fd, tmpfile = tempfile.mkstemp() |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
47 os.close(fd) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
48 |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
49 exception = None |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
50 try: |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
51 |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
52 # clone the repository to be merged in |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
53 call(['hg', 'clone', repo, tempdir]) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
54 |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
55 # check manifest for conflicts |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
56 repo_manifest = manifest(tempdir) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
57 assert repo_manifest, "Empty repository: %s" % repo |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
58 intersection = root_manifest.intersection(repo_manifest) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
59 assert not intersection, "Overlap between %s and %s: %s" % (hgroot, repo, intersection) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
60 |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
61 # create a bundle |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
62 call(['hg', 'bundle', tmpfile, '--all'], cwd=tempdir) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
63 |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
64 # apply the bundle |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
65 call(['hg', 'unbundle', tmpfile], cwd=hgroot) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
66 call(['hg', 'merge'], cwd=hgroot) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
67 |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
68 if subpath: |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
69 # move the new files to their new locations |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
70 for item in repo_manifest: |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
71 path = os.path.join(subpath, item) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
72 fullpath = os.path.join(hgroot, path) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
73 assert not os.path.exists(fullpath), "%s already exists" % fullpath |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
74 subdirectory = os.path.dirname(fullpath) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
75 if not os.path.exists(subdirectory): |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
76 os.makedirs(subdirectory) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
77 call(['hg', 'mv', item, path], cwd=hgroot) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
78 call(['hg', 'commit', '-m', 'merge %s to %s' % (repo, subpath)], cwd=hgroot) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
79 else: |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
80 call(['hg', 'commit', '-m', 'merge in %s' % repo], cwd=hgroot) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
81 |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
82 except Exception, exception: |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
83 pass # reraise on cleanup |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
84 |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
85 # cleanup |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
86 shutil.rmtree(tempdir) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
87 os.remove(tmpfile) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
88 if exception is not None: |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
89 raise exception |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
90 |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
91 def main(args=sys.argv[1:]): |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
92 |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
93 # parse command line options |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
94 usage = "%prog [options] http://hg.example.com/repository/path#destination/path [...]" |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
95 parser = optparse.OptionParser(usage=usage, description=__doc__) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
96 parser.add_option('-m', '--master', dest='master', |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
97 help="use this as the master repository (new clone, otherwise use CWD)") |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
98 options, args = parser.parse_args(args) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
99 if not args: |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
100 parser.print_help() |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
101 parser.exit() |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
102 |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
103 if options.master: |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
104 # clone the new repository |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
105 directory = url2filename(options.master) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
106 if os.path.exists(directory): |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
107 shutil.rmtree(directory) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
108 call(['hg', 'clone', options.master]) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
109 hgroot = os.path.join(os.getcwd(), directory) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
110 else: |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
111 # get the root of the repository |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
112 process = subprocess.Popen(['hg', 'root'], stdout=subprocess.PIPE) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
113 hgroot, stderr = process.communicate() |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
114 hgroot = hgroot.strip() |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
115 if process.returncode: |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
116 sys.exit(1) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
117 assert os.path.exists(hgroot) and os.path.isdir(hgroot), "%s not found" % hgroot |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
118 |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
119 # get the other repos to add |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
120 for repo in args: |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
121 subpath = None |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
122 if '#' in repo: |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
123 repo, subpath = repo.rsplit('#', 1) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
124 merge(hgroot, repo, subpath) |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
125 |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
126 if __name__ == '__main__': |
7bad4b7281f2
add a file to merge hg repositories
Jeff Hammel <jhammel@mozilla.com>
parents:
diff
changeset
|
127 main() |