Initial version of git-meld-commit
[git-meld-toys.git] / git-meld-commit
blobd58da13ae9f1ae8a23eff9cf2c8f0fa3d3498618
1 #!/usr/bin/env python
3 # Copyright (c) 2009 James Ascroft-Leigh
4 #
5 # Permission is hereby granted, free of charge, to any person
6 # obtaining a copy of this software and associated documentation
7 # files (the "Software"), to deal in the Software without
8 # restriction, including without limitation the rights to use,
9 # copy, modify, merge, publish, distribute, sublicense, and/or sell
10 # copies of the Software, and to permit persons to whom the
11 # Software is furnished to do so, subject to the following
12 # conditions:
14 # The above copyright notice and this permission notice shall be
15 # included in all copies or substantial portions of the Software.
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 # OTHER DEALINGS IN THE SOFTWARE.
26 """\
27 %prog [options] COMMIT
29 Shows the difference between the tree from COMMIT and the tree from
30 the parent of COMMIT. Invokes meld once for each parent.
31 """
33 # test cases:
34 # initial: (cd ~/git/nacl-build && ~/git/git-meld-toys/git-meld-commit \
35 # 8816f9f4ea28583d6dfa1fd96d3448977f6e2299)
36 # commit: (cd ~/git/nacl-build && ~/git/git-meld-toys/git-meld-commit \
37 # 707c127f621bf308f1e1a8526e79d5dc3888483c)
38 # merge: (cd ~/git/git && ~/git/git-meld-toys/git-meld-commit \
39 # 2d602e9179c7eb1a31a0abf41283c132e26a61af)
41 import optparse
42 import os
43 import subprocess
44 import shutil
45 import sys
46 import tempfile
49 def parse_argv(prog, argv):
50 parser = optparse.OptionParser(__doc__, prog=prog)
51 options, args = parser.parse_args(argv)
52 if len(args) == 0:
53 commit_spec = "HEAD"
54 else:
55 commit_spec = args.pop(0)
56 if len(args) > 0:
57 parser.error("Unexpected: %r" % (args,))
58 return (commit_spec,)
61 def dump_tree(tree_ish, destination):
62 os.mkdir(destination)
63 git = subprocess.Popen(["git", "archive", "--format=tar", tree_ish],
64 stdout=subprocess.PIPE)
65 tar = subprocess.Popen(["tar", "-C", destination, "-x"],
66 stdin=git.stdout)
67 tar.communicate()
68 git.communicate()
69 assert git.returncode == 0, git.returncode
70 assert tar.returncode == 0, tar.returncode
73 def meld(lhs, rhs):
74 work_dir = tempfile.mkdtemp(prefix="git-meld-commit-")
75 try:
76 lhs_path = os.path.join(work_dir, "lhs", lhs)
77 rhs_path = os.path.join(work_dir, "rhs", rhs)
78 os.mkdir(os.path.dirname(lhs_path))
79 os.mkdir(os.path.dirname(rhs_path))
80 dump_tree(lhs, lhs_path)
81 dump_tree(rhs, rhs_path)
82 subprocess.check_call(["meld", lhs_path, rhs_path])
83 finally:
84 shutil.rmtree(work_dir)
87 def main(commit_spec):
88 cmd = ["git", "show", "--quiet", "--pretty=format:%P", commit_spec]
89 git = subprocess.Popen(cmd, stdout=subprocess.PIPE)
90 stdout, stderr = git.communicate()
91 assert git.returncode == 0, git.returncode
92 parents = stdout.rstrip("\n").split(" ")
93 if parents == [""]:
94 parents = []
95 for parent in parents:
96 meld(commit_spec, parent)
99 if __name__ == "__main__":
100 sys.exit(main(*parse_argv(sys.argv[0], sys.argv[1:])))