mercurial/subrepo.py
author Erik Zielke <ez@aragost.com>
Mon, 29 Nov 2010 09:37:23 +0100
changeset 13155 f02d7a562a21
parent 13153 dca5488f0e4f
child 13160 07d08c130892
permissions -rw-r--r--
subrepo: avoids empty commit when .hgsubstate is dirty (issue2403) This patch avoids empty commit when .hgsubstate is dirty. Empty commit was caused by .hgsubstate being updated back to the state of the working copy parent when committing, if a user had changed it manually and not made any changes in subrepositories. The subrepository state from the working copies parent is compared with the state calculated as a result of trying to commit the subrepositories. If the two states are the same, then return None otherwise the commit is just done. The line: "committing subrepository x" will be written if there is nothing committed, but .hgsubstate is dirty for x subrepository.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
8812
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     1
# subrepo.py - sub-repository handling for Mercurial
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     2
#
10324
55d134ef8ab7 subrepo: correct copyright
David Soria Parra <dsp@php.net>
parents: 10299
diff changeset
     3
# Copyright 2009-2010 Matt Mackall <mpm@selenic.com>
8812
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     4
#
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 10251
diff changeset
     6
# GNU General Public License version 2 or any later version.
8812
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
     7
11109
a2bc2f2d77a9 subrepo: normalize path part of URLs so that pulling subrepos from webdir works
Edouard Gomez <ed.gomez@free.fr>
parents: 11078
diff changeset
     8
import errno, os, re, xml.dom.minidom, shutil, urlparse, posixpath
13027
7f2ecb64140d subrepo: archive git subrepos
Eric Eisner <ede@mit.edu>
parents: 13018
diff changeset
     9
import stat, subprocess, tarfile
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
    10
from i18n import _
12167
d2c5b0927c28 diff: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12166
diff changeset
    11
import config, util, node, error, cmdutil
9092
9aebeea7ac00 subrepo: use hg.repository instead of creating localrepo directly
Abderrahim Kitouni <a.kitouni@gmail.com>
parents: 9049
diff changeset
    12
hg = None
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
    13
10177
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
    14
nullstate = ('', '', 'empty')
8812
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    15
13155
f02d7a562a21 subrepo: avoids empty commit when .hgsubstate is dirty (issue2403)
Erik Zielke <ez@aragost.com>
parents: 13153
diff changeset
    16
f02d7a562a21 subrepo: avoids empty commit when .hgsubstate is dirty (issue2403)
Erik Zielke <ez@aragost.com>
parents: 13153
diff changeset
    17
def substate(ctx):
f02d7a562a21 subrepo: avoids empty commit when .hgsubstate is dirty (issue2403)
Erik Zielke <ez@aragost.com>
parents: 13153
diff changeset
    18
    rev = {}
f02d7a562a21 subrepo: avoids empty commit when .hgsubstate is dirty (issue2403)
Erik Zielke <ez@aragost.com>
parents: 13153
diff changeset
    19
    if '.hgsubstate' in ctx:
f02d7a562a21 subrepo: avoids empty commit when .hgsubstate is dirty (issue2403)
Erik Zielke <ez@aragost.com>
parents: 13153
diff changeset
    20
        try:
f02d7a562a21 subrepo: avoids empty commit when .hgsubstate is dirty (issue2403)
Erik Zielke <ez@aragost.com>
parents: 13153
diff changeset
    21
            for l in ctx['.hgsubstate'].data().splitlines():
f02d7a562a21 subrepo: avoids empty commit when .hgsubstate is dirty (issue2403)
Erik Zielke <ez@aragost.com>
parents: 13153
diff changeset
    22
                revision, path = l.split(" ", 1)
f02d7a562a21 subrepo: avoids empty commit when .hgsubstate is dirty (issue2403)
Erik Zielke <ez@aragost.com>
parents: 13153
diff changeset
    23
                rev[path] = revision
f02d7a562a21 subrepo: avoids empty commit when .hgsubstate is dirty (issue2403)
Erik Zielke <ez@aragost.com>
parents: 13153
diff changeset
    24
        except IOError as err:
f02d7a562a21 subrepo: avoids empty commit when .hgsubstate is dirty (issue2403)
Erik Zielke <ez@aragost.com>
parents: 13153
diff changeset
    25
            if err.errno != errno.ENOENT:
f02d7a562a21 subrepo: avoids empty commit when .hgsubstate is dirty (issue2403)
Erik Zielke <ez@aragost.com>
parents: 13153
diff changeset
    26
                raise
f02d7a562a21 subrepo: avoids empty commit when .hgsubstate is dirty (issue2403)
Erik Zielke <ez@aragost.com>
parents: 13153
diff changeset
    27
    return rev
f02d7a562a21 subrepo: avoids empty commit when .hgsubstate is dirty (issue2403)
Erik Zielke <ez@aragost.com>
parents: 13153
diff changeset
    28
11775
a8614c5a5e9a subrepos: support remapping of .hgsub source paths
Martin Geisler <mg@lazybytes.net>
parents: 11572
diff changeset
    29
def state(ctx, ui):
11571
636554d58665 subrepo: docstrings
Mads Kiilerich <mads@kiilerich.com>
parents: 11470
diff changeset
    30
    """return a state dict, mapping subrepo paths configured in .hgsub
636554d58665 subrepo: docstrings
Mads Kiilerich <mads@kiilerich.com>
parents: 11470
diff changeset
    31
    to tuple: (source from .hgsub, revision from .hgsubstate, kind
636554d58665 subrepo: docstrings
Mads Kiilerich <mads@kiilerich.com>
parents: 11470
diff changeset
    32
    (key in types dict))
636554d58665 subrepo: docstrings
Mads Kiilerich <mads@kiilerich.com>
parents: 11470
diff changeset
    33
    """
8812
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    34
    p = config.config()
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    35
    def read(f, sections=None, remap=None):
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    36
        if f in ctx:
13017
d0e21c5fde41 subrepo: handle missing subrepo spec file as removed
Patrick Mezard <pmezard@gmail.com>
parents: 13015
diff changeset
    37
            try:
d0e21c5fde41 subrepo: handle missing subrepo spec file as removed
Patrick Mezard <pmezard@gmail.com>
parents: 13015
diff changeset
    38
                data = ctx[f].data()
d0e21c5fde41 subrepo: handle missing subrepo spec file as removed
Patrick Mezard <pmezard@gmail.com>
parents: 13015
diff changeset
    39
            except IOError, err:
d0e21c5fde41 subrepo: handle missing subrepo spec file as removed
Patrick Mezard <pmezard@gmail.com>
parents: 13015
diff changeset
    40
                if err.errno != errno.ENOENT:
d0e21c5fde41 subrepo: handle missing subrepo spec file as removed
Patrick Mezard <pmezard@gmail.com>
parents: 13015
diff changeset
    41
                    raise
d0e21c5fde41 subrepo: handle missing subrepo spec file as removed
Patrick Mezard <pmezard@gmail.com>
parents: 13015
diff changeset
    42
                # handle missing subrepo spec files as removed
d0e21c5fde41 subrepo: handle missing subrepo spec file as removed
Patrick Mezard <pmezard@gmail.com>
parents: 13015
diff changeset
    43
                ui.warn(_("warning: subrepo spec file %s not found\n") % f)
d0e21c5fde41 subrepo: handle missing subrepo spec file as removed
Patrick Mezard <pmezard@gmail.com>
parents: 13015
diff changeset
    44
                return
d0e21c5fde41 subrepo: handle missing subrepo spec file as removed
Patrick Mezard <pmezard@gmail.com>
parents: 13015
diff changeset
    45
            p.parse(f, data, sections, remap, read)
10174
65b6dc44cdbf subrepo: fix includes support in .hgsub
Matt Mackall <mpm@selenic.com>
parents: 10069
diff changeset
    46
        else:
65b6dc44cdbf subrepo: fix includes support in .hgsub
Matt Mackall <mpm@selenic.com>
parents: 10069
diff changeset
    47
            raise util.Abort(_("subrepo spec file %s not found") % f)
65b6dc44cdbf subrepo: fix includes support in .hgsub
Matt Mackall <mpm@selenic.com>
parents: 10069
diff changeset
    48
65b6dc44cdbf subrepo: fix includes support in .hgsub
Matt Mackall <mpm@selenic.com>
parents: 10069
diff changeset
    49
    if '.hgsub' in ctx:
65b6dc44cdbf subrepo: fix includes support in .hgsub
Matt Mackall <mpm@selenic.com>
parents: 10069
diff changeset
    50
        read('.hgsub')
8812
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    51
11775
a8614c5a5e9a subrepos: support remapping of .hgsub source paths
Martin Geisler <mg@lazybytes.net>
parents: 11572
diff changeset
    52
    for path, src in ui.configitems('subpaths'):
a8614c5a5e9a subrepos: support remapping of .hgsub source paths
Martin Geisler <mg@lazybytes.net>
parents: 11572
diff changeset
    53
        p.set('subpaths', path, src, ui.configsource('subpaths', path))
a8614c5a5e9a subrepos: support remapping of .hgsub source paths
Martin Geisler <mg@lazybytes.net>
parents: 11572
diff changeset
    54
13155
f02d7a562a21 subrepo: avoids empty commit when .hgsubstate is dirty (issue2403)
Erik Zielke <ez@aragost.com>
parents: 13153
diff changeset
    55
    rev = substate(ctx)
8812
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    56
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    57
    state = {}
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    58
    for path, src in p[''].items():
10177
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
    59
        kind = 'hg'
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
    60
        if src.startswith('['):
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
    61
            if ']' not in src:
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
    62
                raise util.Abort(_('missing ] in subrepo source'))
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
    63
            kind, src = src.split(']', 1)
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
    64
            kind = kind[1:]
11775
a8614c5a5e9a subrepos: support remapping of .hgsub source paths
Martin Geisler <mg@lazybytes.net>
parents: 11572
diff changeset
    65
a8614c5a5e9a subrepos: support remapping of .hgsub source paths
Martin Geisler <mg@lazybytes.net>
parents: 11572
diff changeset
    66
        for pattern, repl in p.items('subpaths'):
11961
f3075ffa6b30 subrepos: handle backslashes in subpaths
Martin Geisler <mg@lazybytes.net>
parents: 11775
diff changeset
    67
            # Turn r'C:\foo\bar' into r'C:\\foo\\bar' since re.sub
f3075ffa6b30 subrepos: handle backslashes in subpaths
Martin Geisler <mg@lazybytes.net>
parents: 11775
diff changeset
    68
            # does a string decode.
f3075ffa6b30 subrepos: handle backslashes in subpaths
Martin Geisler <mg@lazybytes.net>
parents: 11775
diff changeset
    69
            repl = repl.encode('string-escape')
f3075ffa6b30 subrepos: handle backslashes in subpaths
Martin Geisler <mg@lazybytes.net>
parents: 11775
diff changeset
    70
            # However, we still want to allow back references to go
f3075ffa6b30 subrepos: handle backslashes in subpaths
Martin Geisler <mg@lazybytes.net>
parents: 11775
diff changeset
    71
            # through unharmed, so we turn r'\\1' into r'\1'. Again,
f3075ffa6b30 subrepos: handle backslashes in subpaths
Martin Geisler <mg@lazybytes.net>
parents: 11775
diff changeset
    72
            # extra escapes are needed because re.sub string decodes.
f3075ffa6b30 subrepos: handle backslashes in subpaths
Martin Geisler <mg@lazybytes.net>
parents: 11775
diff changeset
    73
            repl = re.sub(r'\\\\([0-9]+)', r'\\\1', repl)
11775
a8614c5a5e9a subrepos: support remapping of .hgsub source paths
Martin Geisler <mg@lazybytes.net>
parents: 11572
diff changeset
    74
            try:
a8614c5a5e9a subrepos: support remapping of .hgsub source paths
Martin Geisler <mg@lazybytes.net>
parents: 11572
diff changeset
    75
                src = re.sub(pattern, repl, src, 1)
a8614c5a5e9a subrepos: support remapping of .hgsub source paths
Martin Geisler <mg@lazybytes.net>
parents: 11572
diff changeset
    76
            except re.error, e:
a8614c5a5e9a subrepos: support remapping of .hgsub source paths
Martin Geisler <mg@lazybytes.net>
parents: 11572
diff changeset
    77
                raise util.Abort(_("bad subrepository pattern in %s: %s")
a8614c5a5e9a subrepos: support remapping of .hgsub source paths
Martin Geisler <mg@lazybytes.net>
parents: 11572
diff changeset
    78
                                 % (p.source('subpaths', pattern), e))
a8614c5a5e9a subrepos: support remapping of .hgsub source paths
Martin Geisler <mg@lazybytes.net>
parents: 11572
diff changeset
    79
10457
4f38d03d4975 subrepo: make sure that the source path is stripped
David Soria Parra <dsp@php.net>
parents: 10378
diff changeset
    80
        state[path] = (src.strip(), rev.get(path, ''), kind)
