changeset 1091:384eb7e05b61

layouts: teach layout detection from file about alternate layouts
author David Schleimer <dschleimer@fb.com>
date Wed, 04 Sep 2013 11:30:50 -0700
parents 80a456b77ade
children cd0d14e25757
files hgsubversion/layouts/base.py hgsubversion/layouts/detect.py hgsubversion/svncommands.py
diffstat 3 files changed, 38 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/hgsubversion/layouts/base.py
+++ b/hgsubversion/layouts/base.py
@@ -30,6 +30,9 @@ class BaseLayout(object):
 
         This should return a path relative to the repo url
 
+        Implementations may indicate that no mapping is possible for
+        the given branch by raising a KeyError.
+
         """
         self.__unimplemented('remotename')
 
@@ -39,6 +42,9 @@ class BaseLayout(object):
         This should return an absolute path, assuming our repo root is at subdir
         A false subdir shall be taken to mean /.
 
+        Implementations may indicate that no mapping is possible for
+        the given branch by raising a KeyError.
+
         """
         self.__unimplemented('remotepath')
 
--- a/hgsubversion/layouts/detect.py
+++ b/hgsubversion/layouts/detect.py
@@ -12,6 +12,8 @@ from mercurial import util as hgutil
 
 from hgsubversion import svnwrap
 
+import __init__ as layouts
+
 def layout_from_subversion(svn, revision=None, ui=None):
     """ Guess what layout to use based on directories under the svn root.
 
@@ -49,7 +51,7 @@ def layout_from_config(ui, allow_auto=Fa
     layout = ui.config('hgsubversion', 'layout', default='auto')
     if layout == 'auto' and not allow_auto:
         raise hgutil.Abort('layout not yet determined')
-    elif layout not in ('auto', 'single', 'standard'):
+    elif layout not in layouts.NAME_TO_CLASS and layout != 'auto':
         raise hgutil.Abort("unknown layout '%s'" % layout)
     return layout
 
@@ -71,17 +73,36 @@ def layout_from_file(meta_data_dir, ui=N
             ui.setconfig('hgsubversion', 'layout', layout)
     return layout
 
-def layout_from_commit(subdir, revpath):
+def layout_from_commit(subdir, revpath, branch, ui):
     """ Guess what the layout is based existing commit info
 
     Specifically, this compares the subdir for the repository and the
-    revpath as extracted from the convinfo in the commit.
+    revpath as extracted from the convinfo in the commit.  If they
+    match, the layout is assumed to be single.  Otherwise, it tries
+    the available layouts and selects the first one that would
+    translate the given branch to the given revpath.
 
     """
 
-    if (subdir or '/') == revpath:
-        layout = 'single'
-    else:
-        layout = 'standard'
-
-    return layout
+    subdir = subdir or '/'
+    if subdir == revpath:
+        return 'single'
+
+    candidates = set()
+    for layout in layouts.NAME_TO_CLASS:
+        layoutobj = layouts.layout_from_name(layout, ui)
+        try:
+            remotepath = layoutobj.remotepath(branch, subdir)
+        except KeyError:
+            continue
+        if  remotepath == revpath:
+            candidates.add(layout)
+
+    if len(candidates) == 1:
+        return candidates.pop()
+    elif candidates:
+        config_layout = layout_from_config(ui, allow_auto=True)
+        if config_layout in candidates:
+            return config_layout
+
+    return 'standard'
--- a/hgsubversion/svncommands.py
+++ b/hgsubversion/svncommands.py
@@ -210,7 +210,8 @@ def _buildmeta(ui, repo, args, partial=F
                                             'right location in the repo.')
 
         if layout is None:
-            layout = layouts.detect.layout_from_commit(subdir, revpath)
+            layout = layouts.detect.layout_from_commit(subdir, revpath,
+                                                       ctx.branch(), ui)
             existing_layout = layouts.detect.layout_from_file(svnmetadir)
             if layout != existing_layout:
                 layouts.persist.layout_to_file(svnmetadir, layout)