fromupstream: Allow picking from git repos directly

It's sort of annoying to have to add remotes for one-off git trees of
maintainers to pick into the tree. Add a way to pick patches from a git
tree directly as long as the form follows git://repo#branch/sha1. To
differentiate this from the 'fromgit' syntax, let's deprecate
fromgit://remote/branch/sha1 and replace it with
git://remote/branch/sha1 by updating the regex to look for lines that
don't have the '#' symbol.

This makes it a little faster to pick patches from random git repos.

BUG=None
TEST=Pick with new syntax and see if it works

Change-Id: Ia31743bc56800bef69fb54360e95f387bb87bd9e
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1308315
Reviewed-by: Douglas Anderson <dianders@chromium.org>
diff --git a/contrib/fromupstream.py b/contrib/fromupstream.py
index 871708f..3590a42 100755
--- a/contrib/fromupstream.py
+++ b/contrib/fromupstream.py
@@ -147,7 +147,9 @@
                         'PROJECT is specified, the default is retrieved from ' +
                         '~/.pwclientrc), ' +
                         'linux commit like linux://HASH, or ' +
-                        'git reference like fromgit://remote/branch/HASH')
+                        'git reference like git://remote/branch/HASH or ' +
+                        'git://repoURL#branch/HASH or ' +
+                        'https://repoURL#branch/HASH')
 
     args = vars(parser.parse_args(args))
 
@@ -191,7 +193,10 @@
             r'linux://([0-9a-f]+)', location
         )
         fromgit_match = re.match(
-            r'fromgit://([^/]+)/(.+)/([0-9a-f]+)$', location
+            r'(from)?git://([^/\#]+)/([^#]+)/([0-9a-f]+)$', location
+        )
+        gitfetch_match = re.match(
+            r'((git|https)://.+)#(.+)/([0-9a-f]+)$', location
         )
 
         if patchwork_match is not None:
@@ -258,9 +263,9 @@
 
             ret = subprocess.call(['git', 'cherry-pick', commit])
         elif fromgit_match is not None:
-            remote = fromgit_match.group(1)
-            branch = fromgit_match.group(2)
-            commit = fromgit_match.group(3)
+            remote = fromgit_match.group(2)
+            branch = fromgit_match.group(3)
+            commit = fromgit_match.group(4)
 
             ret = subprocess.call(['git', 'merge-base', '--is-ancestor',
                                    commit, '%s/%s' % (remote, branch)])
@@ -288,6 +293,30 @@
                 subprocess.call(['git', 'reset', '--hard', 'HEAD~1'])
 
             ret = subprocess.call(['git', 'cherry-pick', commit])
+        elif gitfetch_match is not None:
+            remote = gitfetch_match.group(1)
+            branch = gitfetch_match.group(3)
+            commit = gitfetch_match.group(4)
+
+            ret = subprocess.call(['git', 'fetch', remote, branch])
+            if ret:
+                sys.stderr.write('Error: Branch not in %s\n' % remote)
+                sys.exit(1)
+
+            url = remote
+
+            if args['source_line'] is None:
+                git_pipe = subprocess.Popen(['git', 'rev-parse', commit],
+                                            stdout=subprocess.PIPE)
+                commit = git_pipe.communicate()[0].strip()
+
+                args['source_line'] = \
+                    '(cherry picked from commit %s\n %s %s)' % \
+                    (commit, url, branch)
+            if args['tag'] is None:
+                args['tag'] = 'FROMGIT: '
+
+            ret = subprocess.call(['git', 'cherry-pick', commit])
         else:
             sys.stderr.write('Don\'t know what "%s" means.\n' % location)
             sys.exit(1)