8812
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    81
859f841937d0 subrepo: introduce basic state parsing
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
    82
    return state
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
    83
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
    84
def writestate(repo, state):
11571
636554d58665 subrepo: docstrings
Mads Kiilerich <mads@kiilerich.com>
parents: 11470
diff changeset
    85
    """rewrite .hgsubstate in (outer) repo with these subrepo states"""
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
    86
    repo.wwrite('.hgsubstate',
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
    87
                ''.join(['%s %s\n' % (state[s][1], s)
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
    88
                         for s in sorted(state)]), '')
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
    89
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
    90
def submerge(repo, wctx, mctx, actx):
11571
636554d58665 subrepo: docstrings
Mads Kiilerich <mads@kiilerich.com>
parents: 11470
diff changeset
    91
    """delegated from merge.applyupdates: merging of .hgsubstate file
636554d58665 subrepo: docstrings
Mads Kiilerich <mads@kiilerich.com>
parents: 11470
diff changeset
    92
    in working context, merging context and ancestor context"""
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
    93
    if mctx == actx: # backwards?
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
    94
        actx = wctx.p1()
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
    95
    s1 = wctx.substate
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
    96
    s2 = mctx.substate
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
    97
    sa = actx.substate
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
    98
    sm = {}
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
    99
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
   100
    repo.ui.debug("subrepo merge %s %s %s\n" % (wctx, mctx, actx))
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
   101
9779
58a6f3f4d553 subrepo: add some debug output to submerge
Matt Mackall <mpm@selenic.com>
parents: 9752
diff changeset
   102
    def debug(s, msg, r=""):
58a6f3f4d553 subrepo: add some debug output to submerge
Matt Mackall <mpm@selenic.com>
parents: 9752
diff changeset
   103
        if r:
10177
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
   104
            r = "%s:%s:%s" % r
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
   105
        repo.ui.debug("  subrepo %s: %s %s\n" % (s, msg, r))
9779
58a6f3f4d553 subrepo: add some debug output to submerge
Matt Mackall <mpm@selenic.com>
parents: 9752
diff changeset
   106
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   107
    for s, l in s1.items():
11470
34e33d50c26b subrepo: correctly handle update -C with modified subrepos (issue2022)
Matt Mackall <mpm@selenic.com>
parents: 11463
diff changeset
   108
        a = sa.get(s, nullstate)
11463
f0ea93557133 subrepo: fix recording of + in .hgsubstate (issue2217)
Matt Mackall <mpm@selenic.com>
parents: 11455
diff changeset
   109
        ld = l # local state with possible dirty flag for compares
11470
34e33d50c26b subrepo: correctly handle update -C with modified subrepos (issue2022)
Matt Mackall <mpm@selenic.com>
parents: 11463
diff changeset
   110
        if wctx.sub(s).dirty():
11463
f0ea93557133 subrepo: fix recording of + in .hgsubstate (issue2217)
Matt Mackall <mpm@selenic.com>
parents: 11455
diff changeset
   111
            ld = (l[0], l[1] + "+")
11470
34e33d50c26b subrepo: correctly handle update -C with modified subrepos (issue2022)
Matt Mackall <mpm@selenic.com>
parents: 11463
diff changeset
   112
        if wctx == actx: # overwrite
34e33d50c26b subrepo: correctly handle update -C with modified subrepos (issue2022)
Matt Mackall <mpm@selenic.com>
parents: 11463
diff changeset
   113
            a = ld
11463
f0ea93557133 subrepo: fix recording of + in .hgsubstate (issue2217)
Matt Mackall <mpm@selenic.com>
parents: 11455
diff changeset
   114
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   115
        if s in s2:
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   116
            r = s2[s]
11463
f0ea93557133 subrepo: fix recording of + in .hgsubstate (issue2217)
Matt Mackall <mpm@selenic.com>
parents: 11455
diff changeset
   117
            if ld == r or r == a: # no change or local is newer
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   118
                sm[s] = l
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   119
                continue
11463
f0ea93557133 subrepo: fix recording of + in .hgsubstate (issue2217)
Matt Mackall <mpm@selenic.com>
parents: 11455
diff changeset
   120
            elif ld == a: # other side changed
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
   121
                debug(s, "other changed, get", r)
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   122
                wctx.sub(s).get(r)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   123
                sm[s] = r
11463
f0ea93557133 subrepo: fix recording of + in .hgsubstate (issue2217)
Matt Mackall <mpm@selenic.com>
parents: 11455
diff changeset
   124
            elif ld[0] != r[0]: # sources differ
9048
86b4a9b0ddda ui: extract choice from prompt
Simon Heimberg <simohe@besonet.ch>
parents: 8997
diff changeset
   125
                if repo.ui.promptchoice(
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   126
                    _(' subrepository sources for %s differ\n'
8908
105343f9f744 Fix warning: Seen unexpected token "%"
Dongsheng Song <dongsheng.song@gmail.com>
parents: 8815
diff changeset
   127
                      'use (l)ocal source (%s) or (r)emote source (%s)?')
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   128
                      % (s, l[0], r[0]),
9048
86b4a9b0ddda ui: extract choice from prompt
Simon Heimberg <simohe@besonet.ch>
parents: 8997
diff changeset
   129
                      (_('&Local'), _('&Remote')), 0):
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
   130
                    debug(s, "prompt changed, get", r)
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   131
                    wctx.sub(s).get(r)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   132
                    sm[s] = r
11463
f0ea93557133 subrepo: fix recording of + in .hgsubstate (issue2217)
Matt Mackall <mpm@selenic.com>
parents: 11455
diff changeset
   133
            elif ld[1] == a[1]: # local side is unchanged
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
   134
                debug(s, "other side changed, get", r)
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   135
                wctx.sub(s).get(r)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   136
                sm[s] = r
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   137
            else:
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
   138
                debug(s, "both sides changed, merge with", r)
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   139
                wctx.sub(s).merge(r)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   140
                sm[s] = l
11463
f0ea93557133 subrepo: fix recording of + in .hgsubstate (issue2217)
Matt Mackall <mpm@selenic.com>
parents: 11455
diff changeset
   141
        elif ld == a: # remote removed, local unchanged
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
   142
            debug(s, "remote removed, remove")
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   143
            wctx.sub(s).remove()
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   144
        else:
9048
86b4a9b0ddda ui: extract choice from prompt
Simon Heimberg <simohe@besonet.ch>
parents: 8997
diff changeset
   145
            if repo.ui.promptchoice(
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   146
                _(' local changed subrepository %s which remote removed\n'
8908
105343f9f744 Fix warning: Seen unexpected token "%"
Dongsheng Song <dongsheng.song@gmail.com>
parents: 8815
diff changeset
   147
                  'use (c)hanged version or (d)elete?') % s,
9049
38b5d5e0efab filemerge, subrepo: correct indention
Martin Geisler <mg@lazybytes.net>
parents: 9048
diff changeset
   148
                (_('&Changed'), _('&Delete')), 0):
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
   149
                debug(s, "prompt remove")
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   150
                wctx.sub(s).remove()
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   151
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   152
    for s, r in s2.items():
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   153
        if s in s1:
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   154
            continue
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   155
        elif s not in sa:
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
   156
            debug(s, "remote added, get", r)
10175
fc32b2fc468e subrepo: load from a context where the subrepo exists
Augie Fackler <durin42@gmail.com>
parents: 10174
diff changeset
   157
            mctx.sub(s).get(r)
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   158
            sm[s] = r
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   159
        elif r != sa[s]:
9048
86b4a9b0ddda ui: extract choice from prompt
Simon Heimberg <simohe@besonet.ch>
parents: 8997
diff changeset
   160
            if repo.ui.promptchoice(
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   161
                _(' remote changed subrepository %s which local removed\n'
8908
105343f9f744 Fix warning: Seen unexpected token "%"
Dongsheng Song <dongsheng.song@gmail.com>
parents: 8815
diff changeset
   162
                  'use (c)hanged version or (d)elete?') % s,
9049
38b5d5e0efab filemerge, subrepo: correct indention
Martin Geisler <mg@lazybytes.net>
parents: 9048
diff changeset
   163
                (_('&Changed'), _('&Delete')), 0) == 0:
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
   164
                debug(s, "prompt recreate", r)
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   165
                wctx.sub(s).get(r)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   166
                sm[s] = r
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   167
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   168
    # record merged .hgsubstate
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   169
    writestate(repo, sm)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   170
12752
18b5b6392fcf subrepo: rename relpath to subrelpath and introduce reporelpath
Mads Kiilerich <mads@kiilerich.com>
parents: 12506
diff changeset
   171
def reporelpath(repo):
18b5b6392fcf subrepo: rename relpath to subrelpath and introduce reporelpath
Mads Kiilerich <mads@kiilerich.com>
parents: 12506
diff changeset
   172
    """return path to this (sub)repo as seen from outermost repo"""
18b5b6392fcf subrepo: rename relpath to subrelpath and introduce reporelpath
Mads Kiilerich <mads@kiilerich.com>
parents: 12506
diff changeset
   173
    parent = repo
18b5b6392fcf subrepo: rename relpath to subrelpath and introduce reporelpath
Mads Kiilerich <mads@kiilerich.com>
parents: 12506
diff changeset
   174
    while hasattr(parent, '_subparent'):
18b5b6392fcf subrepo: rename relpath to subrelpath and introduce reporelpath
Mads Kiilerich <mads@kiilerich.com>
parents: 12506
diff changeset
   175
        parent = parent._subparent
18b5b6392fcf subrepo: rename relpath to subrelpath and introduce reporelpath
Mads Kiilerich <mads@kiilerich.com>
parents: 12506
diff changeset
   176
    return repo.root[len(parent.root)+1:]
18b5b6392fcf subrepo: rename relpath to subrelpath and introduce reporelpath
Mads Kiilerich <mads@kiilerich.com>
parents: 12506
diff changeset
   177
18b5b6392fcf subrepo: rename relpath to subrelpath and introduce reporelpath
Mads Kiilerich <mads@kiilerich.com>
parents: 12506
diff changeset
   178
def subrelpath(sub):
11571
636554d58665 subrepo: docstrings
Mads Kiilerich <mads@kiilerich.com>
parents: 11470
diff changeset
   179
    """return path to this subrepo as seen from outermost repo"""
11112
4a9bee613737 subrepo: print paths relative to upper repo root for push/pull/commit
Edouard Gomez <ed.gomez@free.fr>
parents: 11111
diff changeset
   180
    if not hasattr(sub, '_repo'):
4a9bee613737 subrepo: print paths relative to upper repo root for push/pull/commit
Edouard Gomez <ed.gomez@free.fr>
parents: 11111
diff changeset
   181
        return sub._path
12752
18b5b6392fcf subrepo: rename relpath to subrelpath and introduce reporelpath
Mads Kiilerich <mads@kiilerich.com>
parents: 12506
diff changeset
   182
    return reporelpath(sub._repo)
11112
4a9bee613737 subrepo: print paths relative to upper repo root for push/pull/commit
Edouard Gomez <ed.gomez@free.fr>
parents: 11111
diff changeset
   183
12753
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   184
def _abssource(repo, push=False, abort=True):
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   185
    """return pull/push path of repo - either based on parent repo .hgsub info
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   186
    or on the top repo config. Abort or return None if no source found."""
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   187
    if hasattr(repo, '_subparent'):
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   188
        source = repo._subsource
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   189
        if source.startswith('/') or '://' in source:
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   190
            return source
12753
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   191
        parent = _abssource(repo._subparent, push, abort=False)
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   192
        if parent:
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   193
            if '://' in parent:
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   194
                if parent[-1] == '/':
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   195
                    parent = parent[:-1]
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   196
                r = urlparse.urlparse(parent + '/' + source)
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   197
                r = urlparse.urlunparse((r[0], r[1],
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   198
                                         posixpath.normpath(r[2]),
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   199
                                         r[3], r[4], r[5]))
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   200
                return r
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   201
            else: # plain file system path
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   202
                return posixpath.normpath(os.path.join(parent, repo._subsource))
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   203
    else: # recursion reached top repo
12852
5dbff89cf107 subrepo: propagate non-default pull/push path to relative subrepos (issue1852)
Mads Kiilerich <mads@kiilerich.com>
parents: 12799
diff changeset
   204
        if hasattr(repo, '_subtoppath'):
5dbff89cf107 subrepo: propagate non-default pull/push path to relative subrepos (issue1852)
Mads Kiilerich <mads@kiilerich.com>
parents: 12799
diff changeset
   205
            return repo._subtoppath
12753
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   206
        if push and repo.ui.config('paths', 'default-push'):
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   207
            return repo.ui.config('paths', 'default-push')
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   208
        if repo.ui.config('paths', 'default'):
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   209
            return repo.ui.config('paths', 'default')
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   210
    if abort:
12770
614f0d8724ab check-code: find trailing whitespace
Martin Geisler <mg@lazybytes.net>
parents: 12753
diff changeset
   211
        raise util.Abort(_("default path for subrepository %s not found") %
12753
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   212
            reporelpath(repo))
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   213
12176
ecab10820983 subrepos: add function for iterating over ctx subrepos
Martin Geisler <mg@lazybytes.net>
parents: 12167
diff changeset
   214
