Commits

Anonymous committed 4801142

added tasksoutgoing, outgoing now accepts --all-tasks and --completed-tasks options just as push does.
refactored takspush to share code with tasksoutgoing.
refs #17

  • Participants
  • Parent commits 2cd89b4

Comments (0)

Files changed (1)

File hgext/tasks.py

     else:
         return repo.changelog.nodesbetween([tinfo['start']], [tinfo['end']])[0]
 
+def incompletetasknodes(repo):
+    tasks = parse(repo)
+    itasknodes = []
+    for tname, tinfo in tasks.iteritems():
+        if tinfo['state'] == 1:
+            itasknodes += tasknodes(repo, tinfo)
+    return itasknodes
+
 def task(ui, repo, task=None, rev=None, force=False, delete=False, info=None,
         all=False, complete=None, resume=None, delete_all=False,
         delete_complete=False, rename=None, trim=None, append=None,
     extensions.wrapcommand(commands.table, 'update', tasksupdate)
     extensions.wrapcommand(commands.table, 'log', taskslog)
     extensions.wrapcommand(commands.table, 'export', tasksexport)
+    extensions.wrapcommand(commands.table, 'outgoing', tasksoutgoing)
     entry = extensions.wrapcommand(commands.table, 'push', taskspush)
     entry[1].append(('', 'completed-tasks', None,
         _('push all heads that have completed tasks only')))
                 (repo.changelog.rev(nodes[-1]), repo.changelog.rev(nodes[0]))]
     return orig(ui, repo, *args, **opts)
 
+
+
+
 def stashshas(repo, task):
     '''retrieve sha values from task stash'''
     stashpatch = stashfiles(repo, task)[0]
     showtask(ui, repo, task, tasks[task])
     return
 
-def taskspush(orig, ui, repo, dest=None, **opts):
-    if opts.get('completed_tasks') and opts.get('all_tasks'):
-        raise util.Abort(_('cannot specify both --all-tasks and '
-                           '--completed-tasks'))
-
-    if opts.get('all_tasks'):
-        return orig(ui, repo, dest, **opts)
-
-    # create a list of nodes inside incompleted tasks
-    tasks = parse(repo)
-    itasknodes = []
-    for tname, tinfo in tasks.iteritems():
-        if tinfo['state'] == 1:
-            itasknodes += tasknodes(repo, tinfo)
-
-    # no need to do anything if all tasks complete
-    if not itasknodes:
-        return orig(ui, repo, dest, **opts)
-
+def outgoingnodes(ui, repo, dest=None, **opts):
     # get remote repo
     dest, revs, checkout = hg.parseurl(ui.expandpath(dest or 'default-push',
         dest or 'default'), opts.get('rev'))
         cmdutil.setremoteconfig(ui, opts)
         remote = hg.repository(ui, dest)
 
-    # suppress output of this since it unfortunately gets called again
+    # suppress output
     ui.pushbuffer()
     out = repo.findoutgoing(remote, None)
     ui.flush()
 
     if revs:
         revs = [repo.lookup(rev) for rev in revs]
-    outnodes = repo.changelog.nodesbetween(out, revs)[0]
+    return repo.changelog.nodesbetween(out, revs)[0]
 
-    # find outgoing nodes that are in incomplete tasks
-    havebadnode = False
-    for onode in outnodes:
-        if onode in itasknodes:
-            havebadnode = True
-            break
+def hasincompletetask(repo):
+    tasks = parse(repo)
+    for tname, tinfo in tasks.iteritems():
+        if tinfo['state'] == 1:
+            return True;
+    return False
 
-    if not havebadnode:
+def hasintersection(l1, l2):
+    for i in l1:
+        if i in l2:
+            return True
+    return False
+
+
+def tasksoutgoing(orig, ui, repo, dest=None, **opts):
+    if opts.get('all_tasks') or not hasincompletetask(repo):
+        return orig(ui, repo, dest, **opts)
+
+    outnodes = outgoingnodes(ui, repo, dest, **opts)
+    completenodes = stripincomplete(repo, outnodes)
+
+    if opts.get('completed_tasks') or completenodes == outnodes:
+        opts['rev'] = completenodes
+        return orig(ui, repo, dest, **opts)
+    else:
+        res = orig(ui, repo, dest, **opts)
+        ui.warn("warning: incomplete tasks found in outgoing changesets\n"
+            "(use --all-tasks to suppress this message or --completed-tasks to"
+            " prune)\n")
+        return res
+
+def stripincomplete(repo, nodes):
+    stripnodes = set()
+    tasks = parse(repo)
+    for tname, tinfo in tasks.iteritems():
+        if tinfo['state'] == 1:
+            stripnodes |= set(repo.changelog.nodesbetween([ tinfo['start'] ],
+                    None)[0])
+    return list(set(nodes) - stripnodes)
+
+
+def taskspush(orig, ui, repo, dest=None, **opts):
+    if opts.get('completed_tasks') and opts.get('all_tasks'):
+        raise util.Abort(_('cannot specify both --all-tasks and '
+                           '--completed-tasks'))
+
+    if opts.get('all_tasks') or not hasincompletetask(repo):
+        return orig(ui, repo, dest, **opts)
+
+    outnodes = outgoingnodes(ui, repo, dest, **opts)
+    completenodes = stripincomplete(repo, outnodes)
+
+    if outnodes == completenodes:
         return orig(ui, repo, dest, **opts)
 
     if not opts.get('completed_tasks'):
         raise util.Abort(_('pushing incomplete tasks\n'
             '(use --all-tasks to force or --completed-tasks to prune)'))
 
-    # prune nodes from incomplete tasks
     ui.status('searching for completed tasks\n')
-    nodestoremove = []
-    for onode in outnodes:
-        for tname, tinfo in tasks.iteritems():
-            if tinfo['state'] == 1:
-                if onode in tasknodes(repo, tinfo):
-                    # we have to remove all nodes between this node and
-                    # the end node for this task
-                    for n in repo.changelog.nodesbetween([ onode ],
-                            None)[0]:
-                        nodestoremove.append(n)
-    opts['rev'] = [ n for n in outnodes if n not in nodestoremove ]
+    opts['rev'] = completenodes
     return orig(ui, repo, dest, **opts)