Extract changesets between last two tags in Mercurial I have written the following script that I'd like to have reviewed:

#!/usr/bin/python

import os

os.system('hg tags &gt; tags.txt')
file = 'tags.txt'
path = os.path.join(os.getcwd(), file)
fp = open(path)
for i, line in enumerate(fp):
    if i == 1:
        latestTagLine = line      
    elif i == 2:
        previousTagLine = line    
    elif i &gt; 4:
        break
fp.close()
revLatestTag = latestTagLine.split(':')
l = revLatestTag[0].split(' ')
revPreviousTag = previousTagLine.split(':')
p = revPreviousTag[0].split(' ')
command = 'hg log -r {}:{} &gt; diff.txt'.format(l[-1],p[-1])
os.system(command)


Output of hg tags command:


tip                         523:e317b6828206
TOOL_1.4                    522:5bb1197f2e36
TOOL_1.3                    515:7362c0effe40
TOOL_1.1                    406:33379f244971
You didn't specify that you wanted to leave a tags.txt file as an intentional side-effect of your script.  I'm going to assume that it's an unwanted temporary file.  In that case, you can read the output of hg directly through a pipe.  Furthermore, the file object can be used as an iterator to fetch just two lines, with no for-loop.

from subprocess import Popen, PIPE

# Read the first two lines of `hg tags`
with Popen(['hg', 'tags'], stdout=PIPE).stdout as hg_log:
    latestTagLine = hg_log.next()
    previousTagLine = hg_log.next()


The code to interpret each line is repeated, and therefore deserves to be put into a reusable function.  Instead of splitting, use a capturing regular expression.

import re

def parse_tag_line(line):
    match = re.match(r'^(.*) *(\d+):(.*)', line)
    return dict([
        ('tag', match.group(1)),
        ('rev', match.group(2)),
        ('hash', match.group(3)),
    ])


Finish up by generating the output:

log_range = '%s:%s' % (latestTag['hash'], previousTag['hash'])
with open('diff.txt', 'w') as diff:
    Popen(['hg', 'log', '-r', log_range], stdout=diff)





  Personally, I would prefer to just dump the output to sys.stdout, and use the shell to redirect the script's output to a file (script &gt; diff.txt) instead of hard-coding diff.txt in the script itself.  Then, the epilogue would become

log_range = '%s:%s' % (latestTag['hash'], previousTag['hash'])
Popen(['hg', 'log', '-r', log_range])





Putting it all together:

import re
from subprocess import Popen, PIPE

def parse_tag_line(line):
    match = re.match(r'^(.*) *(\d+):(.*)', line)
    return dict([
        ('tag', match.group(1)),
        ('rev', match.group(2)),
        ('hash', match.group(3)),
    ])

# Read the first two lines of `hg tags`
with Popen(['hg', 'tags'], stdout=PIPE).stdout as hg_log:
    latestTag = parse_tag_line(hg_log.next())
    previousTag = parse_tag_line(hg_log.next())

log_range = '%s:%s' % (latestTag['hash'], previousTag['hash'])

# Write `hg log -r ...:...` to diff.txt
with open('diff.txt', 'w') as diff:
    Popen(['hg', 'log', '-r', log_range], stdout=diff)