def itersubrepos(ctx1, ctx2):
ecab10820983 subrepos: add function for iterating over ctx subrepos
Martin Geisler <mg@lazybytes.net>
parents: 12167
diff changeset
   215
    """find subrepos in ctx1 or ctx2"""
ecab10820983 subrepos: add function for iterating over ctx subrepos
Martin Geisler <mg@lazybytes.net>
parents: 12167
diff changeset
   216
    # Create a (subpath, ctx) mapping where we prefer subpaths from
ecab10820983 subrepos: add function for iterating over ctx subrepos
Martin Geisler <mg@lazybytes.net>
parents: 12167
diff changeset
   217
    # ctx1. The subpaths from ctx2 are important when the .hgsub file
ecab10820983 subrepos: add function for iterating over ctx subrepos
Martin Geisler <mg@lazybytes.net>
parents: 12167
diff changeset
   218
    # has been modified (in ctx2) but not yet committed (in ctx1).
ecab10820983 subrepos: add function for iterating over ctx subrepos
Martin Geisler <mg@lazybytes.net>
parents: 12167
diff changeset
   219
    subpaths = dict.fromkeys(ctx2.substate, ctx2)
ecab10820983 subrepos: add function for iterating over ctx subrepos
Martin Geisler <mg@lazybytes.net>
parents: 12167
diff changeset
   220
    subpaths.update(dict.fromkeys(ctx1.substate, ctx1))
ecab10820983 subrepos: add function for iterating over ctx subrepos
Martin Geisler <mg@lazybytes.net>
parents: 12167
diff changeset
   221
    for subpath, ctx in sorted(subpaths.iteritems()):
ecab10820983 subrepos: add function for iterating over ctx subrepos
Martin Geisler <mg@lazybytes.net>
parents: 12167
diff changeset
   222
        yield subpath, ctx.sub(subpath)
ecab10820983 subrepos: add function for iterating over ctx subrepos
Martin Geisler <mg@lazybytes.net>
parents: 12167
diff changeset
   223
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   224
def subrepo(ctx, path):
11571
636554d58665 subrepo: docstrings
Mads Kiilerich <mads@kiilerich.com>
parents: 11470
diff changeset
   225
    """return instance of the right subrepo class for subrepo in path"""
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   226
    # subrepo inherently violates our import layering rules
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   227
    # because it wants to make repo objects from deep inside the stack
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   228
    # so we manually delay the circular imports to not break
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   229
    # scripts that don't use our demand-loading
9092
9aebeea7ac00 subrepo: use hg.repository instead of creating localrepo directly
Abderrahim Kitouni <a.kitouni@gmail.com>
parents: 9049
diff changeset
   230
    global hg
9aebeea7ac00 subrepo: use hg.repository instead of creating localrepo directly
Abderrahim Kitouni <a.kitouni@gmail.com>
parents: 9049
diff changeset
   231
    import hg as h
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   232
    hg = h
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   233
8997
70f5d3be5917 subrepo: audit subrepo paths
Matt Mackall <mpm@selenic.com>
parents: 8908
diff changeset
   234
    util.path_auditor(ctx._repo.root)(path)
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   235
    state = ctx.substate.get(path, nullstate)
10177
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
   236
    if state[2] not in types:
10299
e768941f14c1 subrepo: fix errors reported by pylint
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10273
diff changeset
   237
        raise util.Abort(_('unknown subrepo type %s') % state[2])
10177
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
   238
    return types[state[2]](ctx, path, state[:2])
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   239
11559
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   240
# subrepo classes need to implement the following abstract class:
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   241
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   242
class abstractsubrepo(object):
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   243
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   244
    def dirty(self):
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   245
        """returns true if the dirstate of the subrepo does not match
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   246
        current stored state
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   247
        """
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   248
        raise NotImplementedError
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   249
12506
e7d45e41338c subrepos: add missing self argument to abstractsubrepo.checknested
Brodie Rao <brodie@bitheap.org>
parents: 12503
diff changeset
   250
    def checknested(self, path):
12162
af8c4929931c localrepo: add auditor attribute which knows about subrepos
Martin Geisler <mg@lazybytes.net>
parents: 12060
diff changeset
   251
        """check if path is a subrepository within this repository"""
af8c4929931c localrepo: add auditor attribute which knows about subrepos
Martin Geisler <mg@lazybytes.net>
parents: 12060
diff changeset
   252
        return False
af8c4929931c localrepo: add auditor attribute which knows about subrepos
Martin Geisler <mg@lazybytes.net>
parents: 12060
diff changeset
   253
11559
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   254
    def commit(self, text, user, date):
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   255
        """commit the current changes to the subrepo with the given
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   256
        log message. Use given user and date if possible. Return the
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   257
        new state of the subrepo.
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   258
        """
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   259
        raise NotImplementedError
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   260
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   261
    def remove(self):
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   262
        """remove the subrepo
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   263
11559
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   264
        (should verify the dirstate is not dirty first)
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   265
        """
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   266
        raise NotImplementedError
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   267
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   268
    def get(self, state):
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   269
        """run whatever commands are needed to put the subrepo into
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   270
        this state
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   271
        """
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   272
        raise NotImplementedError
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   273
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   274
    def merge(self, state):
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   275
        """merge currently-saved state with the new state."""
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   276
        raise NotImplementedError
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   277
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   278
    def push(self, force):
11572
324bad1dc230 Merge with stable
Martin Geisler <mg@lazybytes.net>
parents: 11560 11571
diff changeset
   279
        """perform whatever action is analogous to 'hg push'
11559
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   280
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   281
        This may be a no-op on some systems.
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   282
        """
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   283
        raise NotImplementedError
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   284
12270
166b9866580a add: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12210
diff changeset
   285
    def add(self, ui, match, dryrun, prefix):
166b9866580a add: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12210
diff changeset
   286
        return []
11559
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   287
12166
441a74b8def1 status: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12162
diff changeset
   288
    def status(self, rev2, **opts):
441a74b8def1 status: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12162
diff changeset
   289
        return [], [], [], [], [], [], []
441a74b8def1 status: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12162
diff changeset
   290
12167
d2c5b0927c28 diff: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12166
diff changeset
   291
    def diff(self, diffopts, node2, match, prefix, **opts):
d2c5b0927c28 diff: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12166
diff changeset
   292
        pass
d2c5b0927c28 diff: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12166
diff changeset
   293
12272
42ecd56399d7 outgoing: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12270
diff changeset
   294
    def outgoing(self, ui, dest, opts):
42ecd56399d7 outgoing: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12270
diff changeset
   295
        return 1
42ecd56399d7 outgoing: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12270
diff changeset
   296
12274
c02e1ed3d407 incoming: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12272
diff changeset
   297
    def incoming(self, ui, source, opts):
c02e1ed3d407 incoming: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12272
diff changeset
   298
        return 1
c02e1ed3d407 incoming: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12272
diff changeset
   299
12322
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   300
    def files(self):
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   301
        """return filename iterator"""
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   302
        raise NotImplementedError
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   303
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   304
    def filedata(self, name):
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   305
        """return file data"""
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   306
        raise NotImplementedError
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   307
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   308
    def fileflags(self, name):
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   309
        """return file flags"""
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   310
        return ''
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   311
13144
aae2d5cbde64 subrepo: add progress bar support to archive
Martin Geisler <mg@aragost.com>
parents: 13137
diff changeset
   312
    def archive(self, ui, archiver, prefix):
aae2d5cbde64 subrepo: add progress bar support to archive
Martin Geisler <mg@aragost.com>
parents: 13137
diff changeset
   313
        files = self.files()
aae2d5cbde64 subrepo: add progress bar support to archive
Martin Geisler <mg@aragost.com>
parents: 13137
diff changeset
   314
        total = len(files)
aae2d5cbde64 subrepo: add progress bar support to archive
Martin Geisler <mg@aragost.com>
parents: 13137
diff changeset
   315
        relpath = subrelpath(self)
aae2d5cbde64 subrepo: add progress bar support to archive
Martin Geisler <mg@aragost.com>
parents: 13137
diff changeset
   316
        ui.progress(_('archiving (%s)') % relpath, 0,
aae2d5cbde64 subrepo: add progress bar support to archive
Martin Geisler <mg@aragost.com>
parents: 13137
diff changeset
   317
                    unit=_('files'), total=total)
aae2d5cbde64 subrepo: add progress bar support to archive
Martin Geisler <mg@aragost.com>
parents: 13137
diff changeset
   318
        for i, name in enumerate(files):
12323
f00953d9533c subrepo: add support for 'hg archive'
Martin Geisler <mg@aragost.com>
parents: 12322
diff changeset
   319
            flags = self.fileflags(name)
f00953d9533c subrepo: add support for 'hg archive'
Martin Geisler <mg@aragost.com>
parents: 12322
diff changeset
   320
            mode = 'x' in flags and 0755 or 0644
f00953d9533c subrepo: add support for 'hg archive'
Martin Geisler <mg@aragost.com>
parents: 12322
diff changeset
   321
            symlink = 'l' in flags
f00953d9533c subrepo: add support for 'hg archive'
Martin Geisler <mg@aragost.com>
parents: 12322
diff changeset
   322
            archiver.addfile(os.path.join(prefix, self._path, name),
f00953d9533c subrepo: add support for 'hg archive'
Martin Geisler <mg@aragost.com>
parents: 12322
diff changeset
   323
                             mode, symlink, self.filedata(name))
13144
aae2d5cbde64 subrepo: add progress bar support to archive
Martin Geisler <mg@aragost.com>
parents: 13137
diff changeset
   324
            ui.progress(_('archiving (%s)') % relpath, i + 1,
aae2d5cbde64 subrepo: add progress bar support to archive
Martin Geisler <mg@aragost.com>
parents: 13137
diff changeset
   325
                        unit=_('files'), total=total)
aae2d5cbde64 subrepo: add progress bar support to archive
Martin Geisler <mg@aragost.com>
parents: 13137
diff changeset
   326
        ui.progress(_('archiving (%s)') % relpath, None)
12323
f00953d9533c subrepo: add support for 'hg archive'
Martin Geisler <mg@aragost.com>
parents: 12322
diff changeset
   327
f00953d9533c subrepo: add support for 'hg archive'
Martin Geisler <mg@aragost.com>
parents: 12322
diff changeset
   328
11559
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   329
class hgsubrepo(abstractsubrepo):
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   330
    def __init__(self, ctx, path, state):
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   331
        self._path = path
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   332
        self._state = state
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   333
        r = ctx._repo
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   334
        root = r.wjoin(path)
10666
4c50a90b90fc subrepo: keep ui and hgrc in sync when creating new repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10665
diff changeset
   335
        create = False
4c50a90b90fc subrepo: keep ui and hgrc in sync when creating new repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10665
diff changeset
   336
        if not os.path.exists(os.path.join(root, '.hg')):
4c50a90b90fc subrepo: keep ui and hgrc in sync when creating new repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10665
diff changeset
   337
            create = True
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   338
            util.makedirs(root)
10666
4c50a90b90fc subrepo: keep ui and hgrc in sync when creating new repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10665
diff changeset
   339
        self._repo = hg.repository(r.ui, root, create=create)
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   340
        self._repo._subparent = r
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   341
        self._repo._subsource = state[0]
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   342
10666
4c50a90b90fc subrepo: keep ui and hgrc in sync when creating new repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10665
diff changeset
   343
        if create:
4c50a90b90fc subrepo: keep ui and hgrc in sync when creating new repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10665
diff changeset
   344
            fp = self._repo.opener("hgrc", "w", text=True)
4c50a90b90fc subrepo: keep ui and hgrc in sync when creating new repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10665
diff changeset
   345
            fp.write('[paths]\n')
4c50a90b90fc subrepo: keep ui and hgrc in sync when creating new repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10665
diff changeset
   346
4c50a90b90fc subrepo: keep ui and hgrc in sync when creating new repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10665
diff changeset
   347
            def addpathconfig(key, value):
12753
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   348
                if value:
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   349
                    fp.write('%s = %s\n' % (key, value))
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   350
                    self._repo.ui.setconfig('paths', key, value)
10666
4c50a90b90fc subrepo: keep ui and hgrc in sync when creating new repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10665
diff changeset
   351
12753
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   352
            defpath = _abssource(self._repo, abort=False)
ef5eaf53f4f7 subrepo: abort instead of pushing/pulling to the repo itself
Mads Kiilerich <mads@kiilerich.com>
parents: 12752
diff changeset
   353
            defpushpath = _abssource(self._repo, True, abort=False)
10666
4c50a90b90fc subrepo: keep ui and hgrc in sync when creating new repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10665
diff changeset
   354
            addpathconfig('default', defpath)
10697
c90d923fff64 subrepo: fix hgrc paths section during subrepo pulling
Edouard Gomez <ed.gomez@free.fr>
parents: 10666
diff changeset
   355
            if defpath != defpushpath:
