mercurial/subrepo.py
changeset 8814 ab668c92a036
parent 8813 db3c1ab0e632
child 8815 e87b0fc4750b
equal deleted inserted replaced
8813:db3c1ab0e632 8814:ab668c92a036
     4 #
     4 #
     5 # This software may be used and distributed according to the terms of the
     5 # This software may be used and distributed according to the terms of the
     6 # GNU General Public License version 2, incorporated herein by reference.
     6 # GNU General Public License version 2, incorporated herein by reference.
     7 
     7 
     8 import errno, os
     8 import errno, os
       
     9 from i18n import _
     9 import config, util, node, error
    10 import config, util, node, error
    10 localrepo = None
    11 localrepo = hg = None
    11 
    12 
    12 nullstate = ('', '')
    13 nullstate = ('', '')
    13 
    14 
    14 def state(ctx):
    15 def state(ctx):
    15     p = config.config()
    16     p = config.config()
    41 def writestate(repo, state):
    42 def writestate(repo, state):
    42     repo.wwrite('.hgsubstate',
    43     repo.wwrite('.hgsubstate',
    43                 ''.join(['%s %s\n' % (state[s][1], s)
    44                 ''.join(['%s %s\n' % (state[s][1], s)
    44                          for s in sorted(state)]), '')
    45                          for s in sorted(state)]), '')
    45 
    46 
       
    47 def submerge(repo, wctx, mctx, actx):
       
    48     if mctx == actx: # backwards?
       
    49         actx = wctx.p1()
       
    50     s1 = wctx.substate
       
    51     s2 = mctx.substate
       
    52     sa = actx.substate
       
    53     sm = {}
       
    54 
       
    55     for s, l in s1.items():
       
    56         a = sa.get(s, nullstate)
       
    57         if s in s2:
       
    58             r = s2[s]
       
    59             if l == r or r == a: # no change or local is newer
       
    60                 sm[s] = l
       
    61                 continue
       
    62             elif l == a: # other side changed
       
    63                 wctx.sub(s).get(r)
       
    64                 sm[s] = r
       
    65             elif l[0] != r[0]: # sources differ
       
    66                 if repo.ui.prompt(
       
    67                     _(' subrepository sources for %s differ\n'
       
    68                       'use (l)ocal source (%s) or (r)emote source (%s)?'
       
    69                       % (s, l[0], r[0]),
       
    70                       (_('&Local'), _('&Remote')), _('l'))) == _('r'):
       
    71                     wctx.sub(s).get(r)
       
    72                     sm[s] = r
       
    73             elif l[1] == a[1]: # local side is unchanged
       
    74                 wctx.sub(s).get(r)
       
    75                 sm[s] = r
       
    76             else:
       
    77                 wctx.sub(s).merge(r)
       
    78                 sm[s] = l
       
    79         elif l == a: # remote removed, local unchanged
       
    80             wctx.sub(s).remove()
       
    81         else:
       
    82             if repo.ui.prompt(
       
    83                 _(' local changed subrepository %s which remote removed\n'
       
    84                   'use (c)hanged version or (d)elete?' % s,
       
    85                   (_('&Changed'), _('&Delete')), _('c'))) == _('d'):
       
    86                 wctx.sub(s).remove()
       
    87 
       
    88     for s, r in s2.items():
       
    89         if s in s1:
       
    90             continue
       
    91         elif s not in sa:
       
    92             wctx.sub(s).get(r)
       
    93             sm[s] = r
       
    94         elif r != sa[s]:
       
    95             if repo.ui.prompt(
       
    96                 _(' remote changed subrepository %s which local removed\n'
       
    97                   'use (c)hanged version or (d)elete?' % s,
       
    98                   (_('&Changed'), _('&Delete')), _('c'))) == _('c'):
       
    99                 wctx.sub(s).get(r)
       
   100                 sm[s] = r
       
   101 
       
   102     # record merged .hgsubstate
       
   103     writestate(repo, sm)
       
   104 
       
   105 def _abssource(repo):
       
   106     if hasattr(repo, '_subparent'):
       
   107         source = repo._subsource
       
   108         if source.startswith('/') or '://' in source:
       
   109             return source
       
   110         return os.path.join(_abssource(repo._subparent), repo._subsource)
       
   111     return repo.ui.config('paths', 'default', repo.root)
       
   112 
    46 def subrepo(ctx, path):
   113 def subrepo(ctx, path):
    47     # subrepo inherently violates our import layering rules
   114     # subrepo inherently violates our import layering rules
    48     # because it wants to make repo objects from deep inside the stack
   115     # because it wants to make repo objects from deep inside the stack
    49     # so we manually delay the circular imports to not break
   116     # so we manually delay the circular imports to not break
    50     # scripts that don't use our demand-loading
   117     # scripts that don't use our demand-loading
    51     global localrepo
   118     global localrepo, hg
    52     import localrepo as l
   119     import localrepo as l, hg as h
    53     localrepo = l
   120     localrepo = l
       
   121     hg = h
    54 
   122 
    55     state = ctx.substate.get(path, nullstate)
   123     state = ctx.substate.get(path, nullstate)
    56     if state[0].startswith('['): # future expansion
   124     if state[0].startswith('['): # future expansion
    57         raise error.Abort('unknown subrepo source %s' % state[0])
   125         raise error.Abort('unknown subrepo source %s' % state[0])
    58     return hgsubrepo(ctx, path, state)
   126     return hgsubrepo(ctx, path, state)
    62         self._parent = ctx
   130         self._parent = ctx
    63         self._path = path
   131         self._path = path
    64         self._state = state
   132         self._state = state
    65         r = ctx._repo
   133         r = ctx._repo
    66         root = r.wjoin(path)
   134         root = r.wjoin(path)
    67         self._repo = localrepo.localrepository(r.ui, root)
   135         if os.path.exists(os.path.join(root, '.hg')):
       
   136             self._repo = localrepo.localrepository(r.ui, root)
       
   137         else:
       
   138             util.makedirs(root)
       
   139             self._repo = localrepo.localrepository(r.ui, root, create=True)
       
   140         self._repo._subparent = r
       
   141         self._repo._subsource = state[0]
    68 
   142 
    69     def dirty(self):
   143     def dirty(self):
    70         r = self._state[1]
   144         r = self._state[1]
    71         if r == '':
   145         if r == '':
    72             return True
   146             return True
    78     def commit(self, text, user, date):
   152     def commit(self, text, user, date):
    79         n = self._repo.commit(text, user, date)
   153         n = self._repo.commit(text, user, date)
    80         if not n:
   154         if not n:
    81             return self._repo['.'].hex() # different version checked out
   155             return self._repo['.'].hex() # different version checked out
    82         return node.hex(n)
   156         return node.hex(n)
       
   157 
       
   158     def remove(self):
       
   159         # we can't fully delete the repository as it may contain
       
   160         # local-only history
       
   161         self._repo.ui.note(_('removing subrepo %s\n') % self._path)
       
   162         hg.clean(self._repo, node.nullid, False)
       
   163 
       
   164     def get(self, state):
       
   165         source, revision = state
       
   166         try:
       
   167             self._repo.lookup(revision)
       
   168         except error.RepoError:
       
   169             self._repo._subsource = source
       
   170             self._repo.ui.status(_('pulling subrepo %s\n') % self._path)
       
   171             srcurl = _abssource(self._repo)
       
   172             other = hg.repository(self._repo.ui, srcurl)
       
   173             self._repo.pull(other)
       
   174 
       
   175         hg.clean(self._repo, revision, False)
       
   176 
       
   177     def merge(self, state):
       
   178         hg.merge(self._repo, state[1], remind=False)