# HG changeset patch # User David Schleimer # Date 1378319450 25200 # Node ID 384eb7e05b612f889b09e26aea2b58c7a1afca0f # Parent 80a456b77ade8ab0d7a64decc6421d1a041549f9 layouts: teach layout detection from file about alternate layouts diff --git a/hgsubversion/layouts/base.py b/hgsubversion/layouts/base.py --- 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') diff --git a/hgsubversion/layouts/detect.py b/hgsubversion/layouts/detect.py --- 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' diff --git a/hgsubversion/svncommands.py b/hgsubversion/svncommands.py --- 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)