c90d923fff64 subrepo: fix hgrc paths section during subrepo pulling
Edouard Gomez <ed.gomez@free.fr>
parents: 10666
diff changeset
   356
                addpathconfig('default-push', defpushpath)
10666
4c50a90b90fc subrepo: keep ui and hgrc in sync when creating new repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10665
diff changeset
   357
            fp.close()
4c50a90b90fc subrepo: keep ui and hgrc in sync when creating new repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10665
diff changeset
   358
12270
166b9866580a add: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12210
diff changeset
   359
    def add(self, ui, match, dryrun, prefix):
166b9866580a add: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12210
diff changeset
   360
        return cmdutil.add(ui, self._repo, match, dryrun, True,
166b9866580a add: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12210
diff changeset
   361
                           os.path.join(prefix, self._path))
166b9866580a add: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12210
diff changeset
   362
12166
441a74b8def1 status: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12162
diff changeset
   363
    def status(self, rev2, **opts):
441a74b8def1 status: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12162
diff changeset
   364
        try:
441a74b8def1 status: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12162
diff changeset
   365
            rev1 = self._state[1]
441a74b8def1 status: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12162
diff changeset
   366
            ctx1 = self._repo[rev1]
441a74b8def1 status: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12162
diff changeset
   367
            ctx2 = self._repo[rev2]
441a74b8def1 status: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12162
diff changeset
   368
            return self._repo.status(ctx1, ctx2, **opts)
441a74b8def1 status: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12162
diff changeset
   369
        except error.RepoLookupError, inst:
12503
b4711585a455 subrepo: improve lookup error messages
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 12323
diff changeset
   370
            self._repo.ui.warn(_('warning: error "%s" in subrepository "%s"\n')
12752
18b5b6392fcf subrepo: rename relpath to subrelpath and introduce reporelpath
Mads Kiilerich <mads@kiilerich.com>
parents: 12506
diff changeset
   371
                               % (inst, subrelpath(self)))
12166
441a74b8def1 status: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12162
diff changeset
   372
            return [], [], [], [], [], [], []
441a74b8def1 status: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12162
diff changeset
   373
12167
d2c5b0927c28 diff: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12166
diff changeset
   374
    def diff(self, diffopts, node2, match, prefix, **opts):
d2c5b0927c28 diff: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12166
diff changeset
   375
        try:
d2c5b0927c28 diff: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12166
diff changeset
   376
            node1 = node.bin(self._state[1])
12209
affec9fb56ef subrepos: handle diff nodeids in subrepos, not before
Patrick Mezard <pmezard@gmail.com>
parents: 12176
diff changeset
   377
            # We currently expect node2 to come from substate and be
affec9fb56ef subrepos: handle diff nodeids in subrepos, not before
Patrick Mezard <pmezard@gmail.com>
parents: 12176
diff changeset
   378
            # in hex format
12210
21eb85e9ea94 subrepo: handle diff with working copy
Martin Geisler <mg@lazybytes.net>
parents: 12209
diff changeset
   379
            if node2 is not None:
21eb85e9ea94 subrepo: handle diff with working copy
Martin Geisler <mg@lazybytes.net>
parents: 12209
diff changeset
   380
                node2 = node.bin(node2)
12167
d2c5b0927c28 diff: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12166
diff changeset
   381
            cmdutil.diffordiffstat(self._repo.ui, self._repo, diffopts,
d2c5b0927c28 diff: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12166
diff changeset
   382
                                   node1, node2, match,
d2c5b0927c28 diff: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12166
diff changeset
   383
                                   prefix=os.path.join(prefix, self._path),
d2c5b0927c28 diff: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12166
diff changeset
   384
                                   listsubrepos=True, **opts)
d2c5b0927c28 diff: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12166
diff changeset
   385
        except error.RepoLookupError, inst:
12503
b4711585a455 subrepo: improve lookup error messages
Wagner Bruna <wbruna@softwareexpress.com.br>
parents: 12323
diff changeset
   386
            self._repo.ui.warn(_('warning: error "%s" in subrepository "%s"\n')
12752
18b5b6392fcf subrepo: rename relpath to subrelpath and introduce reporelpath
Mads Kiilerich <mads@kiilerich.com>
parents: 12506
diff changeset
   387
                               % (inst, subrelpath(self)))
12167
d2c5b0927c28 diff: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12166
diff changeset
   388
13144
aae2d5cbde64 subrepo: add progress bar support to archive
Martin Geisler <mg@aragost.com>
parents: 13137
diff changeset
   389
    def archive(self, ui, archiver, prefix):
aae2d5cbde64 subrepo: add progress bar support to archive
Martin Geisler <mg@aragost.com>
parents: 13137
diff changeset
   390
        abstractsubrepo.archive(self, ui, archiver, prefix)
12323
f00953d9533c subrepo: add support for 'hg archive'
Martin Geisler <mg@aragost.com>
parents: 12322
diff changeset
   391
f00953d9533c subrepo: add support for 'hg archive'
Martin Geisler <mg@aragost.com>
parents: 12322
diff changeset
   392
        rev = self._state[1]
f00953d9533c subrepo: add support for 'hg archive'
Martin Geisler <mg@aragost.com>
parents: 12322
diff changeset
   393
        ctx = self._repo[rev]
f00953d9533c subrepo: add support for 'hg archive'
Martin Geisler <mg@aragost.com>
parents: 12322
diff changeset
   394
        for subpath in ctx.substate:
f00953d9533c subrepo: add support for 'hg archive'
Martin Geisler <mg@aragost.com>
parents: 12322
diff changeset
   395
            s = subrepo(ctx, subpath)
13144
aae2d5cbde64 subrepo: add progress bar support to archive
Martin Geisler <mg@aragost.com>
parents: 13137
diff changeset
   396
            s.archive(ui, archiver, os.path.join(prefix, self._path))
12323
f00953d9533c subrepo: add support for 'hg archive'
Martin Geisler <mg@aragost.com>
parents: 12322
diff changeset
   397
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   398
    def dirty(self):
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   399
        r = self._state[1]
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   400
        if r == '':
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   401
            return True
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   402
        w = self._repo[None]
10666
4c50a90b90fc subrepo: keep ui and hgrc in sync when creating new repo
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10665
diff changeset
   403
        if w.p1() != self._repo[r]: # version checked out change
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   404
            return True
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   405
        return w.dirty() # working directory changed
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   406
12162
af8c4929931c localrepo: add auditor attribute which knows about subrepos
Martin Geisler <mg@lazybytes.net>
parents: 12060
diff changeset
   407
    def checknested(self, path):
af8c4929931c localrepo: add auditor attribute which knows about subrepos
Martin Geisler <mg@lazybytes.net>
parents: 12060
diff changeset
   408
        return self._repo._checknested(self._repo.wjoin(path))
af8c4929931c localrepo: add auditor attribute which knows about subrepos
Martin Geisler <mg@lazybytes.net>
parents: 12060
diff changeset
   409
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   410
    def commit(self, text, user, date):
12752
18b5b6392fcf subrepo: rename relpath to subrelpath and introduce reporelpath
Mads Kiilerich <mads@kiilerich.com>
parents: 12506
diff changeset
   411
        self._repo.ui.debug("committing subrepo %s\n" % subrelpath(self))
8813
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   412
        n = self._repo.commit(text, user, date)
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   413
        if not n:
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   414
            return self._repo['.'].hex() # different version checked out
db3c1ab0e632 commit: recurse into subrepositories
Matt Mackall <mpm@selenic.com>
parents: 8812
diff changeset
   415
        return node.hex(n)
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   416
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   417
    def remove(self):
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   418
        # we can't fully delete the repository as it may contain
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   419
        # local-only history
12752
18b5b6392fcf subrepo: rename relpath to subrelpath and introduce reporelpath
Mads Kiilerich <mads@kiilerich.com>
parents: 12506
diff changeset
   420
        self._repo.ui.note(_('removing subrepo %s\n') % subrelpath(self))
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   421
        hg.clean(self._repo, node.nullid, False)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   422
9507
5987183d6e59 subrepo: add auto-pull for merge
Matt Mackall <mpm@selenic.com>
parents: 9186
diff changeset
   423
    def _get(self, state):
10177
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
   424
        source, revision, kind = state
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   425
        try:
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   426
            self._repo.lookup(revision)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   427
        except error.RepoError:
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   428
            self._repo._subsource = source
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   429
            srcurl = _abssource(self._repo)
10671
001ffc2b3d22 subrepo: wrap long line
Martin Geisler <mg@lazybytes.net>
parents: 10670
diff changeset
   430
            self._repo.ui.status(_('pulling subrepo %s from %s\n')
12752
18b5b6392fcf subrepo: rename relpath to subrelpath and introduce reporelpath
Mads Kiilerich <mads@kiilerich.com>
parents: 12506
diff changeset
   431
                                 % (subrelpath(self), srcurl))
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   432
            other = hg.repository(self._repo.ui, srcurl)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   433
            self._repo.pull(other)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   434
9507
5987183d6e59 subrepo: add auto-pull for merge
Matt Mackall <mpm@selenic.com>
parents: 9186
diff changeset
   435
    def get(self, state):
5987183d6e59 subrepo: add auto-pull for merge
Matt Mackall <mpm@selenic.com>
parents: 9186
diff changeset
   436
        self._get(state)
10177
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
   437
        source, revision, kind = state
9782
c1c40511c276 subrepo: add more debugging output, lose _ markers
Matt Mackall <mpm@selenic.com>
parents: 9781
diff changeset
   438
        self._repo.ui.debug("getting subrepo %s\n" % self._path)
8814
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   439
        hg.clean(self._repo, revision, False)
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   440
ab668c92a036 subrepo: add update/merge logic
Matt Mackall <mpm@selenic.com>
parents: 8813
diff changeset
   441
    def merge(self, state):
9507
5987183d6e59 subrepo: add auto-pull for merge
Matt Mackall <mpm@selenic.com>
parents: 9186
diff changeset
   442
        self._get(state)
9781
eccc8aacd6f9 subrepo: do a linear update when appropriate
Matt Mackall <mpm@selenic.com>
parents: 9780
diff changeset
   443
        cur = self._repo['.']
eccc8aacd6f9 subrepo: do a linear update when appropriate
Matt Mackall <mpm@selenic.com>
parents: 9780
diff changeset
   444
        dst = self._repo[state[1]]
10251
a19d2993385d subrepo: fix merging of already merged subrepos (issue1986)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10068
diff changeset
   445
        anc = dst.ancestor(cur)
a19d2993385d subrepo: fix merging of already merged subrepos (issue1986)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10068
diff changeset
   446
        if anc == cur:
12752
18b5b6392fcf subrepo: rename relpath to subrelpath and introduce reporelpath
Mads Kiilerich <mads@kiilerich.com>
parents: 12506
diff changeset
   447
            self._repo.ui.debug("updating subrepo %s\n" % subrelpath(self))
9781
eccc8aacd6f9 subrepo: do a linear update when appropriate
Matt Mackall <mpm@selenic.com>
parents: 9780
diff changeset
   448
            hg.update(self._repo, state[1])
10251
a19d2993385d subrepo: fix merging of already merged subrepos (issue1986)
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10068
diff changeset
   449
        elif anc == dst:
12752
18b5b6392fcf subrepo: rename relpath to subrelpath and introduce reporelpath
Mads Kiilerich <mads@kiilerich.com>
parents: 12506
diff changeset
   450
            self._repo.ui.debug("skipping subrepo %s\n" % subrelpath(self))
9781
eccc8aacd6f9 subrepo: do a linear update when appropriate
Matt Mackall <mpm@selenic.com>
parents: 9780
diff changeset
   451
        else:
12752
18b5b6392fcf subrepo: rename relpath to subrelpath and introduce reporelpath
Mads Kiilerich <mads@kiilerich.com>
parents: 12506
diff changeset
   452
            self._repo.ui.debug("merging subrepo %s\n" % subrelpath(self))
9781
eccc8aacd6f9 subrepo: do a linear update when appropriate
Matt Mackall <mpm@selenic.com>
parents: 9780
diff changeset
   453
            hg.merge(self._repo, state[1], remind=False)
8815
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
   454
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
   455
    def push(self, force):
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
   456
        # push subrepos depth-first for coherent ordering
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
   457
        c = self._repo['']
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
   458
        subs = c.substate # only repos that are committed
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
   459
        for s in sorted(subs):
11067
49e14ec67144 subrepo: propagate and catch push failures
Matt Mackall <mpm@selenic.com>
parents: 10954
diff changeset
   460
            if not c.sub(s).push(force):
49e14ec67144 subrepo: propagate and catch push failures
Matt Mackall <mpm@selenic.com>
parents: 10954
diff changeset
   461
                return False
8815
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
   462
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
   463
        dsturl = _abssource(self._repo, True)
