hgext/chainsaw.py
changeset 51433 d36a81d70f25
parent 51431 fe68a2dc0bf2
child 51434 dd519ea71416
equal deleted inserted replaced
51432:e79c7320605f 51433:d36a81d70f25
    24 from mercurial.i18n import _
    24 from mercurial.i18n import _
    25 from mercurial import (
    25 from mercurial import (
    26     cmdutil,
    26     cmdutil,
    27     commands,
    27     commands,
    28     error,
    28     error,
       
    29     localrepo,
    29     registrar,
    30     registrar,
       
    31 )
       
    32 from mercurial.utils import (
       
    33     urlutil,
    30 )
    34 )
    31 
    35 
    32 cmdtable = {}
    36 cmdtable = {}
    33 command = registrar.command(cmdtable)
    37 command = registrar.command(cmdtable)
    34 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
    38 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
    71             b'',
    75             b'',
    72             b'source',
    76             b'source',
    73             b'',
    77             b'',
    74             _(b'repository to clone from'),
    78             _(b'repository to clone from'),
    75         ),
    79         ),
       
    80         (
       
    81             b'',
       
    82             b'dest',
       
    83             b'',
       
    84             _(b'repository to update to REV (possibly cloning)'),
       
    85         ),
       
    86         (
       
    87             b'',
       
    88             b'initial-clone-minimal',
       
    89             False,
       
    90             _(
       
    91                 b'Pull only the prescribed revision upon initial cloning. '
       
    92                 b'This has the side effect of ignoring clone-bundles, '
       
    93                 b'which if often slower on the client side and stressful '
       
    94                 b'to the server than applying available clone bundles.'
       
    95             ),
       
    96         ),
    76     ],
    97     ],
    77     _(b'hg admin::chainsaw-update [OPTION] --rev REV --source SOURCE...'),
    98     _(
       
    99         b'hg admin::chainsaw-update [OPTION] --rev REV --source SOURCE --dest DEST'
       
   100     ),
    78     helpbasic=True,
   101     helpbasic=True,
       
   102     norepo=True,
    79 )
   103 )
    80 def update(ui, repo, **opts):
   104 def update(ui, **opts):
    81     """pull and update to a given revision, no matter what, (EXPERIMENTAL)
   105     """pull and update to a given revision, no matter what, (EXPERIMENTAL)
    82 
   106 
    83     Context of application: *some* Continuous Integration (CI) systems,
   107     Context of application: *some* Continuous Integration (CI) systems,
    84     packaging or deployment tools.
   108     packaging or deployment tools.
    85 
   109 
    86     Wanted end result: clean working directory updated at the given revision.
   110     Wanted end result: local repository at the given REPO_PATH, having the
       
   111     latest changes to the given revision and with a clean working directory
       
   112     updated at the given revision.
    87 
   113 
    88     chainsaw-update pulls from one source, then updates the working directory
   114     chainsaw-update pulls from one source, then updates the working directory
    89     to the given revision, overcoming anything that would stand in the way.
   115     to the given revision, overcoming anything that would stand in the way.
    90 
   116 
    91     By default, it will:
   117     By default, it will:
    92 
   118 
       
   119     - clone if the local repo does not exist yet, **removing any directory
       
   120       at the given path** that would not be a Mercurial repository.
       
   121       The initial clone is full by default, so that clonebundles can be
       
   122       applied. Use the --initial-clone-minimal flag to avoid this.
    93     - break locks if needed, leading to possible corruption if there
   123     - break locks if needed, leading to possible corruption if there
    94       is a concurrent write access.
   124       is a concurrent write access.
    95     - perform recovery actions if needed
   125     - perform recovery actions if needed
    96     - revert any local modification.
   126     - revert any local modification.
    97     - purge unknown and ignored files.
   127     - purge unknown and ignored files.
   114     repositories), an exceptional recloning is better than missing a release
   144     repositories), an exceptional recloning is better than missing a release
   115     deadline.
   145     deadline.
   116     """
   146     """
   117     rev = opts['rev']
   147     rev = opts['rev']
   118     source = opts['source']
   148     source = opts['source']
       
   149     repo_path = opts['dest']
   119     if not rev:
   150     if not rev:
   120         raise error.InputError(_(b'specify a target revision with --rev'))
   151         raise error.InputError(_(b'specify a target revision with --rev'))
   121     if not source:
   152     if not source:
   122         raise error.InputError(_(b'specify a pull path with --source'))
   153         raise error.InputError(_(b'specify a pull path with --source'))
       
   154     if not repo_path:
       
   155         raise error.InputError(_(b'specify a repo path with --dest'))
       
   156     repo_path = urlutil.urllocalpath(repo_path)
       
   157 
       
   158     try:
       
   159         repo = localrepo.instance(ui, repo_path, create=False)
       
   160         repo_created = False
       
   161         ui.status(_(b'loaded repository at "%s"\n' % repo_path))
       
   162     except error.RepoError:
       
   163         try:
       
   164             shutil.rmtree(repo_path)
       
   165         except FileNotFoundError:
       
   166             ui.status(_(b'no such directory: "%s"\n' % repo_path))
       
   167         else:
       
   168             ui.status(
       
   169                 _(
       
   170                     b'removed non-repository file or directory '
       
   171                     b'at "%s"' % repo_path
       
   172                 )
       
   173             )
       
   174 
       
   175         ui.status(_(b'creating repository at "%s"\n' % repo_path))
       
   176         repo = localrepo.instance(ui, repo_path, create=True)
       
   177         repo_created = True
       
   178 
   123     if repo.svfs.tryunlink(b'lock'):
   179     if repo.svfs.tryunlink(b'lock'):
   124         ui.status(_(b'had to break store lock\n'))
   180         ui.status(_(b'had to break store lock\n'))
   125     if repo.vfs.tryunlink(b'wlock'):
   181     if repo.vfs.tryunlink(b'wlock'):
   126         ui.status(_(b'had to break working copy lock\n'))
   182         ui.status(_(b'had to break working copy lock\n'))
   127 
   183 
   128     ui.status(_(b'recovering after interrupted transaction, if any\n'))
   184     ui.status(_(b'recovering after interrupted transaction, if any\n'))
   129     repo.recover()
   185     repo.recover()
   130 
   186 
   131     ui.status(_(b'pulling from %s\n') % source)
   187     ui.status(_(b'pulling from %s\n') % source)
       
   188     if repo_created and not opts.get('initial_clone_minimal'):
       
   189         pull_revs = []
       
   190     else:
       
   191         pull_revs = [rev]
   132     overrides = {(b'ui', b'quiet'): True}
   192     overrides = {(b'ui', b'quiet'): True}
   133     with ui.configoverride(overrides, b'chainsaw-update'):
   193     with repo.ui.configoverride(overrides, b'chainsaw-update'):
   134         pull = cmdutil.findcmd(b'pull', commands.table)[1][0]
   194         pull = cmdutil.findcmd(b'pull', commands.table)[1][0]
   135         pull(ui, repo, source, rev=[rev], remote_hidden=False)
   195         pull(repo.ui, repo, source, rev=pull_revs, remote_hidden=False)
   136 
   196 
   137     purge = cmdutil.findcmd(b'purge', commands.table)[1][0]
   197     purge = cmdutil.findcmd(b'purge', commands.table)[1][0]
   138     purge(
   198     purge(
   139         ui,
   199         ui,
   140         repo,
   200         repo,