[PATCH] Add support for bzr diff to the "patch" bzrtool command
Goffredo Baroncelli
kreijack at alice.it
Fri Mar 3 21:33:42 GMT 2006
Hi all,
the bazaar diff output incorporates additional tags to highlight that some
action ( as symlinking and/or renaming ) are happened in the past.
So I patched the 'patch' command of the bzrtool plugin in order to support for
the following additional tag
=== removed file
=== removed directory
=== removed symlink
=== added file
=== added directory
=== added symlink
=== target is [ after === added symlink ]
=== renamed file
=== renamed directory
=== renamed symlink
example
$ bzr diff -r1..2
=== added symlink 'linkb'
=== target is 'b'
=== renamed file 'a' => 'b'
--- a
+++ b
@@ -1,1 +1,1 @@
-first line
+2nd line
$ bzr revert -r1
$ ls -l
-rw-r--r-- 1 ghigo ghigo 9 2006-03-03 22:14 a
$ bzr diff -r1..2 | patch
patching file a
$ ls -l
total 4
-rw-r--r-- 1 ghigo ghigo 9 2006-03-03 22:14 a
$ bzr revert -r1
$ bzr diff -r1..2 | bzr patch --bzrdiff
patching file b
symlinking 'b' => 'linkb'
renaming 'a' => 'b'
$ ls -l
total 4
-rw-r--r-- 1 ghigo ghigo 9 2006-03-03 22:14 b
lrwxrwxrwx 1 ghigo ghigo 1 2006-03-03 22:14 linkb -> b
You can see the patch at
http://goffredo-baroncelli.homelinux.net/bazaar-dev/diffbzrtools?cmd=diff;otherrevid=abentley@panoramicfeedback.com-20060302141119-7a5ee02eb6483c50;rev=;pathrevid=;path=
You can browse the source and the history at
http://goffredo-baroncelli.homelinux.net/bazaar-dev/diffbzrtools
You can pull the source with
bzr pull http://goffredo-baroncelli.homelinux.net/bazaar-dev/diffbzrtools
You can download the source from
http://goffredo-baroncelli.homelinux.net/bazaar-dev/diffbzrtools?cmd=export;rev=;path=;mode=tgz
Below the patch
------
=== modified file '__init__.py'
--- __init__.py
+++ __init__.py
@@ -98,16 +98,22 @@
strip_help="""Strip the smallest prefix containing num leading slashes from \
each file name found in the patch file."""
Option.OPTIONS['strip'] = Option('strip', type=int, help=strip_help)
+Option.OPTIONS['bzrdiff'] = Option('bzrdiff',type=None,
+ help="""Handle extra bzr tags""")
class cmd_patch(bzrlib.commands.Command):
"""Apply a named patch to the current tree.
"""
takes_args = ['filename?']
- takes_options = ['strip']
- def run(self, filename=None, strip=1):
+ takes_options = ['strip','bzrdiff']
+ def run(self, filename=None, strip=-1, bzrdiff=0):
from patch import patch
from bzrlib.branch import Branch
b = Branch.open_containing('.')[0]
- return patch(b, filename, strip)
+ if strip == -1:
+ if bzrdiff: strip = 0
+ else: strip = 1
+
+ return patch(b, filename, strip, legacy= not bzrdiff)
class cmd_shelve(bzrlib.commands.Command):
=== modified file 'patch.py'
--- patch.py
+++ patch.py
@@ -14,11 +14,116 @@
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-import sys
+import sys, os
from subprocess import Popen, PIPE
from bzrlib.transport import get_transport
from urlparse import urlsplit, urlunsplit
-def patch(branch, location, strip):
+
+class BzrTagProc:
+ """This class handle the additional bazaar diff tags
+
+ TODO:
+ error handling
+ """
+ def __init__(self):
+ self.renamed = None
+ self.link = None
+
+ def _extractname(self, s):
+ x = s[0]
+ i = 1
+ ls = len(s)
+
+ while i < ls:
+ if s[i] == '\\':
+ assert(i+1 < ls )
+ i += 2
+ continue
+
+ if s[i] == x:
+ return s[1:i],i+1
+
+ i += 1
+
+ assert(False)
+
+ def extractname(self, s):
+ space = s.find(" ",9) # find the 2nd space
+ assert(space)
+ return self._extractname(s[space+1:])[0]
+
+ def extractnames(self, s):
+ space = s.find(" ",10) # find the 2nd space
+ assert(space)
+ s=s[space+1:]
+ source, pos = self._extractname(s)
+ assert( pos +4 < len(s) )
+ dest, dummy = self._extractname(s[pos+4:])
+
+ return source,dest
+
+ def flush(self):
+ self.process( )
+
+ def process(self, cmd = None):
+ if self.renamed:
+ os.rename(self.renamed[0], self.renamed[1])
+ self.renamed = None
+
+ if not cmd: return
+
+ if ( cmd.startswith("removed file") or
+ cmd.startswith("removed symlink") ):
+
+ target = self.extractname(cmd)
+ print "removing '%s'"%target
+ os.unlink(target)
+
+ elif cmd.startswith("removed directory"):
+
+ target = self.extractname(cmd)
+ print "removing '%s'"%target
+ os.rmdir(target)
+
+ elif cmd.startswith("added file"):
+ target = self.extractname(cmd)
+ print "adding '%s'"%target
+ f = open(target,"w")
+ f.close( )
+
+ elif cmd.startswith("added directory"):
+ target = self.extractname(cmd)
+ print "adding '%s'"%target
+ os.mkdir(target)
+
+ elif cmd.startswith("added symlink"):
+ assert(not self.link)
+ self.link = self.extractname(cmd)
+
+ elif cmd.startswith("target is"):
+ assert(self.link)
+ source = self.extractname(cmd)
+ print "symlinking '%s' => '%s'"%(source, self.link)
+ os.symlink(source, self.link)
+ self.link = None
+
+ elif ( cmd.startswith("renamed symlink") or
+ cmd.startswith("renamed file") or
+ cmd.startswith("renamed directory") ):
+
+ space = cmd.find(" ",10) # find the 2nd space
+ assert(space)
+ source,dest = self.extractnames(cmd[space+1:])
+ print "renaming '%s' => '%s'"%(source,dest)
+
+ os.rename(source,dest)
+
+ else:
+ sys.stderr.write("Unsupported tag: '%s'\n"%cmd)
+
+
+
+def patch(branch, location, strip, legacy):
"""Apply a patch to a branch, using patch(1). URLs may be used."""
my_file = None
if location is None:
@@ -33,8 +138,30 @@
if my_file is None:
my_file = file(location, 'rb')
cmd = ['patch', '--directory', branch.base, '--strip', str(strip)]
- child_proc = Popen(cmd, stdin=PIPE)
- for line in my_file:
- child_proc.stdin.write(line)
- child_proc.stdin.close()
- return child_proc.wait()
+ r = 0
+ if legacy:
+ child_proc = Popen(cmd, stdin=PIPE)
+ for line in my_file:
+ child_proc.stdin.write(line)
+ child_proc.stdin.close()
+ r = child_proc.wait()
+ else:
+ bzr_tags_proc = BzrTagProc( )
+ child_proc = None
+ for line in my_file:
+ if line.startswith("=== "):
+ if child_proc:
+ child_proc.stdin.close()
+ r = child_proc.wait()
+ child_proc = None
+ bzr_tags_proc.process(line[4:])
+ else:
+ if not child_proc:
+ child_proc = Popen(cmd, stdin=PIPE)
+ #sys.stdout.write("# %s"%line)
+ child_proc.stdin.write(line)
+ if child_proc:
+ child_proc.stdin.close()
+ r = child_proc.wait()
+ bzr_tags_proc.flush( )
+ return r
\ No newline at end of file
Goffredo
--
gpg key@ keyserver.linux.it: Goffredo Baroncelli (ghigo) <kreijack_AT_inwind.it>
Key fingerprint = CE3C 7E01 6782 30A3 5B87 87C0 BB86 505C 6B2A CFF9
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 191 bytes
Desc: not available
Url : https://lists.ubuntu.com/archives/bazaar/attachments/20060303/30564a96/attachment.pgp
More information about the bazaar
mailing list