11111
d2da9e6dd13e subrepo: print pushing url
Edouard Gomez <ed.gomez@free.fr>
parents: 11109
diff changeset
   464
        self._repo.ui.status(_('pushing subrepo %s to %s\n') %
12752
18b5b6392fcf subrepo: rename relpath to subrelpath and introduce reporelpath
Mads Kiilerich <mads@kiilerich.com>
parents: 12506
diff changeset
   465
            (subrelpath(self), dsturl))
8815
e87b0fc4750b subrepo: basic push support
Matt Mackall <mpm@selenic.com>
parents: 8814
diff changeset
   466
        other = hg.repository(self._repo.ui, dsturl)
11067
49e14ec67144 subrepo: propagate and catch push failures
Matt Mackall <mpm@selenic.com>
parents: 10954
diff changeset
   467
        return self._repo.push(other, force)
10177
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
   468
12272
42ecd56399d7 outgoing: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12270
diff changeset
   469
    def outgoing(self, ui, dest, opts):
42ecd56399d7 outgoing: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12270
diff changeset
   470
        return hg.outgoing(ui, self._repo, _abssource(self._repo, True), opts)
42ecd56399d7 outgoing: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12270
diff changeset
   471
12274
c02e1ed3d407 incoming: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12272
diff changeset
   472
    def incoming(self, ui, source, opts):
c02e1ed3d407 incoming: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12272
diff changeset
   473
        return hg.incoming(ui, self._repo, _abssource(self._repo, False), opts)
c02e1ed3d407 incoming: recurse into subrepositories with --subrepos/-S flag
Martin Geisler <mg@lazybytes.net>
parents: 12272
diff changeset
   474
12322
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   475
    def files(self):
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   476
        rev = self._state[1]
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   477
        ctx = self._repo[rev]
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   478
        return ctx.manifest()
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   479
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   480
    def filedata(self, name):
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   481
        rev = self._state[1]
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   482
        return self._repo[rev][name].data()
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   483
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   484
    def fileflags(self, name):
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   485
        rev = self._state[1]
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   486
        ctx = self._repo[rev]
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   487
        return ctx.flags(name)
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   488
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   489
11559
9d88597470af subrepo: add abstract superclass for subrepo classes
Martin Geisler <mg@lazybytes.net>
parents: 11470
diff changeset
   490
class svnsubrepo(abstractsubrepo):
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   491
    def __init__(self, ctx, path, state):
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   492
        self._path = path
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   493
        self._state = state
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   494
        self._ctx = ctx
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   495
        self._ui = ctx._repo.ui
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   496
11560
ea2cdee9a1fe subrepos: let caller specify a filename for SVN commands
Martin Geisler <mg@lazybytes.net>
parents: 11559
diff changeset
   497
    def _svncommand(self, commands, filename=''):
ea2cdee9a1fe subrepos: let caller specify a filename for SVN commands
Martin Geisler <mg@lazybytes.net>
parents: 11559
diff changeset
   498
        path = os.path.join(self._ctx._repo.origroot, self._path, filename)
10954
33119d0252c1 subrepo: fix repo root path handling in svn subrepo
Brett Cannon <brett@python.org>
parents: 10697
diff changeset
   499
        cmd = ['svn'] + commands + [path]
10199
c2e2a5e6c36b subrepo: force en_US.UTF-8 locale when calling svn
Patrick Mezard <pmezard@gmail.com>
parents: 10197
diff changeset
   500
        env = dict(os.environ)
10271
9b38bec5dc29 subrepo: make svn use C locale for portability
Patrick Mezard <pmezard@gmail.com>
parents: 10264
diff changeset
   501
        # Avoid localized output, preserve current locale for everything else.
9b38bec5dc29 subrepo: make svn use C locale for portability
Patrick Mezard <pmezard@gmail.com>
parents: 10264
diff changeset
   502
        env['LC_MESSAGES'] = 'C'
13108
dcaad69cfd6a subrepo: use subprocess.Popen without the shell
Eric Eisner <ede@mit.edu>
parents: 13107
diff changeset
   503
        p = subprocess.Popen(cmd, bufsize=-1, close_fds=util.closefds,
13014
d1c52354b0a9 subrepo: use subprocess directly to avoid python 2.6 bug
Patrick Mezard <pmezard@gmail.com>
parents: 13013
diff changeset
   504
                             stdout=subprocess.PIPE, stderr=subprocess.PIPE,
d1c52354b0a9 subrepo: use subprocess directly to avoid python 2.6 bug
Patrick Mezard <pmezard@gmail.com>
parents: 13013
diff changeset
   505
                             universal_newlines=True, env=env)
d1c52354b0a9 subrepo: use subprocess directly to avoid python 2.6 bug
Patrick Mezard <pmezard@gmail.com>
parents: 13013
diff changeset
   506
        stdout, stderr = p.communicate()
d1c52354b0a9 subrepo: use subprocess directly to avoid python 2.6 bug
Patrick Mezard <pmezard@gmail.com>
parents: 13013
diff changeset
   507
        stderr = stderr.strip()
d1c52354b0a9 subrepo: use subprocess directly to avoid python 2.6 bug
Patrick Mezard <pmezard@gmail.com>
parents: 13013
diff changeset
   508
        if stderr:
d1c52354b0a9 subrepo: use subprocess directly to avoid python 2.6 bug
Patrick Mezard <pmezard@gmail.com>
parents: 13013
diff changeset
   509
            raise util.Abort(stderr)
d1c52354b0a9 subrepo: use subprocess directly to avoid python 2.6 bug
Patrick Mezard <pmezard@gmail.com>
parents: 13013
diff changeset
   510
        return stdout
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   511
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   512
    def _wcrev(self):
10272
886858b834da subrepo: svn xml output is much easier to parse
Patrick Mezard <pmezard@gmail.com>
parents: 10271
diff changeset
   513
        output = self._svncommand(['info', '--xml'])
886858b834da subrepo: svn xml output is much easier to parse
Patrick Mezard <pmezard@gmail.com>
parents: 10271
diff changeset
   514
        doc = xml.dom.minidom.parseString(output)
886858b834da subrepo: svn xml output is much easier to parse
Patrick Mezard <pmezard@gmail.com>
parents: 10271
diff changeset
   515
        entries = doc.getElementsByTagName('entry')
886858b834da subrepo: svn xml output is much easier to parse
Patrick Mezard <pmezard@gmail.com>
parents: 10271
diff changeset
   516
        if not entries:
12799
8f71e5074e3c subrepo: svnsubrepo._wcrev should return str after 3d6ba8c2b1b8
Martin Geisler <mg@lazybytes.net>
parents: 12798
diff changeset
   517
            return '0'
12798
3d6ba8c2b1b8 subrepo: fix status check on SVN subrepos (issue2445)
Matt Mackall <mpm@selenic.com>
parents: 12770
diff changeset
   518
        return str(entries[0].getAttribute('revision')) or '0'
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   519
10273
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   520
    def _wcchanged(self):
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   521
        """Return (changes, extchanges) where changes is True
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   522
        if the working directory was changed, and extchanges is
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   523
        True if any of these changes concern an external entry.
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   524
        """
10272
886858b834da subrepo: svn xml output is much easier to parse
Patrick Mezard <pmezard@gmail.com>
parents: 10271
diff changeset
   525
        output = self._svncommand(['status', '--xml'])
10273
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   526
        externals, changes = [], []
10272
886858b834da subrepo: svn xml output is much easier to parse
Patrick Mezard <pmezard@gmail.com>
parents: 10271
diff changeset
   527
        doc = xml.dom.minidom.parseString(output)
10273
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   528
        for e in doc.getElementsByTagName('entry'):
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   529
            s = e.getElementsByTagName('wc-status')
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   530
            if not s:
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   531
                continue
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   532
            item = s[0].getAttribute('item')
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   533
            props = s[0].getAttribute('props')
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   534
            path = e.getAttribute('path')
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   535
            if item == 'external':
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   536
                externals.append(path)
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   537
            if (item not in ('', 'normal', 'unversioned', 'external')
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   538
                or props not in ('', 'none')):
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   539
                changes.append(path)
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   540
        for path in changes:
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   541
            for ext in externals:
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   542
                if path == ext or path.startswith(ext + os.sep):
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   543
                    return True, True
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   544
        return bool(changes), False
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   545
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   546
    def dirty(self):
10273
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   547
        if self._wcrev() == self._state[1] and not self._wcchanged()[0]:
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   548
            return False
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   549
        return True
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   550
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   551
    def commit(self, text, user, date):
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   552
        # user and date are out of our hands since svn is centralized
10273
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   553
        changed, extchanged = self._wcchanged()
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   554
        if not changed:
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   555
            return self._wcrev()
10273
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   556
        if extchanged:
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   557
            # Do not try to commit externals
e898bc7810ad subrepo: handle svn externals and meta changes (issue1982)
Patrick Mezard <pmezard@gmail.com>
parents: 10272
diff changeset
   558
            raise util.Abort(_('cannot commit svn externals'))
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   559
        commitinfo = self._svncommand(['commit', '-m', text])
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   560
        self._ui.status(commitinfo)
12060
63eab3b74ba6 subrepo: use [0-9] instead of [\d] in svn subrepo regex
Martin Geisler <mg@lazybytes.net>
parents: 11961
diff changeset
   561
        newrev = re.search('Committed revision ([0-9]+).', commitinfo)
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   562
        if not newrev:
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   563
            raise util.Abort(commitinfo.splitlines()[-1])
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   564
        newrev = newrev.groups()[0]
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   565
        self._ui.status(self._svncommand(['update', '-r', newrev]))
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   566
        return newrev
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   567
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   568
    def remove(self):
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   569
        if self.dirty():
10299
e768941f14c1 subrepo: fix errors reported by pylint
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10273
diff changeset
   570
            self._ui.warn(_('not removing repo %s because '
e768941f14c1 subrepo: fix errors reported by pylint
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10273
diff changeset
   571
                            'it has changes.\n' % self._path))
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   572
            return
10510
f77f3383c666 i18n: mark more strings for translation
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 10457
diff changeset
   573
        self._ui.note(_('removing subrepo %s\n') % self._path)
13013
92b0d669637f subrepo: fix removing read-only svn files on Windows
Patrick Mezard <pmezard@gmail.com>
parents: 12930
diff changeset
   574
92b0d669637f subrepo: fix removing read-only svn files on Windows
Patrick Mezard <pmezard@gmail.com>
parents: 12930
diff changeset
   575
        def onerror(function, path, excinfo):
92b0d669637f subrepo: fix removing read-only svn files on Windows
Patrick Mezard <pmezard@gmail.com>
parents: 12930
diff changeset
   576
            if function is not os.remove:
92b0d669637f subrepo: fix removing read-only svn files on Windows
Patrick Mezard <pmezard@gmail.com>
parents: 12930
diff changeset
   577
                raise
92b0d669637f subrepo: fix removing read-only svn files on Windows
Patrick Mezard <pmezard@gmail.com>
parents: 12930
diff changeset
   578
            # read-only files cannot be unlinked under Windows
92b0d669637f subrepo: fix removing read-only svn files on Windows
Patrick Mezard <pmezard@gmail.com>
parents: 12930
diff changeset
   579
            s = os.stat(path)
92b0d669637f subrepo: fix removing read-only svn files on Windows
Patrick Mezard <pmezard@gmail.com>
parents: 12930
diff changeset
   580
            if (s.st_mode & stat.S_IWRITE) != 0:
92b0d669637f subrepo: fix removing read-only svn files on Windows
Patrick Mezard <pmezard@gmail.com>
parents: 12930
diff changeset
   581
                raise
92b0d669637f subrepo: fix removing read-only svn files on Windows
Patrick Mezard <pmezard@gmail.com>
parents: 12930
diff changeset
   582
            os.chmod(path, stat.S_IMODE(s.st_mode) | stat.S_IWRITE)
92b0d669637f subrepo: fix removing read-only svn files on Windows
Patrick Mezard <pmezard@gmail.com>
parents: 12930
diff changeset
   583
            os.remove(path)
92b0d669637f subrepo: fix removing read-only svn files on Windows
Patrick Mezard <pmezard@gmail.com>
parents: 12930
diff changeset
   584
13015
82ca0c43bc44 subrepo: prune empty directories when removing svn subrepo
Patrick Mezard <pmezard@gmail.com>
parents: 13014
diff changeset
   585
        path = self._ctx._repo.wjoin(self._path)
82ca0c43bc44 subrepo: prune empty directories when removing svn subrepo
Patrick Mezard <pmezard@gmail.com>
parents: 13014
diff changeset
   586
        shutil.rmtree(path, onerror=onerror)
82ca0c43bc44 subrepo: prune empty directories when removing svn subrepo
Patrick Mezard <pmezard@gmail.com>
parents: 13014
diff changeset
   587
        try:
82ca0c43bc44 subrepo: prune empty directories when removing svn subrepo
Patrick Mezard <pmezard@gmail.com>
parents: 13014
diff changeset
   588
            os.removedirs(os.path.dirname(path))
