Skip to content

Instantly share code, notes, and snippets.

@arsane
Last active August 29, 2015 14:05
Show Gist options
  • Save arsane/f0a91780e5c0d5c3e49d to your computer and use it in GitHub Desktop.
Save arsane/f0a91780e5c0d5c3e49d to your computer and use it in GitHub Desktop.
export mercurial revision changes in folders.
# This script is used to export changes between two commits
# into two folders for people don't have hg to review code.
#
# Usage:
# python hgfolderdiff.py rev1 rev2 diffs.zip
#
# export change files in two revisions into two directories,
# and then archive to zip file.
#
import os, subprocess, sys
import tempfile
from zipfile import ZipFile, ZIP_DEFLATED
def copy_files(rev, paths, copyto):
rev_dir = copyto+'/'+rev
for path in paths:
fdir, tail = os.path.split(rev_dir +'/' + path)
if not os.path.exists(fdir):
os.makedirs(fdir)
cmd = 'hg cat -r %s "%s" > "%s"' % (rev, path, rev_dir+'/'+path)
os.system(cmd)
def zipdir(path, z):
os.chdir(path)
for root, dirs, files in os.walk(path):
for file in files:
rel_dir = os.path.relpath(root, path)
z.write(os.path.join(rel_dir, file))
def main(revfrom, revto, destination, *args):
root, err = getoutput("hg root")
if "no Merurial repository" in err:
print "This script must be run from within an Hg repository"
return
root = root.strip()
filelist, _ = getoutput("hg status --rev %s:%s" % (revfrom, revto))
paths_old = []
paths_new = []
for line in filelist.split('\n'):
try:
(status, path) = line.split(' ', 1)
except ValueError:
continue
if status == 'M':
paths_old.append(path)
paths_new.append(path)
elif status == 'A':
paths_new.append(path)
elif status == 'R':
paths_old.append(path)
else:
print "Unknown status: %s: %s" % (status, path)
if len(paths_old) < 1 and len(paths_new) < 1:
print "No changed files could be found."
return
os.chdir(root)
dirpath = tempfile.mkdtemp()
copy_files(revfrom, paths_old, dirpath)
copy_files(revto, paths_new, dirpath)
z = ZipFile(destination, "w", ZIP_DEFLATED)
zipdir(dirpath, z)
z.close()
print "Done."
def getoutput(cmd):
p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
return p.communicate()
if __name__ == '__main__':
main(*sys.argv[1:])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment