chiark / gitweb /
7be94e0013d57d7d0ce12d697910d830c3563be2
[stgit] / stgit / commands / refresh.py
1
2 __copyright__ = """
3 Copyright (C) 2005, Catalin Marinas <catalin.marinas@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2 as
7 published by the Free Software Foundation.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 """
18
19 import sys, os
20 from stgit.argparse import opt
21 from stgit.commands.common import *
22 from stgit.utils import *
23 from stgit.out import *
24 from stgit import stack, git
25 from stgit.config import config
26
27 help = 'Generate a new commit for the current patch'
28 kind = 'patch'
29 usage = ['[options] [<files or dirs>]']
30 description = """
31 Include the latest tree changes in the current patch. This command
32 generates a new GIT commit object with the patch details, the previous
33 one no longer being visible. The '--force' option is useful
34 when a commit object was created with a different tool
35 but the changes need to be included in the current patch."""
36
37 options = [
38     opt('-f', '--force', action = 'store_true',
39         short = 'Force the refresh even if HEAD and top differ'),
40     opt('--update', action = 'store_true',
41         short = 'Only update the current patch files'),
42     opt('--index', action = 'store_true',
43         short = 'Refresh from index instead of worktree', long = """
44         Instead of setting the patch top to the current contents of
45         the worktree, set it to the current contents of the index."""),
46     opt('--undo', action = 'store_true',
47         short = 'Revert the commit generated by the last refresh'),
48     opt('-a', '--annotate', metavar = 'NOTE',
49         short = 'Annotate the patch log entry'),
50     opt('-p', '--patch',
51         short = 'Refresh (applied) PATCH instead of the top patch')]
52
53 directory = DirectoryHasRepository(log = True)
54
55 def func(parser, options, args):
56     """Generate a new commit for the current or given patch.
57     """
58     args = git.ls_files(args)
59     directory.cd_to_topdir()
60
61     autoresolved = config.get('stgit.autoresolved')
62     if autoresolved != 'yes':
63         check_conflicts()
64
65     if options.patch:
66         if args or options.update:
67             raise CmdException, \
68                   'Only full refresh is available with the --patch option'
69         patch = options.patch
70         if not crt_series.patch_applied(patch):
71             raise CmdException, 'Patches "%s" not applied' % patch
72     else:
73         patch = crt_series.get_current()
74         if not patch:
75             raise CmdException, 'No patches applied'
76
77     if options.index:
78         if args or options.update:
79             raise CmdException, \
80                   'Only full refresh is available with the --index option'
81         if options.patch:
82             raise CmdException, \
83                   '--patch is not compatible with the --index option'
84
85     if not options.force:
86         check_head_top_equal(crt_series)
87
88     if options.undo:
89         out.start('Undoing the refresh of "%s"' % patch)
90         crt_series.undo_refresh()
91         out.done()
92         return
93
94     if not options.index:
95         files = [path for (stat, path) in git.tree_status(files = args, verbose = True)]
96
97     if options.index or files or not crt_series.head_top_equal():
98         if options.patch:
99             applied = crt_series.get_applied()
100             between = applied[:applied.index(patch):-1]
101             pop_patches(crt_series, between, keep = True)
102         elif options.update:
103             rev1 = git_id(crt_series, 'HEAD^')
104             rev2 = git_id(crt_series, 'HEAD')
105             patch_files = git.barefiles(rev1, rev2).split('\n')
106             files = [f for f in files if f in patch_files]
107             if not files:
108                 out.info('No modified files for updating patch "%s"' % patch)
109                 return
110
111         out.start('Refreshing patch "%s"' % patch)
112
113         if autoresolved == 'yes':
114             resolved_all()
115
116         if options.index:
117             crt_series.refresh_patch(cache_update = False,
118                                      backup = True, notes = options.annotate)
119         else:
120             crt_series.refresh_patch(files = files,
121                                      backup = True, notes = options.annotate)
122
123         if crt_series.empty_patch(patch):
124             out.done('empty patch')
125         else:
126             out.done()
127
128         if options.patch:
129             between.reverse()
130             push_patches(crt_series, between)
131     elif options.annotate:
132         # only annotate the top log entry as there is no need to
133         # refresh the patch and generate a full commit
134         crt_series.log_patch(crt_series.get_patch(patch), None,
135                              notes = options.annotate)
136     else:
137         out.info('Patch "%s" is already up to date' % patch)