82ca0c43bc44 subrepo: prune empty directories when removing svn subrepo
Patrick Mezard <pmezard@gmail.com>
parents: 13014
diff changeset
   589
        except OSError:
82ca0c43bc44 subrepo: prune empty directories when removing svn subrepo
Patrick Mezard <pmezard@gmail.com>
parents: 13014
diff changeset
   590
            pass
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   591
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   592
    def get(self, state):
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   593
        status = self._svncommand(['checkout', state[0], '--revision', state[1]])
12060
63eab3b74ba6 subrepo: use [0-9] instead of [\d] in svn subrepo regex
Martin Geisler <mg@lazybytes.net>
parents: 11961
diff changeset
   594
        if not re.search('Checked out revision [0-9]+.', status):
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   595
            raise util.Abort(status.splitlines()[-1])
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   596
        self._ui.status(status)
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   597
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   598
    def merge(self, state):
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   599
        old = int(self._state[1])
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   600
        new = int(state[1])
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   601
        if new > old:
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   602
            self.get(state)
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   603
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   604
    def push(self, force):
11455
3827728b54e2 subrepo: fix silent push failure for SVN (issue2241)
Matt Mackall <mpm@selenic.com>
parents: 11117
diff changeset
   605
        # push is a no-op for SVN
3827728b54e2 subrepo: fix silent push failure for SVN (issue2241)
Matt Mackall <mpm@selenic.com>
parents: 11117
diff changeset
   606
        return True
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   607
12322
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   608
    def files(self):
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   609
        output = self._svncommand(['list'])
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   610
        # This works because svn forbids \n in filenames.
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   611
        return output.splitlines()
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   612
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   613
    def filedata(self, name):
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   614
        return self._svncommand(['cat'], name)
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   615
510afb31cf99 subrepo: introduce files and filedata methods for subrepo classes
Martin Geisler <mg@aragost.com>
parents: 12274
diff changeset
   616
13106
c869bd9e1193 subrepo: gitsubrepo should inherit from abstractsubrepo
Eric Eisner <ede@mit.edu>
parents: 13097
diff changeset
   617
class gitsubrepo(abstractsubrepo):
12992
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   618
    def __init__(self, ctx, path, state):
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   619
        # TODO add git version check.
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   620
        self._state = state
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   621
        self._ctx = ctx
12993
a91334380699 subrepo: cloning and updating of git subrepos
Eric Eisner <ede@mit.edu>
parents: 12992
diff changeset
   622
        self._relpath = path
12992
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   623
        self._path = ctx._repo.wjoin(path)
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   624
        self._ui = ctx._repo.ui
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   625
13095
49c7e875482d subrepo: use environment variable instead of git commit's --date
Eric Eisner <ede@mit.edu>
parents: 13094
diff changeset
   626
    def _gitcommand(self, commands, env=None, stream=False):
49c7e875482d subrepo: use environment variable instead of git commit's --date
Eric Eisner <ede@mit.edu>
parents: 13094
diff changeset
   627
        return self._gitdir(commands, env=env, stream=stream)[0]
12992
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   628
13095
49c7e875482d subrepo: use environment variable instead of git commit's --date
Eric Eisner <ede@mit.edu>
parents: 13094
diff changeset
   629
    def _gitdir(self, commands, env=None, stream=False):
49c7e875482d subrepo: use environment variable instead of git commit's --date
Eric Eisner <ede@mit.edu>
parents: 13094
diff changeset
   630
        return self._gitnodir(commands, env=env, stream=stream, cwd=self._path)
12992
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   631
13095
49c7e875482d subrepo: use environment variable instead of git commit's --date
Eric Eisner <ede@mit.edu>
parents: 13094
diff changeset
   632
    def _gitnodir(self, commands, env=None, stream=False, cwd=None):
12992
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   633
        """Calls the git command
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   634
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   635
        The methods tries to call the git command. versions previor to 1.6.0
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   636
        are not supported and very probably fail.
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   637
        """
13110
cad35f06c031 subrepo: show git command with --debug
Eric Eisner <ede@mit.edu>
parents: 13109
diff changeset
   638
        self._ui.debug('%s: git %s\n' % (self._relpath, ' '.join(commands)))
13111
560b8001f765 subrepo: silence git output when ui.quiet is set
Eric Eisner <ede@mit.edu>
parents: 13110
diff changeset
   639
        # unless ui.quiet is set, print git's stderr,
560b8001f765 subrepo: silence git output when ui.quiet is set
Eric Eisner <ede@mit.edu>
parents: 13110
diff changeset
   640
        # which is mostly progress and useful info
560b8001f765 subrepo: silence git output when ui.quiet is set
Eric Eisner <ede@mit.edu>
parents: 13110
diff changeset
   641
        errpipe = None
560b8001f765 subrepo: silence git output when ui.quiet is set
Eric Eisner <ede@mit.edu>
parents: 13110
diff changeset
   642
        if self._ui.quiet:
560b8001f765 subrepo: silence git output when ui.quiet is set
Eric Eisner <ede@mit.edu>
parents: 13110
diff changeset
   643
            errpipe = open(os.devnull, 'w')
13108
dcaad69cfd6a subrepo: use subprocess.Popen without the shell
Eric Eisner <ede@mit.edu>
parents: 13107
diff changeset
   644
        p = subprocess.Popen(['git'] + commands, bufsize=-1, cwd=cwd, env=env,
13027
7f2ecb64140d subrepo: archive git subrepos
Eric Eisner <ede@mit.edu>
parents: 13018
diff changeset
   645
                             close_fds=util.closefds,
13111
560b8001f765 subrepo: silence git output when ui.quiet is set
Eric Eisner <ede@mit.edu>
parents: 13110
diff changeset
   646
                             stdout=subprocess.PIPE, stderr=errpipe)
13027
7f2ecb64140d subrepo: archive git subrepos
Eric Eisner <ede@mit.edu>
parents: 13018
diff changeset
   647
        if stream:
7f2ecb64140d subrepo: archive git subrepos
Eric Eisner <ede@mit.edu>
parents: 13018
diff changeset
   648
            return p.stdout, None
7f2ecb64140d subrepo: archive git subrepos
Eric Eisner <ede@mit.edu>
parents: 13018
diff changeset
   649
13085
b4814f1f415c subrepo: strip gitcommand output
Eric Eisner <ede@mit.edu>
parents: 13029
diff changeset
   650
        retdata = p.stdout.read().strip()
12992
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   651
        # wait for the child to exit to avoid race condition.
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   652
        p.wait()
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   653
13107
3bc237b0eaea subrepo: treat git error code 1 as success
Eric Eisner <ede@mit.edu>
parents: 13106
diff changeset
   654
        if p.returncode != 0 and p.returncode != 1:
12992
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   655
            # there are certain error codes that are ok
13110
cad35f06c031 subrepo: show git command with --debug
Eric Eisner <ede@mit.edu>
parents: 13109
diff changeset
   656
            command = commands[0]
13150
8617b8b74fae subrepo: use low-level git-for-each-ref command in branchmap
Eric Eisner <ede@mit.edu>
parents: 13144
diff changeset
   657
            if command in ('cat-file', 'symbolic-ref'):
12992
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   658
                return retdata, p.returncode
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   659
            # for all others, abort
13110
cad35f06c031 subrepo: show git command with --debug
Eric Eisner <ede@mit.edu>
parents: 13109
diff changeset
   660
            raise util.Abort('git %s error %d in %s' %
cad35f06c031 subrepo: show git command with --debug
Eric Eisner <ede@mit.edu>
parents: 13109
diff changeset
   661
                             (command, p.returncode, self._relpath))
12992
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   662
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   663
        return retdata, p.returncode
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   664
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   665
    def _gitstate(self):
13085
b4814f1f415c subrepo: strip gitcommand output
Eric Eisner <ede@mit.edu>
parents: 13029
diff changeset
   666
        return self._gitcommand(['rev-parse', 'HEAD'])
12992
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   667
13152
70d80907e4b8 subrepo: defer determination of git's current branch
Eric Eisner <ede@mit.edu>
parents: 13151
diff changeset
   668
    def _gitcurrentbranch(self):
70d80907e4b8 subrepo: defer determination of git's current branch
Eric Eisner <ede@mit.edu>
parents: 13151
diff changeset
   669
        current, err = self._gitdir(['symbolic-ref', 'HEAD', '--quiet'])
70d80907e4b8 subrepo: defer determination of git's current branch
Eric Eisner <ede@mit.edu>
parents: 13151
diff changeset
   670
        if err:
70d80907e4b8 subrepo: defer determination of git's current branch
Eric Eisner <ede@mit.edu>
parents: 13151
diff changeset
   671
            current = None
70d80907e4b8 subrepo: defer determination of git's current branch
Eric Eisner <ede@mit.edu>
parents: 13151
diff changeset
   672
        return current
70d80907e4b8 subrepo: defer determination of git's current branch
Eric Eisner <ede@mit.edu>
parents: 13151
diff changeset
   673
12992
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   674
    def _githavelocally(self, revision):
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   675
        out, code = self._gitdir(['cat-file', '-e', revision])
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   676
        return code == 0
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   677
13029
f930032aa6d5 subrepo: lazier git push logic
Eric Eisner <ede@mit.edu>
parents: 13027
diff changeset
   678
    def _gitisancestor(self, r1, r2):
13085
b4814f1f415c subrepo: strip gitcommand output
Eric Eisner <ede@mit.edu>
parents: 13029
diff changeset
   679
        base = self._gitcommand(['merge-base', r1, r2])
13029
f930032aa6d5 subrepo: lazier git push logic
Eric Eisner <ede@mit.edu>
parents: 13027
diff changeset
   680
        return base == r1
f930032aa6d5 subrepo: lazier git push logic
Eric Eisner <ede@mit.edu>
parents: 13027
diff changeset
   681
12995
d90fc91c8377 subrepo: update and merge works with any git branch
Eric Eisner <ede@mit.edu>
parents: 12994
diff changeset
   682
    def _gitbranchmap(self):
13086
8db85e39d59c subrepo: return both mapping directions from gitbranchmap
Eric Eisner <ede@mit.edu>
parents: 13085
diff changeset
   683
        '''returns 3 things:
8db85e39d59c subrepo: return both mapping directions from gitbranchmap
Eric Eisner <ede@mit.edu>
parents: 13085
diff changeset
   684
        a map from git branch to revision
13152
70d80907e4b8 subrepo: defer determination of git's current branch
Eric Eisner <ede@mit.edu>
parents: 13151
diff changeset
   685
        a map from revision to branches
70d80907e4b8 subrepo: defer determination of git's current branch
Eric Eisner <ede@mit.edu>
parents: 13151
diff changeset
   686
        a map from remote branch to local tracking branch'''
13086
8db85e39d59c subrepo: return both mapping directions from gitbranchmap
Eric Eisner <ede@mit.edu>
parents: 13085
diff changeset
   687
        branch2rev = {}
8db85e39d59c subrepo: return both mapping directions from gitbranchmap
Eric Eisner <ede@mit.edu>
parents: 13085
diff changeset
   688
        rev2branch = {}
13151
519ac79d680b subrepo: incorporate tracking branches into gitbranchmap
Eric Eisner <ede@mit.edu>
parents: 13150
diff changeset
   689
        tracking = {}
13150
8617b8b74fae subrepo: use low-level git-for-each-ref command in branchmap
Eric Eisner <ede@mit.edu>
parents: 13144
diff changeset
   690
        out = self._gitcommand(['for-each-ref', '--format',
13151
519ac79d680b subrepo: incorporate tracking branches into gitbranchmap
Eric Eisner <ede@mit.edu>
parents: 13150
diff changeset
   691
                                '%(objectname) %(refname) %(upstream) end'])
12995
d90fc91c8377 subrepo: update and merge works with any git branch
Eric Eisner <ede@mit.edu>
parents: 12994
diff changeset
   692
        for line in out.split('\n'):
13151
519ac79d680b subrepo: incorporate tracking branches into gitbranchmap
Eric Eisner <ede@mit.edu>
parents: 13150
diff changeset
   693
            revision, ref, upstream = line.split(' ')[:3]
13150
8617b8b74fae subrepo: use low-level git-for-each-ref command in branchmap
Eric Eisner <ede@mit.edu>
parents: 13144
diff changeset
   694
            if ref.startswith('refs/tags/'):
12995
d90fc91c8377 subrepo: update and merge works with any git branch
Eric Eisner <ede@mit.edu>
parents: 12994
diff changeset
   695
                continue
13150
8617b8b74fae subrepo: use low-level git-for-each-ref command in branchmap
Eric Eisner <ede@mit.edu>
parents: 13144
diff changeset
   696
            if ref.startswith('refs/remotes/') and ref.endswith('/HEAD'):
12995
d90fc91c8377 subrepo: update and merge works with any git branch
Eric Eisner <ede@mit.edu>
parents: 12994
diff changeset
   697
                continue # ignore remote/HEAD redirects
13150
8617b8b74fae subrepo: use low-level git-for-each-ref command in branchmap
Eric Eisner <ede@mit.edu>
parents: 13144
diff changeset
   698
            branch2rev[ref] = revision
