Add a family of git-commands to assist with the management of multiple CLs/branches.

git-rebase-update - ensure all branches are up to date
git-new-branch - create branches
git-rename-branch - rename a branch while preserving parentage relationships
git-reparent-branch - change the parent of a branch, including rebasing it correctly onto that new parent.
git-squash-branch - collapse a branch into a single commit
git-upstream-diff - show the diff between the current branch and it's upstream branch
git-mark-merge-base - explicitly set what you want the above tools to consider the merge-base for the current branch.

R=agable@chromium.org, hinoka@chromium.org, stip@chromium.org, szager@chromium.org
BUG=261738

Review URL: https://codereview.chromium.org/184253003

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@259520 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/git_map_branches.py b/git_map_branches.py
index fc6c8ce..7351790 100755
--- a/git_map_branches.py
+++ b/git_map_branches.py
@@ -19,9 +19,11 @@
     * Note that multiple branches may be Cyan, if they are all on the same
       commit, and you have that commit checked out.
   * Green - a local branch
-  * Magenta - a placeholder for the '{NO UPSTREAM}' "branch". If you have
-    local branches which do not track any upstream, then you will see this.
+  * Magenta - a tag
+  * Magenta '{NO UPSTREAM}' - If you have local branches which do not track any
+    upstream, then you will see this.
 """
+
 import collections
 import sys
 
@@ -29,15 +31,14 @@
 from third_party.colorama import Fore, Style
 
 from git_common import current_branch, branches, upstream, hash_one, hash_multi
+from git_common import tags
 
 NO_UPSTREAM = '{NO UPSTREAM}'
 
-def print_branch(cur, cur_hash, branch, branch_hashes, par_map, branch_map,
-                 depth=0):
-  branch_hash = branch_hashes[branch]
+def color_for_branch(branch, branch_hash, cur_hash, tag_set):
   if branch.startswith('origin'):
     color = Fore.RED
-  elif branch == NO_UPSTREAM:
+  elif branch == NO_UPSTREAM or branch in tag_set:
     color = Fore.MAGENTA
   elif branch_hash == cur_hash:
     color = Fore.CYAN
@@ -49,6 +50,15 @@
   else:
     color += Style.NORMAL
 
+  return color
+
+
+def print_branch(cur, cur_hash, branch, branch_hashes, par_map, branch_map,
+                 tag_set, depth=0):
+  branch_hash = branch_hashes[branch]
+
+  color = color_for_branch(branch, branch_hash, cur_hash, tag_set)
+
   suffix = ''
   if cur == 'HEAD':
     if branch_hash == cur_hash:
@@ -59,7 +69,7 @@
   print color + "  "*depth + branch + suffix
   for child in par_map.pop(branch, ()):
     print_branch(cur, cur_hash, child, branch_hashes, par_map, branch_map,
-                 depth=depth+1)
+                 tag_set, depth=depth+1)
 
 
 def main(argv):
@@ -77,13 +87,14 @@
   current_hash = hashes[0]
   par_hashes = {k: hashes[i+1] for i, k in enumerate(branch_map.iterkeys())}
   par_hashes[NO_UPSTREAM] = 0
+  tag_set = tags()
   while par_map:
     for parent in par_map:
       if parent not in branch_map:
         if parent not in par_hashes:
           par_hashes[parent] = hash_one(parent)
         print_branch(current, current_hash, parent, par_hashes, par_map,
-                     branch_map)
+                     branch_map, tag_set)
         break