Code

Changes between Version 18 and Version 19 of MercurialBranches


Ignore:
Timestamp:
07/02/11 10:37:16 (3 years ago)
Author:
lukeplant
Comment:

Updated backport script for features available in Mercurial 1.9

Legend:

Unmodified
Added
Removed
Modified
  • MercurialBranches

    v18 v19  
    2828 * Alternatively, use the [http://mercurial.selenic.com/wiki/MqExtension queues] extension to manage long lived patches. 
    2929 * To collapse several commits into a single commit before pushing back to svn, use the [http://mercurial.selenic.com/wiki/HisteditExtension histedit] extension 
    30  * To backport a changeset from trunk, use the [http://mercurial.selenic.com/wiki/TransplantExtension transplant] extension.  Or use this handy script which will generate the commit message for you: 
    31    {{{ 
     30 
     31=== Backporting === 
     32 
     33To backport a changeset from trunk, use the [http://mercurial.selenic.com/wiki/TransplantExtension transplant] extension. From Mercurial 1.9 onwards, you can use the 'filter' feature of transplant to create the commit message for you. Save the following script as ~/bin/django_backport_filter (for example) and make it executable: 
     34 
     35{{{ 
    3236#!sh 
    33 #!/bin/bash 
    34  
    35 function usage { 
    36     echo "Usage: hg_backport <branch> <hgrevision>"; 
    37     echo "   or: hg_backport <branch> --svnrev <svnrevision>"; 
    38 } 
    39  
    40 if [ $# -lt 2 ] 
     37#!/bin/sh 
     38CURRENT_BRANCH=`hg branch | cut -f 2 -d '/'` 
     39SVN_REV=`hg svn info -r $HGREVISION | egrep '^Revision' | cut -f 2 -d ' '` 
     40SOURCE_BRANCH=`hg log --template "{branch}" -r $HGREVISION` 
     41if [ "x$SOURCE_BRANCH" = "xdefault" ] 
    4142then 
    42         usage; 
    43         exit 1; 
     43    SOURCE_BRANCH=trunk 
    4444fi 
    4545 
    46 hg st -a -r -m | grep '' > /dev/null && { echo "Working directory not clean - exiting" > /dev/stderr; exit 1; } 
    47  
    48 SHORTBRANCH="$1" 
    49 BRANCH="releases/$SHORTBRANCH" 
    50 if [ "$2" = "--svnrev" ] 
    51 then 
    52     SVNREV="$3" 
    53     HGREV=`hg log -r "svnrev($SVNREV)" --template '{rev}'` 
    54     if [ "x$HGREV" = "x" ] 
    55     then 
    56         echo "Can't find hg rev" 
    57         exit 1; 
    58     fi 
    59 else 
    60     HGREV="$2" 
    61     SVNREV=`hg svn info -r $HGREV | egrep '^Revision' | cut -f 2 -d ' '` 
    62     if [ "x$SVNREV" = "x" ] 
    63     then 
    64         echo "Can't find svn rev"; 
    65         exit 1; 
    66     fi 
    67 fi 
    68  
    69 echo "Backporting Subversion revision $SVNREV" 
    70 hg update $BRANCH || exit 1; 
    71 # Make a commit message first in case the transplant fails 
    72 hg log -r $HGREV --template "[$SHORTBRANCH] {desc}\n\nBackport of [$SVNREV] from trunk.\n" > hg-commit-message.txt || exit 1 
    73 hg transplant $HGREV || exit 1; 
    74 # Modify the commit message 
    75 # We need to get added files, since after rollback this is forgotten 
    76 ADDED=$(hg log -r tip --template '{file_adds}') 
    77 REMOVED=$(hg log -r tip --template '{file_dels}') 
    78 hg rollback > /dev/null || exit 1 
    79 if [ "x$ADDED" != "x" ] 
    80 then 
    81     hg add $ADDED || exit 1 
    82 fi 
    83 if [ "x$REMOVED" != "x" ] 
    84 then 
    85     hg remove $REMOVED || exit 1 
    86 fi 
    87 hg commit -l hg-commit-message.txt || exit 1 
    88 echo "Backport committed." 
    89    }}} 
    90    The command line is like one of the following: 
    91    {{{ 
    92 #!sh 
    93 hg_backport 1.2.X 13643 
    94 hg_backport 1.2.X --svnrev 13237 
    95 }}} 
    96    where 1.2.X is a directory under 'releases/' in the Subversion repo, 13643 is a hg revision ID, and 13237 is a Subversion revision ID.  The change is already committed to the local repo, but not 'pushed', so you can still rollback if changes need to be made. 
    97  
    98 === An alternate approach === 
    99  
    100 Another way of doing the same thing: Use the --filter option to the transplant extension. This requires the use of a Python script. Put the following in backport.py, and stick it in a tools directory somewhere: 
    101 {{{ 
    102 #!python 
    103 #!/usr/bin/python 
    104 import os 
    105 import sys 
    106  
    107 msg = sys.argv[1] 
    108 patch = sys.argv[2] 
    109  
    110 print 
    111 branch = os.environ.get('DJANGO_BRANCH',None) 
    112 if branch is None: 
    113     branch = raw_input('Backport branch: ') 
    114 else: 
    115     print "Backport branch:", branch 
    116  
    117 msg_file = open(msg, 'r') 
    118 outlines = [] 
    119 firstline = True 
    120 for raw_line in msg_file: 
    121     line = raw_line.strip() 
    122     if firstline: 
    123         if line.startswith('#'): 
    124             outlines.append(line) 
    125         else: 
    126             firstline = False 
    127             print 'MERGING: %s' % line 
    128             outlines.append('[%s] %s' % (branch, line)) 
    129     else: 
    130         outlines.append(line) 
    131 msg_file.close() 
    132  
    133 svn_revision = os.environ.get('SVNMERGE_REVISION',None) 
    134 if svn_revision is None: 
    135     svn_revision = raw_input('SVN Revision: ') 
    136 else: 
    137     print "SVN Revision:", svn_revision 
    138 outlines.append('') 
    139 outlines.append('Backport of r%s from trunk.' % svn_revision) 
    140  
    141 # And write the updated message file. 
    142 msg_file = open(msg,'w') 
    143 for line in outlines: 
    144     print >> msg_file, line 
    145 msg_file.close() 
    146  
    147 # In case of a clash, write the filename of the message file 
    148 print "Log message written to",msg 
     46sed -nie '1 p;2 p;3 p' "$1" 
     47hg log -r $HGREVISION --template "[$CURRENT_BRANCH] {desc}\n\nBackport of [$SVN_REV] from $SOURCE_BRANCH.\n" >> "$1" 
    14948}}} 
    15049 
    151 Then, use the following shell script to do the actual backport: 
     50Then, on the branch you want to backport to: 
    15251{{{ 
    15352#!sh 
    154 export SVNMERGE_REVISION=`hg svn info -r $1 | egrep '^Revision' | cut -f 2 -d ' '` 
    155 export DJANGO_BRANCH=`hg branch | cut -f 2 -d '/'` 
    156 hg transplant $1 --filter /path/to/backport.py 
    157 unset SVNMERGE_REVISION 
    158 unset DJANGO_BRANCH 
     53 
     54hg transplant --filter ~/bin/django_backport_filter <hg revision number of changeset to backport> 
    15955}}} 
    160  
    161 If you call this script 'hg_backport', then  
    162  
    163 The command line is like: 
    164 {{{ 
    165 #!sh 
    166 hg_backport 13643 
    167 }}} 
    168 Any hg revision ID can be used as the argument; since the most common usage pattern is to backport the most recent svn commit on trunk, you can use 'tip': 
    169 {{{ 
    170 #!sh 
    171 hg_backport tip 
    172 }}} 
     56(Older revisions of this wiki page have methods that work for older versions of Mercurial, but they are suboptimal - upgrading hg is preferred). 
    17357 
    17458=== Gotchas ===