[Svnmerge] Fwd: [Issue 2869] multiple pathid formats
Giovanni Bajo
rasky at develer.com
Mon Feb 16 16:26:51 PST 2009
On lun, 2009-02-16 at 10:01 -0500, Dustin J. Mitchell wrote:
> On Mon, Feb 16, 2009 at 8:05 AM, Giovanni Bajo <rasky at develer.com>
> wrote:
> > Where is the latest patch? Attached to the issue tracker?
>
> Yes:
>
> http://subversion.tigris.org/nonav/issues/showattachment.cgi/971/locid-final.patch
>
> Thanks!
Comments:
>
> + def __eq__(self, other):
> + return self is other
> +
> + def __ne__(self, other):
> + return self is not other
> +
> + def __hash__(self):
> + return id(self)
>
This is the default.
>
> + # convert pathid_str to a PathIdentifier
> + if not locobjs.has_key(pathid_str):
> + if is_url(pathid_str):
> + # we can determine every form; pathid_hint knows how to do that
> + pathid_hint(pathid_str)
> + elif pathid_str[:7] == 'uuid://':
> + mo = re.match('uuid://([^/]*)(.*)', pathid_str)
> + if not mo:
> + error("Invalid path identifier '%s'" % pathid_str)
> + uuid, repo_relative_path = mo.groups()
> + pathid = PathIdentifier(repo_relative_path, uuid=uuid)
> + # we can cache this by uuid:// pathid and by repo-relative path
> + locobjs[pathid_str] = locobjs[repo_relative_path] = pathid
> + elif pathid_str and pathid_str[0] == '/':
> + # strip any trailing slashes
> + pathid_str = pathid_str.rstrip('/')
> + pathid = PathIdentifier(repo_relative_path=pathid_str)
> + # we can only cache this by repo-relative path
> + locobjs[pathid_str] = pathid
> + else:
> + error("Invalid path identifier '%s'" % pathid_str)
This would be a perfect PathIdentifier.create() staticmethod, AFAICT. By
moving the code there, you're uniting all the logic about
formatting/parsing of a PathIdentifier string representation within the
class itself.
> -def is_url(url):
> +def is_url(url, check_valid=False):
> """Check if url is a valid url."""
> - return re.search(r"^[a-zA-Z][-+\.\w]*://[^\s]+$", url) is not None
> + if re.search(r"^[a-zA-Z][-+\.\w]*://[^\s]+$", url) is not None and url[:4] != 'uuid':
> + if not check_valid: return True
> + return get_svninfo(url, fail_on_invalid=False) != {}
> + return False
>
I would prefer if is_url() would stay a purely syntactic function, just
as is_pathid() and is_wc(). Instead of this change, I would add another
function called check_url() (or check_valid_url()), so that you can
replace later occurrences of:
> + if is_url(cf_url, check_valid=True):
> + cf_pathid = target_to_pathid(cf_url)
into:
if is_url(cf_url) and check_url(cf_url):
[...]
> - for L in launchsvn('info "%s"' % target):
> + lines = launchsvn('info "%s"' % target)
> + if not lines: lines = [ "x: (Not a valid URL)" ]
Why you need this special case?
>
> - info[key] = value.strip()
> + value = value.strip()
> + if value == '(Not a valid URL)':
> + if fail_on_invalid:
> + error("Not a valid URL: %s" % target)
> + return {} # no info on this URL
> + info[key] = value
Hmm... I don't this this whole modification to get_svninfo() is worth
it. It looks like your only goal was to implement the URL validity
check. In that case, it's easy even without all this code:
def check_url(url):
return "URL" in get_svninfo(url)
Notice that this how this is already done: if you look at other usages
of get_svninfo(), you will see that missing items from the dictionary is
sometimes interpreted as a "bad target" signal.
> +def pathid_hint(target):
> + """Cache some information about target, as it may be referenced by
> + repo-relative path in subversion properties; the cache can help to
> + expand such a relative path to a full path identifier."""
> + if locobjs.has_key(target): return
> + if not is_url(target) and not is_wc(target): return
What about putting all this code (pathid_hint, target_to_pathid,
locobjs, repo_hints) within the PathIdentifier class?
Eg: pathid_hint -> PathIdentifier.hint(), target_to_pathid ->
staticmetod PathIdentifier.from_target() (factory). The caches could be
moved within the class objects (PathIdentifier.locobjs, ecc.). Or
something like that...
I think it would make the code even easier to read.
> -def check_old_prop_version(branch_target, branch_props):
> - """Check if branch_props (of branch_target) are svnmerge properties in
> - old format, and emit an error if so."""
> -
> - # Previous svnmerge versions allowed trailing /'s in the repository
> - # local path. Newer versions of svnmerge will trim trailing /'s
> - # appearing in the command line, so if there are any properties with
> - # trailing /'s, they will not be properly matched later on, so require
> - # the user to change them now.
> - fixed = {}
> - changed = False
> - for source, revs in branch_props.items():
> - src = rstrip(source, "/")
> - fixed[src] = revs
> - if src != source:
> - changed = True
> -
> - if changed:
> - err_msg = "old property values detected; an upgrade is required.\n\n"
> - err_msg += "Please execute and commit these changes to upgrade:\n\n"
> - err_msg += 'svn propset "%s" "%s" "%s"' % \
> - (opts["prop"], format_merge_props(fixed), branch_target)
> - error(err_msg)
> -
>
If I understand correctly your whole patch, you're removing this code
because, after your patch, svnmerge.py will be again able to cope with
this old format. Is this correct?
> + OptionArg("-L", "--location-type",
> + dest="location-type",
> + default="path",
> + help="Use this type of location identifier in the new " +
> + "Subversion properties; 'uuid', 'url', or 'path' " +
> + "(default)"),
Why "path" is the default? Is this only some kind of backward
compatibility default? I would say uuid is the best choice here, isn't
it?
The patch looks great altogether. It's a great cleanup and also
introduces a valuable feature for cross-repo merges. Thanks!
--
Giovanni Bajo
Develer S.r.l.
http://www.develer.com
More information about the Svnmerge
mailing list