@@ 139,7 139,8 @@ cmdtable = {
"hg grupdate [REPO [+]] [options]"),
"grfreeze": (freeze,
[('f', 'file', '', "output state to a .hggrfrozen file", 'FILE'),
- ('p', 'publish', False, "publish all record changeset"),]
+ ('p', 'publish', False, "publish all record changeset"),
+ ('k', 'keep', False, "keep previous changeid of unmodified guests"),]
+ threadopt,
"hg grfreeze"),
"grsummary": (summary,
@@ 148,7 149,8 @@ cmdtable = {
+ jsonopt + localopt,
"hg grsummary"),
"grstate": (state,
- jsonopt + localopt,
+ [('k', 'keep', False, "keep previous changeid of unmodified guests"),]
+ + jsonopt + localopt,
"hg grstate"),
"grout" : (grout,
localopt + threadopt + jsonopt,
@@ 1,4 1,6 @@
# Guestrepo: A Mercurial Extension for the managing of components
+# Copyright (C) 2013-2015 Paul Nathan
+# Other copyrights as found in hg.
# Copyright (C) 2012 Schweitzer Engineering Laboratories, Inc.
# This program is free software; you can redistribute it and/or modify
@@ 118,7 120,7 @@ def grupdate(ui, repo, *args, **opts):
if opts.get('file'):
guests = getguests(ui, repo, opts.get('file'), local=opts.get('local'))
else:
- guests = getguests(ui, repo, local=opts.get('local'))
+ guests = getguests(ui, repo, local=opts.get('local'), check=True)
if args:
guests = matchguests(repo.root,
@@ 247,7 249,7 @@ def pull(ui, repo, *args, **opts):
see help for the guestrepo extension for more information on the files used
'''
- guests = getguests(ui, repo, local=opts.get('local'))
+ guests = getguests(ui, repo, local=opts.get('local'), check=True)
if args:
guests = matchguests(repo.root,
@@ 404,13 406,8 @@ def state(ui, repo, **opts):
'id' : dict_rep['id']})
ui.write(json.dumps(json_list) + "\n")
else:
- # '%-10s' : left justifier at least 10 chars (space completed)
- # => 'guest = myguest default'
- lines = ("%-10s = %-10s %s\n" % (guest.configpath,
- guest.name,
- guest.get_cset(ui, '.').hex())
- for guest in filterwarnguests(ui, guests))
- ui.write(''.join(lines))
+ statestr = makestatestr(getstate(ui, repo, guests, opts.get('keep')))
+ ui.write(statestr)
@warn_uncomitted_config
def freeze(ui, repo, **opts):
@@ 425,12 422,15 @@ def freeze(ui, repo, **opts):
``.hgguestrepo`` file.
'''
guests = getguests(ui, repo)
+ state = getstate(ui, repo, guests, opts.get('keep'))
+ statestr = makestatestr(state)
if opts.get('publish', False):
+ state = dict(state)
if not SUPPORTS_PHASES:
msg = 'your version of Mercurial does not support phases'
raise util.Abort(msg)
def publishaction(ui, repo, guest):
- commands.phase(ui, repo, rev=[guest.get_cset(ui, rev='.').hex()],
+ commands.phase(ui, repo, rev=[state[guest]],
public=True, draft=None, secret=None, force=False)
workers = makeworkers(ui, opts)
@@ 615,13 615,13 @@ def getmapping(ui, repo, useworkingmap=F
# detect case of uncommitted branch
currentbranch = currentctx.branch()
if currentbranch not in repo.branchmap():
- raise util.Abort("unmanaged mapping file: "
- "no commits on current branch")
+ raise util.Abort("unmanaged mapping file; no commits on current branch")
# Use the current changeset as a base for the mapping
ctx = repo['.']
return conf.load_mapping(ctx)
+
def getguests(ui, repo, frozen_file=None, ctx=None, **kwargs):
''' Get the guest repos by parsing the .hgguestrepo.
@@ 631,6 631,8 @@ def getguests(ui, repo, frozen_file=None
local = kwargs.get('local')
+ check = kwargs.get('check')
+ skip = False
# Two choices: we can either mooch the local (uncommitted)
# changes (using --local), or we go for the local ctx
@@ 841,6 843,60 @@ def applyguests(ui, repo, guests, worker
if work:
workers.run(work, guest)
+def readconfig(filename, ctx):
+ ''' read a config file at a context
+
+ throws IOError when config file missing from the working directory,
+ error. LookupError if config is missing from a changeset
+ '''
+ p = config.config()
+ p.parse(filename, ctx[filename].data())
+ return p
+
+def makestatestr(states):
+ '''
+ Create a description string for a list of state.
+
+ It can also return the same string in JSON.
+ '''
+ lines = []
+ for guest, hex in states:
+ lines.append("%s = %s %s\n" %
+ (guest.configpath.ljust(10),
+ guest.name.ljust(10),
+ hex))
+ return ''.join(lines)
+
+
+def getstate(ui, repo, guests, keep=False):
+ '''
+ Return a list of repo's guest's state.
+
+ :keep: do not change previous state if guest remains unchanged
+ '''
+ states = []
+ conf = get_conf(ui, repo)
+ # in legacy config (.hgguestrepo): path = <identifier> changeset
+ # in current config (.hggrsnap): path = changeset
+ config = conf.load_conf_as_kv_pair(repo['.'])
+ for guest in filterwarnguests(ui, guests):
+ guestrepo = hg.repository(ui, guest.root, create=False)
+ guestctx = guestrepo['.']
+ gueststate = guestctx.hex()
+ # we try to see if we can keep the previous saved state
+ if keep:
+ guestconfig = config.get(guest.configpath, None)
+ if guestconfig is not None:
+ # pick off the changeset...
+ initialstate = guestconfig.split()[-1]
+ try:
+ if guestrepo[initialstate] == guestrepo['.']:
+ gueststate = initialstate
+ except error.RepoLookupError:
+ pass # initial state not found
+ states.append((guest, gueststate))
+ return states
+
def template_output_to_list(template_output):
'''
Take the output of hg.incoming or hg.incoming formatted using the
@@ 878,3 934,58 @@ def template_output_to_list(template_out
in_records.append(loaded_object)
return in_records
+
+
+
+# N.b., might be dead code.
+class guestrepo(object):
+ '''An aggregate representing a guest repository'''
+ def __init__(self, name, configpath, canonpath, uri, csid, root):
+ self.name = name
+ self.configpath = configpath
+ self.canonpath = canonpath
+ self.uri = uri
+ self.csid = csid
+ self.root = root
+
+ def isrepo(self, warn=False):
+ return os.path.exists(os.path.join(self.root, '.hg'))
+
+ def to_dict(self, ui):
+ '''
+ Output all of the metadata associated with a Guestrepo as a dict
+ '''
+ guestrepo = hg.repository(ui, self.root, create=False)
+ guestctx = guestrepo[None]
+
+ # Set up GR attributes in JSON
+ json_dict = {'path' : self.canonpath}
+ json_dict['branch'] = guestctx.branch()
+ json_dict['remote_name'] = self.name
+
+ parents = guestctx.parents()
+ json_dict['id'] = (' '.join(['+'.join([node.hex(p.node()) for p in parents]), ]))[:12]
+
+ if guestctx.tags():
+ json_dict['tags'] = '/'.join(guestctx.tags())
+
+ if guestctx.bookmarks():
+ json_dict['bookmarks'] = '/'.join(guestctx.bookmarks())
+
+ current_bookmark = bookmarks.readcurrent(guestrepo)
+
+ if current_bookmark:
+ json_dict['current_bookmark'] = current_bookmark
+
+ if changed(guestrepo):
+ json_dict['changed'] = True
+
+ return json_dict
+
+ def to_gr_entry(self, ui):
+ guestrepo = hg.repository(ui, self.root, create=False)
+ changeset_id = node.hex(guestrepo[None].parents()[0].node())
+ return "%s = %s %s\n" % self.configpath.ljust(10), self.name.ljust(10), changeset_id
+
+ def to_mapping_entry(self, ui):
+ return "%s = %s" % self.configpath.ljust(10), self.name