[RFC][#30159] Fix to make bzr st and bzr st -S display paths relative to cwd.

Eddie Parker eddie at kickingdragon.com
Sun Feb 8 00:07:29 GMT 2009


Hello,

This is my first attempt at a patch submission, so please be gentle. ;)

I've written some code to get bug 30159 [1] fixed.  This is the bug about 'paths always being relative to the project root'.

A couple of points:

- This patch only fixes bzr st and bzr st -S.
  + The bug hints at other use cases, but doesn't detail which they are, so I only fixed the ones I cared about.
- The code makes use of a couple of free-floating functions I wrote that I'm not happy with their location, but I'm unsure where it's best to put them.  Suggestions welcome.

As always, if there's a better way of achieving this, I welcome your opinions.

Cheers,

-e-

[1] https://bugs.launchpad.net/bzr/+bug/30159

-------------- next part --------------
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: eddie at megatron-20090208000452-rfxan174qakwpvkb
# target_branch: lp:bzr
# testament_sha1: 732feee4e5e9effb410100aa611348b2747e853c
# timestamp: 2009-02-07 16:04:57 -0800
# base_revision_id: pqm at pqm.ubuntu.com-20090205215322-dlhyepy2fid5i7w6
# 
# Begin patch
=== modified file 'bzrlib/delta.py'
--- bzrlib/delta.py	2008-12-10 09:33:06 +0000
+++ bzrlib/delta.py	2009-02-08 00:04:52 +0000
@@ -21,8 +21,71 @@
 from bzrlib.inventory import InventoryEntry
 from bzrlib.trace import mutter, is_quiet
 from bzrlib.symbol_versioning import deprecated_function
-
-
+import os
+import os.path
+import sys
+
+def RelativePath(path, start):
+    ''' Return the relative path between the two.
+
+        @note I understand python 2.6 has a function like this, but I
+              don't have it installed so I can't test if they're equivalent.
+    '''
+
+    def FindCommonAncestor(p1, p2):
+        p1split = p2.split(os.path.sep)
+        p2split = p1.split(os.path.sep)
+        
+        commonAncestorIndex = None
+        for i in range(len(p1split)):
+            if i >= len(p2split) or p1split[i] != p2split[i]:
+                break
+
+            commonAncestorIndex = i
+
+        if commonAncestorIndex == None:
+            return None
+
+        return os.path.sep.join(p1split[0:commonAncestorIndex+1])
+            
+    commonAncestor = FindCommonAncestor(path, start)
+
+    if commonAncestor != None:
+        relPath = start
+
+        while os.path.abspath(relPath) != commonAncestor:
+            relPath = os.path.join(relPath, "..")
+
+        relPath += path[len(commonAncestor):]
+
+        assert(os.path.abspath(relPath) == os.path.abspath(path))
+
+        return relPath
+
+    return path
+
+def AttemptToShortenPath(path):
+    # lazy loaded due to cyclic dependency
+    from bzrlib.workingtree import WorkingTree
+    rootDirectory = os.getcwd() 
+    repoDirectory = WorkingTree.open_containing(None)[0].basedir
+    
+    # Attempt to shorten the path to something relative to cwd.
+    # Need to calculate this per loop in case we're showing things across the whole repo.
+    fullPath = os.path.join(repoDirectory, path)
+    
+    path = RelativePath(fullPath, rootDirectory)
+    
+    if path.startswith(rootDirectory):
+        path = path[len(rootDirectory):]
+    
+        if path[0] == os.path.sep:
+            path = path[1:]
+
+    return path
+                
+
+    
 class TreeDelta(object):
     """Describes changes from one tree to another.
 
@@ -161,6 +224,7 @@
         def show_list(files, long_status_name, short_status_letter,
                       default_format='%s', with_file_id_format='%-30s',
                       show_more=None):
+
             if files:
                 header_shown = False
                 if short_status:
@@ -169,10 +233,14 @@
                     prefix = ''
                 prefix = indent + prefix + '  '
 
+
                 for item in files:
                     path, file_id, kind = item[:3]
                     if (filter is not None and not filter(path, file_id)):
                         continue
+
+                    path = AttemptToShortenPath(path)
+
                     if not header_shown and not short_status:
                         to_file.write(indent + long_status_name + ':\n')
                         header_shown = True
@@ -330,6 +398,14 @@
             return
         if paths[1] == '' and versioned == 'added' and self.suppress_root_add:
             return
+
+        def RunAttemptToShortenPath(x):
+            if x == None:
+                return x
+
+            return AttemptToShortenPath(x)
+
+        paths = [RunAttemptToShortenPath(x) for x in paths]
         if versioned == 'unversioned':
             # skip ignored unversioned files if needed.
             if self.unversioned_filter is not None:

# Begin bundle
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
5gA=


More information about the bazaar mailing list