annotate python/hg-merge.py @ 386:bea5f2fe4ea4

it works even more!
author Jeff Hammel <jhammel@mozilla.com>
date Fri, 26 Jul 2013 14:58:18 -0700
parents 7bad4b7281f2
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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()