Skip to content
Snippets Groups Projects
Commit a7eb3512e54a authored by Marcin Kasperski's avatar Marcin Kasperski
Browse files

Introduced new, shorter syntax for alternative paths:

    alias.sth.local = ...
    alias.sth.remote = ...
parent 0cec122f5333
No related branches found
No related tags found
No related merge requests found
......@@ -93,6 +93,7 @@
--------------------------------------------------------
To (re)use the same alias in a few different locations, use
``.alias``::
``ALIAS.XTRA.local`` and ``ALIAS.XTRA.remote`` keys, where ``XTRA``
is something unique. For example::
[path_pattern]
......@@ -97,8 +98,7 @@
[path_pattern]
production.local = ~/devel/{repo}
production.remote = ssh://www-owner@www.mekk.net/public/{repo}
experiment.local = ~/experiments/{repo}
experiment.remote = ssh://www-owner@beta.mekk.net/public/{repo}
experiment.alias = production
production.main.local = ~/devel/{repo}
production.main.remote = ssh://www-owner@www.acme.org/public/{repo}
production.beta.local = ~/experiments/{repo}
production.beta.remote = ssh://www-owner@beta.acme.org/public/{repo}
......@@ -104,7 +104,8 @@
Definitions above let you ``hg push production`` not only in
``~/devel/website/blog`` but also in ``~/experiments/website/qagame``.
Whether this is a good idea, is up to you.
would let you ``hg push production`` not only in
``~/devel/website/blog`` but also in ``~/experiments/website/qagame``
(pushing to ``www.acme.org`` in the former, and to ``beta.acme.org`` in the
latter case). Whether this is a good idea, is up to you.
......@@ -173,4 +174,7 @@
Pattern syntax
=======================================================
Introduction
--------------------
Patterns are defined in ``[path_pattern]`` section of mercurial
......@@ -176,8 +180,6 @@
Patterns are defined in ``[path_pattern]`` section of mercurial
configuration file (typically they are kept in ``~/.hgrc``, but feel
free to define them system-wide).
You may have as many patterns as you like. Example::
configuration file (typically ``~/.hgrc``). You may have as many
patterns as you like. Example illustrating various syntax elements::
[path_pattern]
lagrange.local = ~/devel/{repo}
......@@ -188,10 +190,18 @@
wrk.remote = https://tim@devel-department.local/{what:/=__:\=__}
ugly.local = ~/(topic)/sources/{subpath}/repo
ugly.remote = ssh://hg{topic}@devel.local/{topic}/{subpath}
cfg.local = ~/.config/upstart
cfg.remote = ssh://hgrepos@central.com/configs/riemann/upstart
cfg2.local = ~/.local/share/applications
cfg2.remote = ssh://hgrepos@central.com/configs/riemann/applications
cfg2.alias = cfg
cfg.dotcfg.local = ~/.config/{repo}
cfg.dotcfg.remote = ssh://hgrepos@central.com/configs/riemann-config/{repo}
cfg.dotshr.local = ~/.local/share/{repo}
cfg.dotshr.remote = ssh://hgrepos@central.com/configs/riemann-local/{repo}
official.hgstable.local = ~/tracked/mercurial/hg-stable
official.hgstable.remote = http://selenic.com/repo/hg-stable
official.thg.local = ~/tracked/mercurial/tortoisehg-stable
official.thg.remote = https://bitbucket.org/tortoisehg/thg
official.evolve.local = ~/tracked/mercurial/mutable-history
official.evolve.remote = https://bitbucket.org/marmoute/mutable-history
Pattern definition
---------------------
Every pattern is defined by the pair of keys - ``«alias».local`` and
......@@ -196,8 +206,8 @@
Every pattern is defined by the pair of keys - ``«alias».local`` and
``«alias».remote`` - or, less frequently, by set of three keys
``«prefix».local``, ``«prefix».remote``, and ``«prefix».alias`` (where
``«prefix»`` is anything unique).
``«alias».remote`` - or, in case the same alias is to be used in a few
places, by ``«alias».«sth».local`` and ``«alias».«sth».remote`` (where
``«sth»`` is anything making the key unique).
While processing patterns, the extension matches current repository
root path against ``local`` pattern, and if it matches, extracts parts
......@@ -227,10 +237,10 @@
obscure patterns are possible (as ``ugly`` above
illustrates).
Markers are optional, if no marker is used (see ``cfg`` above), rule
applies to exactly one repository. This may make sense (over defining
path in given repo ``.hg/hgrc``) if you prefer to centralize your
paths.
Markers are optional, if no marker is used (see ``official`` above),
rule applies to exactly one repository. This may make sense (over
defining path in given repo ``.hg/hgrc``) if you prefer to centralize
your paths.
The ``.remote`` part defines appropriate remote address. This is typical
Mercurial remote path, but ``{marker}``'s can be used to refer to
......@@ -247,6 +257,9 @@
``y``, *then replace any* ``v`` *with* ``z``, *then use the final
result*.
Resolution example
--------------------
For example, with definitions above, if you happen to work
in repository ``~/devel/python/libs/webby``, the extension will:
......@@ -264,6 +277,23 @@
3. Ignore remaining patterns as they do not match.
If ``.alias`` is defined, value of this item serves as path alias.
Otherwise pattern prefix is used as alias. So, with definitions above:
Or, in ``~/tracked/mercurial/tortoisehg-stable``, the extension will:
1. Note that ``official.thg.local`` matches (at this time without
defining anything), extract matching path from
``official.thg.remote``, and finally generate for this repository
path ``official = https://bitbucket.org/tortoisehg/thg`` (so ``hg
pull official`` works there). Note that the path is just
``official``, the ``.thg.`` part was used only to group appropriate
config items.
2. Ignore remaining patters which do not match.
Legacy syntax
------------------------------------------------------
For compatibility reasons, there exist alternative way
to reuse the same path alias. For example, instead of
(currently recommended)::
......@@ -269,4 +299,11 @@
1. You may issue ``hg pull lagrange`` or ``hg push euler`` in
``~/devel/snippets/js``.
[path_pattern]
production.web.local = ~/devel/web/{repo}
production.web.remote = ssh://product@acme.org/www/{repo}
production.db.local = ~/devel/database/{repo}
production.db.remote = ssh://product@backend.acme.org/db/{repo}
production.monit.local = ~/devel/monitoring/{repo}
production.monit.remote = ssh://product@monit.acme.org/{repo}
one can use ``.alias``::
......@@ -272,7 +309,22 @@
2. You may issue ``hg push cfg`` in both ``~/.config/upstart``
and ``~/.local/share/applications`` (in the latter thanks
to ``.alias``).
[path_pattern]
production.local = ~/devel/web/{repo}
production.remote = ssh://product@acme.org/www/{repo}
dbproduction.db.local = ~/devel/database/{repo}
dbproduction.db.remote = ssh://product@backend.acme.org/db/{repo}
dbproduction.alias = production
monproduction.local = ~/devel/monitoring/{repo}
monproduction.remote = ssh://product@monit.acme.org/{repo}
monproduction.alias = production
Both those syntaxes give meaning to ``hg push production`` in all matching
repositories.
.. note::
I keep supporting ``.alias`` syntax for backward compatibility (it
was the first syntax provided for the task) but it is more
elaborate and less readable, so I don't recommend it anymore.
Pattern priority
......@@ -294,9 +346,8 @@
acme.local = ~/devel/{repo}
acme.remote = ssh://johny@apps.mekk.net/code/{repo}
acme.enforce = true
acme-alt.local = ~/devel/libs/{repo}
acme-alt.remote = ssh://johny@libs.mekk.net/{repo}
acme-alt.alias = acme
acme.alt.local = ~/devel/libs/{repo}
acme.alt.remote = ssh://johny@libs.mekk.net/{repo}
(both patterns define the same alias ``acme``) executing ``hg push
acme`` in ``~/devel/libs/calc`` will push to
......@@ -307,7 +358,7 @@
If more than one pattern of the same strength matches, extension tries
it's best to pick one with more specific local path, for example if we
drop ``acme.enforce`` from the example above (or if we add
``acme-alt.enforce``), executing ``hg push acme`` in
``acme.alt.enforce``), executing ``hg push acme`` in
``~/devel/libs/calc`` will push to ``ssh://johny@libs.mekk.net/calc``
as more specific pattern wins.
......@@ -324,6 +375,8 @@
doubt.
Tips and tricks
=======================================================
......@@ -333,12 +386,10 @@
You can define ``default`` via path pattern if you wish::
[path_pattern]
default_hobby.local = ~/hobby/{repo}
default_hobby.remote = ssh://hg@bitbucket.org/Johny/{below:/=-}
default_hobby.alias = default
default_wrk.local = ~/work/{what}
default_wrk.remote = https://tim@devel-department.local/{what}
default_wrk.alias = default
default.hobby.local = ~/hobby/{repo}
default.hobby.remote = ssh://hg@bitbucket.org/Johny/{below:/=-}
default.wrk.local = ~/work/{what}
default.wrk.remote = https://tim@devel-department.local/{what}
(here in ``~/hobby`` I push to bitbucket by default, but in ``~/work``
to department server).
......@@ -347,8 +398,8 @@
Mercurial will sooner or later define ``default`` path in
per-repository ``.hg/hgrc`` files. Enforce your patterns
(``default_hobby.enforce = true``) if you need to defeat those
settings.
(``default.hobby.enforce = true``) if you need to defeat those
settings. Or don't if you want those patterns for defaults only.
Special treatment of specific repositories
......@@ -358,15 +409,15 @@
general rule. In such a case, one can simply overwrite given alias
on repository level, or use pattern priority.
My real example is `Keyring Extension`_ repository. While
I generally use ``-`` as path separator (so Path Pattern
is located at ``/Mekk/mercurial-path_pattern`` and `Dynamic Username`_
at ``/Mekk/mercurial-dynamic_username``), keyring repo predates
this convention and is named ``/Mekk/mercurial_keyring``. So
I solve this by::
My real example is `Keyring Extension`_ repository. While I generally
use dash (``-``) as path separator (so Path Pattern is located at
``/Mekk/mercurial-path_pattern`` and `Dynamic Username`_ at
``/Mekk/mercurial-dynamic_username``), keyring repo predates this
convention and is named ``/Mekk/mercurial_keyring``. So I solve this
by::
[path_pattern]
# By default bitbucket mirrors my dir structure replacing / with -
bbssh.local = ~/devel/{below}
bbssh.remote = ssh://hg@bitbucket.org/Mekk/{below:/=-}
# … but there are overrides
......@@ -367,10 +418,9 @@
[path_pattern]
# By default bitbucket mirrors my dir structure replacing / with -
bbssh.local = ~/devel/{below}
bbssh.remote = ssh://hg@bitbucket.org/Mekk/{below:/=-}
# … but there are overrides
bbssh_keyring.local = ~/devel/mercurial/keyring
bbssh_keyring.remote = ssh://hg@bitbucket.org/Mekk/mercurial_keyring
bbssh_keyring.alias = bbssh
bbssh.keyring.local = ~/devel/mercurial/keyring
bbssh.keyring.remote = ssh://hg@bitbucket.org/Mekk/mercurial_keyring
......@@ -376,7 +426,7 @@
Of course I could achieve the same by defining ``bbssh`` among ``[paths]`` in
``~/devel/mercurial/keyring/.hg/hgrc``, but pattern technique have some
advantages:
Of course I could achieve the same by defining ``bbssh`` among
``[paths]`` in ``~/devel/mercurial/keyring/.hg/hgrc``, but pattern
technique have some advantages:
- as I share and sync snippet of my ``~/.hgrc`` between machines,
this definition automatically propagates everywhere, and I don't need
......@@ -395,11 +445,9 @@
in various tracked repositories::
[path_pattern]
official_hgstable.local = ~/tracked/hg-stable
official_hgstable.remote = http://selenic.com/repo/hg-stable
official_hgstable.alias = official
official_thg.local = ~/tracked/tortoise-hg
official_thg.remote = http://bitbucket.org/tortoisehg/thg/
official_thg.alias = official
official.hgstable.local = ~/tracked/hg-stable
official.hgstable.remote = http://selenic.com/repo/hg-stable
official.thg.local = ~/tracked/tortoise-hg
official.thg.remote = https://bitbucket.org/tortoisehg/thg/
# …
......@@ -404,8 +452,28 @@
# …
Again, of course I could enter those paths directly inside ``.hg/hgrc``,
but definitions above can be synced between machines and survive
if I discard repo in charge for some time.
Of course I could enter those paths directly inside ``.hg/hgrc``, but
those definitions can be synced between machines, and survive
in case I discard the repo in charge for some time.
Separating (and sharing) pattern configuration
---------------------------------------------------
In case the pattern list grows bigger, I recommend moving patterns
into separate config file. For example, write in ``~/.hgrc``::
%include ~/configs/mercurial/path_pattern.hgrc
and then store all patterns in ``path_pattern.hgrc``::
[path_pattern]
Extra benefit of such approach is that it makes sharing the file
easier (in my case ``~/configs/mercurial`` is by itself Mercurial
repository which I share over my various development machines, and
which contains all non-machine specific snippets of my Mercurial
configuration).
Installation
=======================================================
......@@ -528,7 +596,7 @@
=======================================================
Development is tracked on BitBucket, see
http://bitbucket.org/Mekk/mercurial-path_pattern/
https://bitbucket.org/Mekk/mercurial-path_pattern/
Use BitBucket issue tracker for bug reports and enhancement
suggestions.
......@@ -545,7 +613,7 @@
.. _Mercurial: http://mercurial.selenic.com
.. _HISTORY.txt: http://bitbucket.org/Mekk/mercurial-path_pattern/src/tip/HISTORY.txt
.. _HISTORY.txt: https://bitbucket.org/Mekk/mercurial-path_pattern/src/tip/HISTORY.txt
.. _mercurial_extension_utils: https://bitbucket.org/Mekk/mercurial-extension_utils/
.. _Schemes Extension: https://www.mercurial-scm.org/wiki/SchemesExtension
.. _TortoiseHg: http://tortoisehg.bitbucket.org/
......
......@@ -2,7 +2,7 @@
#
# path pattern: define global path aliases, cloneto command
#
# Copyright (c) 2015 Marcin Kasperski <Marcin.Kasperski@mekk.waw.pl>
# Copyright (c) 2015-2016 Marcin Kasperski <Marcin.Kasperski@mekk.waw.pl>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
......@@ -114,5 +114,8 @@
Represents individual path pattern - pair of local (like
"~/sources/{path}") and remote (like "ssh://some/where/{path}")
"""
re_dotted_alias = re.compile(r'^ ([^\.]+) \. .*$', re.VERBOSE)
def __init__(self, prefix):
self.prefix = prefix
......@@ -117,6 +120,10 @@
def __init__(self, prefix):
self.prefix = prefix
self.alias = prefix
match = self.re_dotted_alias.search(prefix)
if match:
self.alias = match.group(1)
else:
self.alias = prefix
self.local = None
self.remote = None
self.enforce = False
......@@ -182,5 +189,6 @@
Loads and parses pattern definitions
"""
def __init__(self, ui):
rgxp_prefix = r'^(\w+(?:\.[\w0-9]+)?)\.'
self.patterns = {} # prefix → PatternPair
# Read «sth».local
......@@ -185,8 +193,9 @@
self.patterns = {} # prefix → PatternPair
# Read «sth».local
for prefix, value in meu.suffix_config_items(ui, "path_pattern", "local"):
for prefix, value in meu.rgxp_config_items(
ui, "path_pattern", re.compile(rgxp_prefix + "local")):
if prefix not in self.patterns:
self.patterns[prefix] = PatternPair(prefix)
ui.debug(_("path_pattern: Parsing local side of path pattern %s") % prefix)
self.patterns[prefix].learn_local(value, ui)
# Read «sth».remote
......@@ -188,11 +197,12 @@
if prefix not in self.patterns:
self.patterns[prefix] = PatternPair(prefix)
ui.debug(_("path_pattern: Parsing local side of path pattern %s") % prefix)
self.patterns[prefix].learn_local(value, ui)
# Read «sth».remote
for prefix, value in meu.suffix_config_items(ui, "path_pattern", "remote"):
for prefix, value in meu.rgxp_config_items(
ui, "path_pattern", re.compile(rgxp_prefix + "remote")):
if prefix not in self.patterns:
self.patterns[prefix] = PatternPair(prefix)
ui.debug(_("path_pattern: Parsing remote side of path pattern %s") % prefix)
self.patterns[prefix].learn_remote(value, ui)
# Read «sth».enforce
......@@ -194,9 +204,10 @@
if prefix not in self.patterns:
self.patterns[prefix] = PatternPair(prefix)
ui.debug(_("path_pattern: Parsing remote side of path pattern %s") % prefix)
self.patterns[prefix].learn_remote(value, ui)
# Read «sth».enforce
for prefix, value in meu.suffix_configbool_items(ui, "path_pattern", "enforce"):
for prefix, value in meu.rgxp_configbool_items(
ui, "path_pattern", re.compile(rgxp_prefix + "enforce")):
if prefix in self.patterns:
self.patterns[prefix].enforce = value
# Read «sth».alias
......@@ -200,7 +211,8 @@
if prefix in self.patterns:
self.patterns[prefix].enforce = value
# Read «sth».alias
for prefix, value in meu.suffix_config_items(ui, "path_pattern", "alias"):
for prefix, value in meu.rgxp_config_items(
ui, "path_pattern", re.compile(rgxp_prefix + "alias")):
if prefix in self.patterns:
self.patterns[prefix].alias = value
# Check for incomplete and invalid items
......
Reusing the same name for different patterns.
Reusing the same name for different patterns (short syntax).
$ WORK_DIR=${WORK_DIR-`pwd`/work}
$ rm -rf $WORK_DIR
......@@ -15,21 +15,16 @@
> [extensions]
> mercurial_path_pattern =
> [path_pattern]
> proda.local = $WORK_DIR/pylibs/{repo}
> proda.remote = ssh://pydev@pyhost.com/{repo:/=-}
> proda.alias = prod
> prodb.local = $WORK_DIR/js/libs/{repo}
> prodb.remote = https://johny@jshost.com/lib/{repo}
> prodb.alias = prod
> off1.local = $WORK_DIR/tracked/alah/beh
> off1.remote = git+ssh://joe@github.com/alah-beh
> off1.alias = official
> off2.local = $WORK_DIR/tracked/something
> off2.remote = https://bitbucket.com/messes
> off2.alias = official
> off3.local = $WORK_DIR/js/libs/xoxo
> off3.remote = https://nodesse.js.com/xoxo
> off3.alias = official
> prod.local = $WORK_DIR/pylibs/{repo}
> prod.remote = ssh://pydev@pyhost.com/{repo:/=-}
> prod.alt.local = $WORK_DIR/js/libs/{repo}
> prod.alt.remote = https://johny@jshost.com/lib/{repo}
> official.3.local = $WORK_DIR/js/libs/xoxo
> official.1.local = $WORK_DIR/tracked/alah/beh
> official.1.remote = git+ssh://joe@github.com/alah-beh
> official.2.local = $WORK_DIR/tracked/something
> official.2.remote = https://bitbucket.com/messes
> official.3.remote = https://nodesse.js.com/xoxo
> EOF
Creating some repos:
......@@ -71,3 +66,23 @@
official = https://bitbucket.com/messes
$ hg --cwd $WORK_DIR/tracked/something/else paths
And printed output:
$ hg list_path_patterns
Defined path patterns:
official
local: /tmp/cramtests-*/name-reuse-compact.t/work/tracked/alah/beh (glob)
remote: git+ssh://joe@github.com/alah-beh
official
local: /tmp/cramtests-*/name-reuse-compact.t/work/tracked/something (glob)
remote: https://bitbucket.com/messes
official
local: /tmp/cramtests-*/name-reuse-compact.t/work/js/libs/xoxo (glob)
remote: https://nodesse.js.com/xoxo
prod
local: /tmp/cramtests-*/name-reuse-compact.t/work/pylibs/{repo} (glob)
remote: ssh://pydev@pyhost.com/{repo:/=-}
prod
local: /tmp/cramtests-*/name-reuse-compact.t/work/js/libs/{repo} (glob)
remote: https://johny@jshost.com/lib/{repo}
......@@ -71,3 +71,23 @@
official = https://bitbucket.com/messes
$ hg --cwd $WORK_DIR/tracked/something/else paths
And printed output:
$ hg list_path_patterns
Defined path patterns:
official
local: /tmp/cramtests-*/name-reuse-long.t/work/tracked/alah/beh (glob)
remote: git+ssh://joe@github.com/alah-beh
official
local: /tmp/cramtests-*/name-reuse-long.t/work/tracked/something (glob)
remote: https://bitbucket.com/messes
official
local: /tmp/cramtests-*/name-reuse-long.t/work/js/libs/xoxo (glob)
remote: https://nodesse.js.com/xoxo
prod
local: /tmp/cramtests-*/name-reuse-long.t/work/pylibs/{repo} (glob)
remote: ssh://pydev@pyhost.com/{repo:/=-}
prod
local: /tmp/cramtests-*/name-reuse-long.t/work/js/libs/{repo} (glob)
remote: https://johny@jshost.com/lib/{repo}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment