blob: 1bdc1f0b4bbbb8934daefbd9a6e27aebdaccddb3 [file] [log] [blame]
Daniel Sandler9e426aa2010-04-01 10:42:33 -04001#
2# Copyright (C) 2010 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
Sarah Owenscecd1d82012-11-01 22:59:27 -070016from __future__ import print_function
Daniel Sandler9e426aa2010-04-01 10:42:33 -040017import sys
18
19from command import Command
20from git_command import GitCommand
Daniel Sandler9e426aa2010-04-01 10:42:33 -040021
22class Rebase(Command):
23 common = True
24 helpSummary = "Rebase local branches on upstream branch"
25 helpUsage = """
26%prog {[<project>...] | -i <project>...}
27"""
28 helpDescription = """
29'%prog' uses git rebase to move local changes in the current topic branch to
30the HEAD of the upstream history, useful when you have made commits in a topic
31branch but need to incorporate new upstream changes "underneath" them.
32"""
33
34 def _Options(self, p):
35 p.add_option('-i', '--interactive',
36 dest="interactive", action="store_true",
37 help="interactive rebase (single project only)")
38
Shawn O. Pearcea22f99a2010-07-15 17:40:41 -070039 p.add_option('-f', '--force-rebase',
40 dest='force_rebase', action='store_true',
41 help='Pass --force-rebase to git rebase')
42 p.add_option('--no-ff',
43 dest='no_ff', action='store_true',
44 help='Pass --no-ff to git rebase')
45 p.add_option('-q', '--quiet',
46 dest='quiet', action='store_true',
47 help='Pass --quiet to git rebase')
48 p.add_option('--autosquash',
49 dest='autosquash', action='store_true',
50 help='Pass --autosquash to git rebase')
51 p.add_option('--whitespace',
52 dest='whitespace', action='store', metavar='WS',
53 help='Pass --whitespace to git rebase')
Joe Hansche5e572342012-03-05 11:41:19 -050054 p.add_option('--auto-stash',
55 dest='auto_stash', action='store_true',
56 help='Stash local modifications before starting')
Shawn O. Pearcea22f99a2010-07-15 17:40:41 -070057
Daniel Sandler9e426aa2010-04-01 10:42:33 -040058 def Execute(self, opt, args):
David Pursehouse8a68ff92012-09-24 12:15:13 +090059 all_projects = self.GetProjects(args)
60 one_project = len(all_projects) == 1
Daniel Sandler9e426aa2010-04-01 10:42:33 -040061
62 if opt.interactive and not one_project:
Sarah Owenscecd1d82012-11-01 22:59:27 -070063 print('error: interactive rebase not supported with multiple projects',
64 file=sys.stderr)
David James8d201162013-10-11 17:03:19 -070065 if len(args) == 1:
66 print('note: project %s is mapped to more than one path' % (args[0],),
67 file=sys.stderr)
Daniel Sandler9e426aa2010-04-01 10:42:33 -040068 return -1
69
David Pursehouse8a68ff92012-09-24 12:15:13 +090070 for project in all_projects:
Daniel Sandler9e426aa2010-04-01 10:42:33 -040071 cb = project.CurrentBranch
72 if not cb:
73 if one_project:
David Pursehouse2f9e7e42013-03-05 17:26:46 +090074 print("error: project %s has a detached HEAD" % project.relpath,
Sarah Owenscecd1d82012-11-01 22:59:27 -070075 file=sys.stderr)
Daniel Sandler9e426aa2010-04-01 10:42:33 -040076 return -1
77 # ignore branches with detatched HEADs
78 continue
79
80 upbranch = project.GetBranch(cb)
81 if not upbranch.LocalMerge:
82 if one_project:
Sarah Owenscecd1d82012-11-01 22:59:27 -070083 print("error: project %s does not track any remote branches"
84 % project.relpath, file=sys.stderr)
Daniel Sandler9e426aa2010-04-01 10:42:33 -040085 return -1
86 # ignore branches without remotes
87 continue
88
Daniel Sandler9e426aa2010-04-01 10:42:33 -040089 args = ["rebase"]
Shawn O. Pearcea22f99a2010-07-15 17:40:41 -070090
91 if opt.whitespace:
92 args.append('--whitespace=%s' % opt.whitespace)
93
94 if opt.quiet:
95 args.append('--quiet')
96
97 if opt.force_rebase:
98 args.append('--force-rebase')
99
100 if opt.no_ff:
101 args.append('--no-ff')
102
103 if opt.autosquash:
104 args.append('--autosquash')
105
Daniel Sandler9e426aa2010-04-01 10:42:33 -0400106 if opt.interactive:
107 args.append("-i")
Daniel Sandler9e426aa2010-04-01 10:42:33 -0400108
Shawn O. Pearcea22f99a2010-07-15 17:40:41 -0700109 args.append(upbranch.LocalMerge)
110
Sarah Owenscecd1d82012-11-01 22:59:27 -0700111 print('# %s: rebasing %s -> %s'
112 % (project.relpath, cb, upbranch.LocalMerge), file=sys.stderr)
Shawn O. Pearcea22f99a2010-07-15 17:40:41 -0700113
Joe Hansche5e572342012-03-05 11:41:19 -0500114 needs_stash = False
115 if opt.auto_stash:
116 stash_args = ["update-index", "--refresh", "-q"]
117
118 if GitCommand(project, stash_args).Wait() != 0:
119 needs_stash = True
120 # Dirty index, requires stash...
121 stash_args = ["stash"]
122
123 if GitCommand(project, stash_args).Wait() != 0:
124 return -1
125
Daniel Sandler9e426aa2010-04-01 10:42:33 -0400126 if GitCommand(project, args).Wait() != 0:
127 return -1
Joe Hansche5e572342012-03-05 11:41:19 -0500128
129 if needs_stash:
130 stash_args.append('pop')
131 stash_args.append('--quiet')
132 if GitCommand(project, stash_args).Wait() != 0:
133 return -1