fetch.py
196 lines
| 6.4 KiB
| text/x-python
|
PythonLexer
/ hgext / fetch.py
Vadim Gelfer
|
r2800 | # fetch.py - pull and merge remote changes | ||
# | ||||
# Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com> | ||||
# | ||||
Martin Geisler
|
r8225 | # This software may be used and distributed according to the terms of the | ||
Matt Mackall
|
r10263 | # GNU General Public License version 2 or any later version. | ||
Martin Geisler
|
r8228 | |||
Augie Fackler
|
r16669 | '''pull, update and merge in one command (DEPRECATED)''' | ||
Vadim Gelfer
|
r2800 | |||
Matt Harbison
|
r52756 | from __future__ import annotations | ||
Pulkit Goyal
|
r29121 | |||
Matt Mackall
|
r3891 | from mercurial.i18n import _ | ||
Augie Fackler
|
r43346 | from mercurial.node import short | ||
Pulkit Goyal
|
r29121 | from mercurial import ( | ||
cmdutil, | ||||
error, | ||||
exchange, | ||||
hg, | ||||
lock, | ||||
Pulkit Goyal
|
r34978 | pycompat, | ||
Yuya Nishihara
|
r32337 | registrar, | ||
Pulkit Goyal
|
r29121 | ) | ||
r47669 | from mercurial.utils import ( | |||
dateutil, | ||||
urlutil, | ||||
) | ||||
Vadim Gelfer
|
r2800 | |||
Pulkit Goyal
|
r29121 | release = lock.release | ||
Gregory Szorc
|
r21247 | cmdtable = {} | ||
Yuya Nishihara
|
r32337 | command = registrar.command(cmdtable) | ||
Augie Fackler
|
r29841 | # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for | ||
Augie Fackler
|
r25186 | # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should | ||
# be specifying the version(s) of Mercurial they are tested with, or | ||||
# leave the attribute unspecified. | ||||
Augie Fackler
|
r43347 | testedwith = b'ships-with-hg-core' | ||
Augie Fackler
|
r16743 | |||
Augie Fackler
|
r43346 | |||
@command( | ||||
Augie Fackler
|
r43347 | b'fetch', | ||
Augie Fackler
|
r43346 | [ | ||
( | ||||
Augie Fackler
|
r43347 | b'r', | ||
b'rev', | ||||
Augie Fackler
|
r43346 | [], | ||
Augie Fackler
|
r43347 | _(b'a specific revision you would like to pull'), | ||
_(b'REV'), | ||||
Augie Fackler
|
r43346 | ), | ||
Augie Fackler
|
r43347 | (b'', b'edit', None, _(b'invoke editor on commit messages')), | ||
(b'', b'force-editor', None, _(b'edit commit message (DEPRECATED)')), | ||||
(b'', b'switch-parent', None, _(b'switch parents when merging')), | ||||
Augie Fackler
|
r43346 | ] | ||
+ cmdutil.commitopts | ||||
+ cmdutil.commitopts2 | ||||
+ cmdutil.remoteopts, | ||||
Augie Fackler
|
r43347 | _(b'hg fetch [SOURCE]'), | ||
Augie Fackler
|
r43346 | helpcategory=command.CATEGORY_REMOTE_REPO_MANAGEMENT, | ||
) | ||||
Augie Fackler
|
r43347 | def fetch(ui, repo, source=b'default', **opts): | ||
Augie Fackler
|
r46554 | """pull changes from a remote repository, merge new changes if needed. | ||
Vadim Gelfer
|
r2800 | |||
Martin Geisler
|
r9258 | This finds all changes from the repository at the specified path | ||
or URL and adds them to the local repository. | ||||
Vadim Gelfer
|
r2800 | |||
Martin Geisler
|
r9258 | If the pulled changes add a new branch head, the head is | ||
automatically merged, and the result of the merge is committed. | ||||
Otherwise, the working directory is updated to include the new | ||||
changes. | ||||
Bryan O'Sullivan
|
r6206 | |||
Kevin Bullock
|
r16476 | When a merge is needed, the working directory is first updated to | ||
the newly pulled changes. Local changes are then merged into the | ||||
pulled changes. To switch the merge order, use --switch-parent. | ||||
Thomas Arendsen Hein
|
r6163 | |||
Martin Geisler
|
r10973 | See :hg:`help dates` for a list of formats valid for -d/--date. | ||
Matt Mackall
|
r12711 | |||
Returns 0 on success. | ||||
Augie Fackler
|
r46554 | """ | ||
Vadim Gelfer
|
r2800 | |||
Matt Harbison
|
r51769 | date = opts.get('date') | ||
Dirkjan Ochtman
|
r6941 | if date: | ||
Matt Harbison
|
r51769 | opts['date'] = dateutil.parsedate(date) | ||
Dirkjan Ochtman
|
r6941 | |||
Martin von Zweigbergk
|
r41444 | parent = repo.dirstate.p1() | ||
Sune Foldager
|
r7049 | branch = repo.dirstate.branch() | ||
Brodie Rao
|
r16719 | try: | ||
branchnode = repo.branchtip(branch) | ||||
except error.RepoLookupError: | ||||
branchnode = None | ||||
Sune Foldager
|
r7049 | if parent != branchnode: | ||
Augie Fackler
|
r43346 | raise error.Abort( | ||
Augie Fackler
|
r43347 | _(b'working directory not at branch tip'), | ||
hint=_(b"use 'hg update' to check out branch tip"), | ||||
Augie Fackler
|
r43346 | ) | ||
Dirkjan Ochtman
|
r6941 | |||
wlock = lock = None | ||||
try: | ||||
wlock = repo.wlock() | ||||
lock = repo.lock() | ||||
Martin von Zweigbergk
|
r22676 | cmdutil.bailifchanged(repo) | ||
Benjamin Pollack
|
r7854 | bheads = repo.branchheads(branch) | ||
bheads = [head for head in bheads if len(repo[head].children()) == 0] | ||||
if len(bheads) > 1: | ||||
Augie Fackler
|
r43346 | raise error.Abort( | ||
_( | ||||
Augie Fackler
|
r43347 | b'multiple heads in this branch ' | ||
b'(use "hg heads ." and "hg merge" to merge)' | ||||
Augie Fackler
|
r43346 | ) | ||
) | ||||
Dirkjan Ochtman
|
r6941 | |||
r50626 | path = urlutil.get_unique_pull_path_obj(b'fetch', ui, source) | |||
Matt Harbison
|
r51769 | other = hg.peer(repo, pycompat.byteskwargs(opts), path) | ||
r50626 | ui.status(_(b'pulling from %s\n') % urlutil.hidepassword(path.loc)) | |||
Dirkjan Ochtman
|
r6941 | revs = None | ||
Matt Harbison
|
r51769 | if opts['rev']: | ||
Benoit Boissinot
|
r8532 | try: | ||
Matt Harbison
|
r51769 | revs = [other.lookup(rev) for rev in opts['rev']] | ||
Benoit Boissinot
|
r8532 | except error.CapabilityError: | ||
Augie Fackler
|
r43346 | err = _( | ||
Augie Fackler
|
r43347 | b"other repository doesn't support revision lookup, " | ||
b"so a rev cannot be specified." | ||||
Augie Fackler
|
r43346 | ) | ||
Pierre-Yves David
|
r26587 | raise error.Abort(err) | ||
Dirkjan Ochtman
|
r6941 | |||
Sune Foldager
|
r7007 | # Are there any changes at all? | ||
Pierre-Yves David
|
r22697 | modheads = exchange.pull(repo, other, heads=revs).cgresult | ||
Vadim Gelfer
|
r2800 | if modheads == 0: | ||
return 0 | ||||
Dirkjan Ochtman
|
r6941 | |||
Sune Foldager
|
r7007 | # Is this a simple fast-forward along the current branch? | ||
newheads = repo.branchheads(branch) | ||||
newchildren = repo.changelog.nodesbetween([parent], newheads)[2] | ||||
Matt Mackall
|
r15748 | if len(newheads) == 1 and len(newchildren): | ||
Sune Foldager
|
r7007 | if newchildren[0] != parent: | ||
Matt Mackall
|
r16091 | return hg.update(repo, newchildren[0]) | ||
Sune Foldager
|
r7007 | else: | ||
Matt Mackall
|
r12711 | return 0 | ||
Sune Foldager
|
r7007 | |||
# Are there more than one additional branch heads? | ||||
newchildren = [n for n in newchildren if n != parent] | ||||
Vadim Gelfer
|
r2800 | newparent = parent | ||
if newchildren: | ||||
newparent = newchildren[0] | ||||
Matt Mackall
|
r4917 | hg.clean(repo, newparent) | ||
Sune Foldager
|
r7007 | newheads = [n for n in newheads if n != newparent] | ||
Bryan O'Sullivan
|
r6206 | if len(newheads) > 1: | ||
Augie Fackler
|
r43346 | ui.status( | ||
_( | ||||
Augie Fackler
|
r43347 | b'not merging with %d other new branch heads ' | ||
b'(use "hg heads ." and "hg merge" to merge them)\n' | ||||
Augie Fackler
|
r43346 | ) | ||
% (len(newheads) - 1) | ||||
) | ||||
Matt Mackall
|
r12711 | return 1 | ||
Sune Foldager
|
r7007 | |||
Matt Mackall
|
r15749 | if not newheads: | ||
return 0 | ||||
Sune Foldager
|
r7007 | # Otherwise, let's merge. | ||
Bryan O'Sullivan
|
r6206 | err = False | ||
if newheads: | ||||
# By default, we consider the repository we're pulling | ||||
# *from* as authoritative, so we merge our changes into | ||||
# theirs. | ||||
Matt Harbison
|
r51769 | if opts['switch_parent']: | ||
Bryan O'Sullivan
|
r6206 | firstparent, secondparent = newparent, newheads[0] | ||
else: | ||||
firstparent, secondparent = newheads[0], newparent | ||||
Augie Fackler
|
r43346 | ui.status( | ||
Augie Fackler
|
r43347 | _(b'updating to %d:%s\n') | ||
Augie Fackler
|
r43346 | % (repo.changelog.rev(firstparent), short(firstparent)) | ||
) | ||||
Bryan O'Sullivan
|
r6206 | hg.clean(repo, firstparent) | ||
Martin von Zweigbergk
|
r44916 | p2ctx = repo[secondparent] | ||
Augie Fackler
|
r43346 | ui.status( | ||
Martin von Zweigbergk
|
r44916 | _(b'merging with %d:%s\n') % (p2ctx.rev(), short(secondparent)) | ||
Augie Fackler
|
r43346 | ) | ||
Martin von Zweigbergk
|
r44916 | err = hg.merge(p2ctx, remind=False) | ||
Dirkjan Ochtman
|
r6941 | |||
Vadim Gelfer
|
r2800 | if not err: | ||
Martin Geisler
|
r9183 | # we don't translate commit messages | ||
Matt Harbison
|
r51769 | message = cmdutil.logmessage(ui, pycompat.byteskwargs(opts)) or ( | ||
r47669 | b'Automated merge with %s' % urlutil.removeauth(other.url()) | |||
Augie Fackler
|
r43346 | ) | ||
Matt Harbison
|
r51769 | editopt = opts.get('edit') or opts.get('force_editor') | ||
Augie Fackler
|
r43347 | editor = cmdutil.getcommiteditor(edit=editopt, editform=b'fetch') | ||
Matt Harbison
|
r51769 | n = repo.commit(message, opts['user'], opts['date'], editor=editor) | ||
Augie Fackler
|
r43346 | ui.status( | ||
Martin von Zweigbergk
|
r43387 | _(b'new changeset %d:%s merges remote changes with local\n') | ||
Augie Fackler
|
r43346 | % (repo.changelog.rev(n), short(n)) | ||
) | ||||
Bryan O'Sullivan
|
r6206 | |||
Matt Mackall
|
r12711 | return err | ||
Vadim Gelfer
|
r2825 | finally: | ||
Ronny Pfannschmidt
|
r8112 | release(lock, wlock) | ||