8617b8b74fae subrepo: use low-level git-for-each-ref command in branchmap
Eric Eisner <ede@mit.edu>
parents: 13144
diff changeset
   699
            rev2branch.setdefault(revision, []).append(ref)
13151
519ac79d680b subrepo: incorporate tracking branches into gitbranchmap
Eric Eisner <ede@mit.edu>
parents: 13150
diff changeset
   700
            if upstream:
519ac79d680b subrepo: incorporate tracking branches into gitbranchmap
Eric Eisner <ede@mit.edu>
parents: 13150
diff changeset
   701
                # assumes no more than one local tracking branch for a remote
519ac79d680b subrepo: incorporate tracking branches into gitbranchmap
Eric Eisner <ede@mit.edu>
parents: 13150
diff changeset
   702
                tracking[upstream] = ref
13152
70d80907e4b8 subrepo: defer determination of git's current branch
Eric Eisner <ede@mit.edu>
parents: 13151
diff changeset
   703
        return branch2rev, rev2branch, tracking
13087
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   704
12993
a91334380699 subrepo: cloning and updating of git subrepos
Eric Eisner <ede@mit.edu>
parents: 12992
diff changeset
   705
    def _fetch(self, source, revision):
a91334380699 subrepo: cloning and updating of git subrepos
Eric Eisner <ede@mit.edu>
parents: 12992
diff changeset
   706
        if not os.path.exists('%s/.git' % self._path):
a91334380699 subrepo: cloning and updating of git subrepos
Eric Eisner <ede@mit.edu>
parents: 12992
diff changeset
   707
            self._ui.status(_('cloning subrepo %s\n') % self._relpath)
a91334380699 subrepo: cloning and updating of git subrepos
Eric Eisner <ede@mit.edu>
parents: 12992
diff changeset
   708
            self._gitnodir(['clone', source, self._path])
a91334380699 subrepo: cloning and updating of git subrepos
Eric Eisner <ede@mit.edu>
parents: 12992
diff changeset
   709
        if self._githavelocally(revision):
a91334380699 subrepo: cloning and updating of git subrepos
Eric Eisner <ede@mit.edu>
parents: 12992
diff changeset
   710
            return
a91334380699 subrepo: cloning and updating of git subrepos
Eric Eisner <ede@mit.edu>
parents: 12992
diff changeset
   711
        self._ui.status(_('pulling subrepo %s\n') % self._relpath)
13097
c922aacf6f1f subrepo: drop arguments unsupported by old git
Eric Eisner <ede@mit.edu>
parents: 13096
diff changeset
   712
        # first try from origin
c922aacf6f1f subrepo: drop arguments unsupported by old git
Eric Eisner <ede@mit.edu>
parents: 13096
diff changeset
   713
        self._gitcommand(['fetch'])
c922aacf6f1f subrepo: drop arguments unsupported by old git
Eric Eisner <ede@mit.edu>
parents: 13096
diff changeset
   714
        if self._githavelocally(revision):
c922aacf6f1f subrepo: drop arguments unsupported by old git
Eric Eisner <ede@mit.edu>
parents: 13096
diff changeset
   715
            return
c922aacf6f1f subrepo: drop arguments unsupported by old git
Eric Eisner <ede@mit.edu>
parents: 13096
diff changeset
   716
        # then try from known subrepo source
c922aacf6f1f subrepo: drop arguments unsupported by old git
Eric Eisner <ede@mit.edu>
parents: 13096
diff changeset
   717
        self._gitcommand(['fetch', source])
12993
a91334380699 subrepo: cloning and updating of git subrepos
Eric Eisner <ede@mit.edu>
parents: 12992
diff changeset
   718
        if not self._githavelocally(revision):
a91334380699 subrepo: cloning and updating of git subrepos
Eric Eisner <ede@mit.edu>
parents: 12992
diff changeset
   719
            raise util.Abort(_("revision %s does not exist in subrepo %s\n") %
a91334380699 subrepo: cloning and updating of git subrepos
Eric Eisner <ede@mit.edu>
parents: 12992
diff changeset
   720
                               (revision, self._path))
a91334380699 subrepo: cloning and updating of git subrepos
Eric Eisner <ede@mit.edu>
parents: 12992
diff changeset
   721
12992
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   722
    def dirty(self):
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   723
        if self._state[1] != self._gitstate(): # version checked out changed?
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   724
            return True
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   725
        # check for staged changes or modified files; ignore untracked files
13153
dca5488f0e4f subrepo: use low-level git-diff-index for dirty()
Eric Eisner <ede@mit.edu>
parents: 13152
diff changeset
   726
        out, code = self._gitdir(['diff-index', '--quiet', 'HEAD'])
dca5488f0e4f subrepo: use low-level git-diff-index for dirty()
Eric Eisner <ede@mit.edu>
parents: 13152
diff changeset
   727
        return code == 1
12992
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   728
12993
a91334380699 subrepo: cloning and updating of git subrepos
Eric Eisner <ede@mit.edu>
parents: 12992
diff changeset
   729
    def get(self, state):
a91334380699 subrepo: cloning and updating of git subrepos
Eric Eisner <ede@mit.edu>
parents: 12992
diff changeset
   730
        source, revision, kind = state
a91334380699 subrepo: cloning and updating of git subrepos
Eric Eisner <ede@mit.edu>
parents: 12992
diff changeset
   731
        self._fetch(source, revision)
12996
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   732
        # if the repo was set to be bare, unbare it
13085
b4814f1f415c subrepo: strip gitcommand output
Eric Eisner <ede@mit.edu>
parents: 13029
diff changeset
   733
        if self._gitcommand(['config', '--bool', 'core.bare']) == 'true':
12996
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   734
            self._gitcommand(['config', 'core.bare', 'false'])
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   735
            if self._gitstate() == revision:
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   736
                self._gitcommand(['reset', '--hard', 'HEAD'])
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   737
                return
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   738
        elif self._gitstate() == revision:
12995
d90fc91c8377 subrepo: update and merge works with any git branch
Eric Eisner <ede@mit.edu>
parents: 12994
diff changeset
   739
            return
13152
70d80907e4b8 subrepo: defer determination of git's current branch
Eric Eisner <ede@mit.edu>
parents: 13151
diff changeset
   740
        branch2rev, rev2branch, tracking = self._gitbranchmap()
13087
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   741
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   742
        def rawcheckout():
12995
d90fc91c8377 subrepo: update and merge works with any git branch
Eric Eisner <ede@mit.edu>
parents: 12994
diff changeset
   743
            # no branch to checkout, check it out with no branch
12993
a91334380699 subrepo: cloning and updating of git subrepos
Eric Eisner <ede@mit.edu>
parents: 12992
diff changeset
   744
            self._ui.warn(_('checking out detached HEAD in subrepo %s\n') %
a91334380699 subrepo: cloning and updating of git subrepos
Eric Eisner <ede@mit.edu>
parents: 12992
diff changeset
   745
                          self._relpath)
a91334380699 subrepo: cloning and updating of git subrepos
Eric Eisner <ede@mit.edu>
parents: 12992
diff changeset
   746
            self._ui.warn(_('check out a git branch if you intend '
a91334380699 subrepo: cloning and updating of git subrepos
Eric Eisner <ede@mit.edu>
parents: 12992
diff changeset
   747
                            'to make changes\n'))
a91334380699 subrepo: cloning and updating of git subrepos
Eric Eisner <ede@mit.edu>
parents: 12992
diff changeset
   748
            self._gitcommand(['checkout', '-q', revision])
13087
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   749
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   750
        if revision not in rev2branch:
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   751
            rawcheckout()
12995
d90fc91c8377 subrepo: update and merge works with any git branch
Eric Eisner <ede@mit.edu>
parents: 12994
diff changeset
   752
            return
13086
8db85e39d59c subrepo: return both mapping directions from gitbranchmap
Eric Eisner <ede@mit.edu>
parents: 13085
diff changeset
   753
        branches = rev2branch[revision]
12995
d90fc91c8377 subrepo: update and merge works with any git branch
Eric Eisner <ede@mit.edu>
parents: 12994
diff changeset
   754
        firstlocalbranch = None
d90fc91c8377 subrepo: update and merge works with any git branch
Eric Eisner <ede@mit.edu>
parents: 12994
diff changeset
   755
        for b in branches:
13150
8617b8b74fae subrepo: use low-level git-for-each-ref command in branchmap
Eric Eisner <ede@mit.edu>
parents: 13144
diff changeset
   756
            if b == 'refs/heads/master':
12995
d90fc91c8377 subrepo: update and merge works with any git branch
Eric Eisner <ede@mit.edu>
parents: 12994
diff changeset
   757
                # master trumps all other branches
13150
8617b8b74fae subrepo: use low-level git-for-each-ref command in branchmap
Eric Eisner <ede@mit.edu>
parents: 13144
diff changeset
   758
                self._gitcommand(['checkout', 'refs/heads/master'])
12995
d90fc91c8377 subrepo: update and merge works with any git branch
Eric Eisner <ede@mit.edu>
parents: 12994
diff changeset
   759
                return
13150
8617b8b74fae subrepo: use low-level git-for-each-ref command in branchmap
Eric Eisner <ede@mit.edu>
parents: 13144
diff changeset
   760
            if not firstlocalbranch and not b.startswith('refs/remotes/'):
12995
d90fc91c8377 subrepo: update and merge works with any git branch
Eric Eisner <ede@mit.edu>
parents: 12994
diff changeset
   761
                firstlocalbranch = b
d90fc91c8377 subrepo: update and merge works with any git branch
Eric Eisner <ede@mit.edu>
parents: 12994
diff changeset
   762
        if firstlocalbranch:
d90fc91c8377 subrepo: update and merge works with any git branch
Eric Eisner <ede@mit.edu>
parents: 12994
diff changeset
   763
            self._gitcommand(['checkout', firstlocalbranch])
13087
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   764
            return
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   765
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   766
        # choose a remote branch already tracked if possible
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   767
        remote = branches[0]
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   768
        if remote not in tracking:
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   769
            for b in branches:
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   770
                if b in tracking:
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   771
                    remote = b
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   772
                    break
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   773
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   774
        if remote not in tracking:
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   775
            # create a new local tracking branch
13150
8617b8b74fae subrepo: use low-level git-for-each-ref command in branchmap
Eric Eisner <ede@mit.edu>
parents: 13144
diff changeset
   776
            local = remote.split('/', 2)[2]
12995
d90fc91c8377 subrepo: update and merge works with any git branch
Eric Eisner <ede@mit.edu>
parents: 12994
diff changeset
   777
            self._gitcommand(['checkout', '-b', local, remote])
13087
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   778
        elif self._gitisancestor(branch2rev[tracking[remote]], remote):
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   779
            # When updating to a tracked remote branch,
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   780
            # if the local tracking branch is downstream of it,
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   781
            # a normal `git pull` would have performed a "fast-forward merge"
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   782
            # which is equivalent to updating the local branch to the remote.
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   783
            # Since we are only looking at branching at update, we need to
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   784
            # detect this situation and perform this action lazily.
13152
70d80907e4b8 subrepo: defer determination of git's current branch
Eric Eisner <ede@mit.edu>
parents: 13151
diff changeset
   785
            if tracking[remote] != self._gitcurrentbranch():
13087
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   786
                self._gitcommand(['checkout', tracking[remote]])
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   787
            self._gitcommand(['merge', '--ff', remote])
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   788
        else:
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   789
            # a real merge would be required, just checkout the revision
cca0779b4832 subrepo: lazily update git's local tracking branches
Eric Eisner <ede@mit.edu>
parents: 13086
diff changeset
   790
            rawcheckout()
12993
a91334380699 subrepo: cloning and updating of git subrepos
Eric Eisner <ede@mit.edu>
parents: 12992
diff changeset
   791
12992
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   792
    def commit(self, text, user, date):
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   793
        cmd = ['commit', '-a', '-m', text]
13095
49c7e875482d subrepo: use environment variable instead of git commit's --date
Eric Eisner <ede@mit.edu>
parents: 13094
diff changeset
   794
        env = os.environ.copy()
12992
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   795
        if user:
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   796
            cmd += ['--author', user]
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   797
        if date:
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   798
            # git's date parser silently ignores when seconds < 1e9
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   799
            # convert to ISO8601
13095
49c7e875482d subrepo: use environment variable instead of git commit's --date
Eric Eisner <ede@mit.edu>
parents: 13094
diff changeset
   800
            env['GIT_AUTHOR_DATE'] = util.datestr(date,
49c7e875482d subrepo: use environment variable instead of git commit's --date
Eric Eisner <ede@mit.edu>
parents: 13094
diff changeset
   801
                                                  '%Y-%m-%dT%H:%M:%S %1%2')
49c7e875482d subrepo: use environment variable instead of git commit's --date
Eric Eisner <ede@mit.edu>
parents: 13094
diff changeset
   802
        self._gitcommand(cmd, env=env)
12992
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   803
        # make sure commit works otherwise HEAD might not exist under certain
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   804
        # circumstances
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   805
        return self._gitstate()
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   806
12994
845c602b8635 subrepo: allow git subrepos to push and merge
Eric Eisner <ede@mit.edu>
parents: 12993
diff changeset
   807
    def merge(self, state):
845c602b8635 subrepo: allow git subrepos to push and merge
Eric Eisner <ede@mit.edu>
parents: 12993
diff changeset
   808
        source, revision, kind = state
845c602b8635 subrepo: allow git subrepos to push and merge
Eric Eisner <ede@mit.edu>
parents: 12993
diff changeset
   809
        self._fetch(source, revision)
13085
b4814f1f415c subrepo: strip gitcommand output
Eric Eisner <ede@mit.edu>
parents: 13029
diff changeset
   810
        base = self._gitcommand(['merge-base', revision, self._state[1]])
12994
845c602b8635 subrepo: allow git subrepos to push and merge
Eric Eisner <ede@mit.edu>
parents: 12993
diff changeset
   811
        if base == revision:
845c602b8635 subrepo: allow git subrepos to push and merge
Eric Eisner <ede@mit.edu>
parents: 12993
diff changeset
   812
            self.get(state) # fast forward merge
845c602b8635 subrepo: allow git subrepos to push and merge
Eric Eisner <ede@mit.edu>
parents: 12993
diff changeset
   813
        elif base != self._state[1]:
845c602b8635 subrepo: allow git subrepos to push and merge
Eric Eisner <ede@mit.edu>
parents: 12993
diff changeset
   814
            self._gitcommand(['merge', '--no-commit', revision])
845c602b8635 subrepo: allow git subrepos to push and merge
Eric Eisner <ede@mit.edu>
parents: 12993
diff changeset
   815
845c602b8635 subrepo: allow git subrepos to push and merge
Eric Eisner <ede@mit.edu>
parents: 12993
diff changeset
   816
    def push(self, force):
13029
f930032aa6d5 subrepo: lazier git push logic
Eric Eisner <ede@mit.edu>
parents: 13027
diff changeset
   817
        # if a branch in origin contains the revision, nothing to do
13152
70d80907e4b8 subrepo: defer determination of git's current branch
Eric Eisner <ede@mit.edu>
parents: 13151
diff changeset
   818
        branch2rev, rev2branch, tracking = self._gitbranchmap()
13109
53341289eaf8 subrepo: speed up git push logic
Eric Eisner <ede@mit.edu>
parents: 13108
diff changeset
   819
        if self._state[1] in rev2branch:
53341289eaf8 subrepo: speed up git push logic
Eric Eisner <ede@mit.edu>
parents: 13108
diff changeset
   820
            for b in rev2branch[self._state[1]]:
13150
8617b8b74fae subrepo: use low-level git-for-each-ref command in branchmap
Eric Eisner <ede@mit.edu>
parents: 13144
diff changeset
   821
                if b.startswith('refs/remotes/origin/'):
13109
53341289eaf8 subrepo: speed up git push logic
Eric Eisner <ede@mit.edu>
parents: 13108
diff changeset
   822
                    return True
13086
8db85e39d59c subrepo: return both mapping directions from gitbranchmap
Eric Eisner <ede@mit.edu>
parents: 13085
diff changeset
   823
        for b, revision in branch2rev.iteritems():
13150
8617b8b74fae subrepo: use low-level git-for-each-ref command in branchmap
Eric Eisner <ede@mit.edu>
parents: 13144
diff changeset
   824
            if b.startswith('refs/remotes/origin/'):
13086
8db85e39d59c subrepo: return both mapping directions from gitbranchmap
Eric Eisner <ede@mit.edu>
parents: 13085
diff changeset
   825
                if self._gitisancestor(self._state[1], revision):
8db85e39d59c subrepo: return both mapping directions from gitbranchmap
Eric Eisner <ede@mit.edu>
parents: 13085
diff changeset
   826
                    return True
13029
f930032aa6d5 subrepo: lazier git push logic
Eric Eisner <ede@mit.edu>
parents: 13027
diff changeset
   827
        # otherwise, try to push the currently checked out branch
12994
845c602b8635 subrepo: allow git subrepos to push and merge
Eric Eisner <ede@mit.edu>
parents: 12993
diff changeset
   828
        cmd = ['push']
845c602b8635 subrepo: allow git subrepos to push and merge
Eric Eisner <ede@mit.edu>
parents: 12993
diff changeset
   829
        if force:
845c602b8635 subrepo: allow git subrepos to push and merge
Eric Eisner <ede@mit.edu>
parents: 12993
diff changeset
   830
            cmd.append('--force')
13152
70d80907e4b8 subrepo: defer determination of git's current branch
Eric Eisner <ede@mit.edu>
parents: 13151
diff changeset
   831
70d80907e4b8 subrepo: defer determination of git's current branch
Eric Eisner <ede@mit.edu>
parents: 13151
diff changeset
   832
        current = self._gitcurrentbranch()
12995
d90fc91c8377 subrepo: update and merge works with any git branch
Eric Eisner <ede@mit.edu>
parents: 12994
diff changeset
   833
        if current:
13029
f930032aa6d5 subrepo: lazier git push logic
Eric Eisner <ede@mit.edu>
parents: 13027
diff changeset
   834
            # determine if the current branch is even useful
f930032aa6d5 subrepo: lazier git push logic
Eric Eisner <ede@mit.edu>
parents: 13027
diff changeset
   835
            if not self._gitisancestor(self._state[1], current):
f930032aa6d5 subrepo: lazier git push logic
Eric Eisner <ede@mit.edu>
parents: 13027
diff changeset
   836
                self._ui.warn(_('unrelated git branch checked out '
f930032aa6d5 subrepo: lazier git push logic
Eric Eisner <ede@mit.edu>
parents: 13027
diff changeset
   837
                                'in subrepo %s\n') % self._relpath)
f930032aa6d5 subrepo: lazier git push logic
Eric Eisner <ede@mit.edu>
parents: 13027
diff changeset
   838
                return False
f930032aa6d5 subrepo: lazier git push logic
Eric Eisner <ede@mit.edu>
parents: 13027
diff changeset
   839
            self._ui.status(_('pushing branch %s of subrepo %s\n') %
13150
8617b8b74fae subrepo: use low-level git-for-each-ref command in branchmap
Eric Eisner <ede@mit.edu>
parents: 13144
diff changeset
   840
                            (current.split('/', 2)[2], self._relpath))
13097
c922aacf6f1f subrepo: drop arguments unsupported by old git
Eric Eisner <ede@mit.edu>
parents: 13096
diff changeset
   841
            self._gitcommand(cmd + ['origin', current])
12995
d90fc91c8377 subrepo: update and merge works with any git branch
Eric Eisner <ede@mit.edu>
parents: 12994
diff changeset
   842
            return True
d90fc91c8377 subrepo: update and merge works with any git branch
Eric Eisner <ede@mit.edu>
parents: 12994
diff changeset
   843
        else:
d90fc91c8377 subrepo: update and merge works with any git branch
Eric Eisner <ede@mit.edu>
parents: 12994
diff changeset
   844
            self._ui.warn(_('no branch checked out in subrepo %s\n'
13029
f930032aa6d5 subrepo: lazier git push logic
Eric Eisner <ede@mit.edu>
parents: 13027
diff changeset
   845
                            'cannot push revision %s') %
f930032aa6d5 subrepo: lazier git push logic
Eric Eisner <ede@mit.edu>
parents: 13027
diff changeset
   846
                          (self._relpath, self._state[1]))
12995
d90fc91c8377 subrepo: update and merge works with any git branch
Eric Eisner <ede@mit.edu>
parents: 12994
diff changeset
   847
            return False
12994
845c602b8635 subrepo: allow git subrepos to push and merge
Eric Eisner <ede@mit.edu>
parents: 12993
diff changeset
   848
12996
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   849
    def remove(self):
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   850
        if self.dirty():
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   851
            self._ui.warn(_('not removing repo %s because '
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   852
                            'it has changes.\n') % self._path)
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   853
            return
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   854
        # we can't fully delete the repository as it may contain
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   855
        # local-only history
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   856
        self._ui.note(_('removing subrepo %s\n') % self._path)
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   857
        self._gitcommand(['config', 'core.bare', 'true'])
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   858
        for f in os.listdir(self._path):
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   859
            if f == '.git':
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   860
                continue
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   861
            path = os.path.join(self._path, f)
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   862
            if os.path.isdir(path) and not os.path.islink(path):
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   863
                shutil.rmtree(path)
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   864
            else:
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   865
                os.remove(path)
3a42651b0a62 subrepo: removing (and restoring) git subrepo state
Eric Eisner <ede@mit.edu>
parents: 12995
diff changeset
   866
13144
aae2d5cbde64 subrepo: add progress bar support to archive
Martin Geisler <mg@aragost.com>
parents: 13137
diff changeset
   867
    def archive(self, ui, archiver, prefix):
13027
7f2ecb64140d subrepo: archive git subrepos
Eric Eisner <ede@mit.edu>
parents: 13018
diff changeset
   868
        source, revision = self._state
7f2ecb64140d subrepo: archive git subrepos
Eric Eisner <ede@mit.edu>
parents: 13018
diff changeset
   869
        self._fetch(source, revision)
7f2ecb64140d subrepo: archive git subrepos
Eric Eisner <ede@mit.edu>
parents: 13018
diff changeset
   870
7f2ecb64140d subrepo: archive git subrepos
Eric Eisner <ede@mit.edu>
parents: 13018
diff changeset
   871
        # Parse git's native archive command.
7f2ecb64140d subrepo: archive git subrepos
Eric Eisner <ede@mit.edu>
parents: 13018
diff changeset
   872
        # This should be much faster than manually traversing the trees
7f2ecb64140d subrepo: archive git subrepos
Eric Eisner <ede@mit.edu>
parents: 13018
diff changeset
   873
        # and objects with many subprocess calls.
7f2ecb64140d subrepo: archive git subrepos
Eric Eisner <ede@mit.edu>
parents: 13018
diff changeset
   874
        tarstream = self._gitcommand(['archive', revision], stream=True)
7f2ecb64140d subrepo: archive git subrepos
Eric Eisner <ede@mit.edu>
parents: 13018
diff changeset
   875
        tar = tarfile.open(fileobj=tarstream, mode='r|')
13144
aae2d5cbde64 subrepo: add progress bar support to archive
Martin Geisler <mg@aragost.com>
parents: 13137
diff changeset
   876
        relpath = subrelpath(self)
aae2d5cbde64 subrepo: add progress bar support to archive
Martin Geisler <mg@aragost.com>
parents: 13137
diff changeset
   877
        ui.progress(_('archiving (%s)') % relpath, 0, unit=_('files'))
aae2d5cbde64 subrepo: add progress bar support to archive
Martin Geisler <mg@aragost.com>
parents: 13137
diff changeset
   878
        for i, info in enumerate(tar):
13027
7f2ecb64140d subrepo: archive git subrepos
Eric Eisner <ede@mit.edu>
parents: 13018
diff changeset
   879
            archiver.addfile(os.path.join(prefix, self._relpath, info.name),
7f2ecb64140d subrepo: archive git subrepos
Eric Eisner <ede@mit.edu>
parents: 13018
diff changeset
   880
                             info.mode, info.issym(),
7f2ecb64140d subrepo: archive git subrepos
Eric Eisner <ede@mit.edu>
parents: 13018
diff changeset
   881
                             tar.extractfile(info).read())
13144
aae2d5cbde64 subrepo: add progress bar support to archive
Martin Geisler <mg@aragost.com>
parents: 13137
diff changeset
   882
            ui.progress(_('archiving (%s)') % relpath, i + 1,
aae2d5cbde64 subrepo: add progress bar support to archive
Martin Geisler <mg@aragost.com>
parents: 13137
diff changeset
   883
                        unit=_('files'))
aae2d5cbde64 subrepo: add progress bar support to archive
Martin Geisler <mg@aragost.com>
parents: 13137
diff changeset
   884
        ui.progress(_('archiving (%s)') % relpath, None)
aae2d5cbde64 subrepo: add progress bar support to archive
Martin Geisler <mg@aragost.com>
parents: 13137
diff changeset
   885
13027
7f2ecb64140d subrepo: archive git subrepos
Eric Eisner <ede@mit.edu>
parents: 13018
diff changeset
   886
10177
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
   887
types = {
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
   888
    'hg': hgsubrepo,
10178
cd477be6f2fc subrepo: Subversion support
Augie Fackler <durin42@gmail.com>
parents: 10177
diff changeset
   889
    'svn': svnsubrepo,
12992
2b73a3279a9f subrepo: support for adding a git subrepo
Eric Eisner <ede@mit.edu>
parents: 12930
diff changeset
   890
    'git': gitsubrepo,
10177
5ca0d220ae21 subrepo: add table-based dispatch for subrepo types
Augie Fackler <durin42@gmail.com>
parents: 10175
diff changeset
   891
    }