1 from stgit
import argparse
, utils
2 from stgit
.argparse
import opt
3 from stgit
.commands
.common
import (
5 DirectoryHasRepository
,
8 from stgit
.config
import config
9 from stgit
.lib
.edit
import auto_edit_patch
, interactive_edit_patch
10 from stgit
.lib
.git
import CommitData
, IndexAndWorktree
11 from stgit
.lib
.transaction
import (
16 from stgit
.out
import out
17 from stgit
.run
import RunException
18 from stgit
.utils
import get_hook
21 Copyright (C) 2005, Catalin Marinas <catalin.marinas@gmail.com>
22 Copyright (C) 2008, Karl Hasselström <kha@treskal.com>
24 This program is free software; you can redistribute it and/or modify
25 it under the terms of the GNU General Public License version 2 as
26 published by the Free Software Foundation.
28 This program is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU General Public License for more details.
33 You should have received a copy of the GNU General Public License
34 along with this program; if not, see http://www.gnu.org/licenses/.
37 help = 'Generate a new commit for the current patch'
39 usage
= ['[options] [--] [<files or dirs>]']
41 Include the latest work tree and index changes in the current patch.
42 This command generates a new git commit object for the patch; the old
43 commit is no longer visible.
45 Refresh will warn if the index is dirty, and require use of either the
46 '--index' or '--force' options to override this check. This is to prevent
47 accidental full refresh when only some changes were staged using git add
50 You may optionally list one or more files or directories relative to
51 the current working directory; if you do, only matching files will be
54 Behind the scenes, stg refresh first creates a new temporary patch
55 with your updates, and then merges that patch into the patch you asked
56 to have refreshed. If you asked to refresh a patch other than the
57 topmost patch, there can be conflicts; in that case, the temporary
58 patch will be left for you to take care of, for example with stg
61 The creation of the temporary patch is recorded in a separate entry in
62 the patch stack log; this means that one undo step will undo the merge
63 between the other patch and the temp patch, and two undo steps will
64 additionally get rid of the temp patch.
66 Additionally, the '--spill' option resets the topmost patch, emptying
67 the patch while leaving the patch's changes intact in the worktree."""
69 args
= ['dirty_files']
75 short
='Only update the current patch files',
81 short
='Refresh from index instead of worktree',
83 Instead of setting the patch top to the current contents of
84 the worktree, set it to the current contents of the index.""",
90 short
='Force refresh even if index is dirty',
92 Instead of warning the user when some work has already been staged
93 (such as with git add interactive mode) force a full refresh.""",
98 args
=['other_applied_patches', 'unapplied_patches'],
99 short
='Refresh (applied) PATCH instead of the top patch',
105 short
='Invoke an editor for the patch description',
111 short
='Show diff when editing patch description',
117 short
='Annotate the patch log entry',
123 short
='Include submodules when refreshing patch contents',
127 action
='store_false',
129 short
='Exclude submodules when refreshing patch contents',
135 short
='Spill patch content to worktree and index, erasing patch content.',
138 options
.extend(argparse
.message_options(save_template
=False))
139 options
.extend(argparse
.hook_options())
140 options
.extend(argparse
.trailer_options())
141 options
.extend(argparse
.author_options())
142 options
.extend(argparse
.diff_opts_option())
144 directory
= DirectoryHasRepository()
147 def get_patch(stack
, given_patch
):
148 """Get the name of the patch we are to refresh."""
150 patch_name
= given_patch
151 if patch_name
not in stack
.patches
:
152 raise CmdException('%s: no such patch' % patch_name
)
155 if not stack
.patchorder
.applied
:
157 'Cannot refresh top patch because no patches are applied'
159 return stack
.patchorder
.applied
[-1]
162 def list_files(stack
, patch_name
, path_limits
, update
, submodules
):
163 """Figure out which files to update."""
164 iw
= stack
.repository
.default_iw
165 paths
= iw
.changed_files(stack
.head
.data
.tree
, path_limits
or [])
167 # --update: Restrict update to the paths that were already part of the patch.
169 commit
= stack
.patches
[patch_name
]
170 for dt
in stack
.repository
.diff_tree_files(
171 commit
.data
.parent
.data
.tree
, commit
.data
.tree
173 _
, _
, _
, _
, _
, oldname
, newname
= dt
174 patch_paths
.add(oldname
)
175 patch_paths
.add(newname
)
178 # Avoid including submodule files by default. This is to ensure that
179 # users in repositories with submodueles do not accidentally include
180 # submodule changes to patches just because they happen to have not
181 # run "git submodule update" prior to running stg refresh. We won't
182 # exclude them if we're explicitly told to include them, or if we're
183 # given explicit paths.
184 if not path_limits
and not submodules
:
185 paths
-= stack
.repository
.submodules(stack
.head
.data
.tree
)
189 def write_tree(stack
, paths
, use_temp_index
):
190 """Possibly update the index, and then write its tree.
192 If any path limiting is in effect, use a temp index.
194 :return: The written tree.
195 :rtype: :class:`Tree<stgit.git.Tree>`
201 iw
= IndexAndWorktree(index
, stack
.repository
.default_worktree
)
202 iw
.update_index(paths
)
203 return index
.write_tree()
206 with stack
.repository
.temp_index() as index
:
208 index
.read_tree(stack
.head
)
211 stack
.repository
.default_iw
.update_index(paths
)
213 return go(stack
.repository
.default_index
)
216 def make_temp_patch(stack
, patch_name
, tree
):
217 """Commit tree to temp patch, in a complete transaction."""
218 commit
= stack
.repository
.commit(
221 parents
=[stack
.head
],
222 message
='Refresh of %s' % patch_name
,
225 temp_name
= stack
.patches
.make_name('refresh-temp')
226 trans
= StackTransaction(stack
, 'refresh (create temporary patch)')
227 trans
.patches
[temp_name
] = commit
228 trans
.applied
.append(temp_name
)
230 trans
.run(stack
.repository
.default_iw
, print_current_patch
=False),
235 def absorb_applied(trans
, iw
, patch_name
, temp_name
, edit_fun
):
236 """Absorb temp patch into the given patch, which must be applied.
238 If the absorption succeeds, call ``edit_fun`` on the resulting
239 :class:`stgit.lib.git.CommitData` before committing it, then commit the return
242 :returns: True if the temp patch is successfully absorbed or False if there remain
243 conflicts for the user to resolve
246 temp_absorbed
= False
248 # Pop any patch on top of the patch we're refreshing.
249 to_pop
= trans
.applied
[trans
.applied
.index(patch_name
) + 1 :]
251 popped_extra
= trans
.pop_patches(lambda pn
: pn
in to_pop
)
252 assert not popped_extra
# no other patches were popped
253 trans
.push_patch(temp_name
, iw
)
254 top_name
= to_pop
.pop()
255 assert top_name
== temp_name
257 # Absorb the temp patch.
258 temp_cd
= trans
.patches
[temp_name
].data
259 assert trans
.patches
[patch_name
] == temp_cd
.parent
260 cd
, new_patch_name
= edit_fun(
261 trans
.patches
[patch_name
].data
.set_tree(temp_cd
.tree
)
263 trans
.patches
[patch_name
] = trans
.stack
.repository
.commit(cd
)
264 if new_patch_name
and patch_name
!= new_patch_name
:
265 trans
.rename_patch(patch_name
, new_patch_name
)
267 popped_extra
= trans
.delete_patches(lambda pn
: pn
== temp_name
, quiet
=True)
268 assert not popped_extra
# the temp patch was topmost
271 # Push back any patch we were forced to pop earlier.
273 trans
.push_patch(pn
, iw
)
274 except TransactionHalted
:
279 def absorb_unapplied(trans
, iw
, patch_name
, temp_name
, edit_fun
):
280 """Absorb the temp patch into the given patch, which must be unapplied.
282 If the absorption succeeds, call ``edit_fun`` on the resulting
283 :class:`stgit.lib.git.CommitData` before committing it, then commit the return
287 :returns: True if the temp patch is absorbed successfully or False
288 if user resolvable conflicts remain
291 # Pop the temp patch.
292 popped_extra
= trans
.pop_patches(lambda pn
: pn
== temp_name
)
293 assert not popped_extra
# the temp patch was topmost
295 # Try to create the new tree of the refreshed patch. (This is the
296 # same operation as pushing the temp patch onto the patch we're
297 # trying to refresh -- but we don't have a worktree to spill
298 # conflicts to, so if the simple merge doesn't succeed, we have to
300 patch_cd
= trans
.patches
[patch_name
].data
301 temp_cd
= trans
.patches
[temp_name
].data
302 new_tree
= trans
.stack
.repository
.simple_merge(
303 base
=temp_cd
.parent
.data
.tree
,
308 # It worked. Refresh the patch with the new tree, and delete
310 cd
, new_patch_name
= edit_fun(patch_cd
.set_tree(new_tree
))
311 trans
.patches
[patch_name
] = trans
.stack
.repository
.commit(cd
)
312 if new_patch_name
and patch_name
!= new_patch_name
:
313 trans
.rename_patch(patch_name
, new_patch_name
)
314 popped_extra
= trans
.delete_patches(lambda pn
: pn
== temp_name
, quiet
=True)
315 assert not popped_extra
# the temp patch was not applied
318 # Nope, we couldn't create the new tree, so we'll just have to
319 # leave the temp patch for the user.
323 def absorb(stack
, patch_name
, temp_name
, edit_fun
, annotate
=None):
324 """Absorb the temp patch into the target patch."""
327 log_msg
+= '\n\n' + annotate
329 trans
= StackTransaction(stack
, log_msg
)
330 iw
= stack
.repository
.default_iw
331 if patch_name
in trans
.applied
:
332 absorb_func
= absorb_applied
334 absorb_func
= absorb_unapplied
336 if absorb_func(trans
, iw
, patch_name
, temp_name
, edit_fun
):
345 'The new changes did not apply cleanly to %s.' % patch_name
,
346 'They were saved in %s.' % temp_name
,
354 def __refresh_spill(annotate
):
355 stack
= directory
.repository
.current_stack
357 # Fetch the topmost patch.
358 patchname
= get_patch(stack
, None)
360 cd
= stack
.patches
[patchname
].data
362 # Set the tree of the patch to the parent.
363 cd
= cd
.set_tree(cd
.parent
.data
.tree
)
365 log_msg
= 'refresh (spill)'
367 log_msg
+= '\n\n' + annotate
369 trans
= StackTransaction(stack
, log_msg
, allow_conflicts
=True)
370 trans
.patches
[patchname
] = stack
.repository
.commit(cd
)
372 # Either a complete success, or a conflict during push. But in
373 # either case, we've successfully effected the edits the user
376 except TransactionException
:
377 # Transaction aborted -- we couldn't check out files due to
378 # dirty index/worktree. The edits were not carried out.
379 out
.error('Unable to spill the topmost patch')
380 return utils
.STGIT_COMMAND_ERROR
391 use_temp_index
=False,
392 refresh_from_index
=False,
393 only_update_patchfiles
=False,
394 include_submodules
=False,
400 stack
= directory
.repository
.current_stack
402 patch_name
= get_patch(stack
, target_patch
)
404 if refresh_from_index
:
411 only_update_patchfiles
,
415 # Make sure there are no conflicts in the files we want to
417 if stack
.repository
.default_index
.conflicts() & paths
:
418 raise CmdException('Cannot refresh -- resolve conflicts first')
420 # Make sure the index is clean before performing a full refresh
421 if not refresh_from_index
and not force
:
423 stack
.repository
.default_index
.is_clean(stack
.head
)
424 or stack
.repository
.default_iw
.worktree_clean()
427 'The index is dirty. Did you mean --index? '
428 'To force a full refresh use --force.'
431 # Update index and write tree
432 tree
= write_tree(stack
, paths
, use_temp_index
=use_temp_index
)
434 # Run pre-commit hook, if fails, abort refresh
436 pre_commit_hook
= get_hook(
439 extra_env
={} if invoke_editor
else {'GIT_EDITOR': ':'},
446 'pre-commit hook failed, review the changes using `stg diff`, '
447 'run `stg add` to add them to index and run `stg refresh` again'
450 # Update index and rewrite tree if hook updated files in index
451 if not stack
.repository
.default_index
.is_clean(tree
):
452 tree
= write_tree(stack
, paths
, use_temp_index
=use_temp_index
)
454 # Commit tree to temp patch, and absorb it into the target patch.
455 retval
, temp_name
= make_temp_patch(stack
, patch_name
, tree
)
457 if retval
!= utils
.STGIT_SUCCESS
:
461 orig_msg
= cd
.message
463 if message
is not None:
464 new_msg
= message
.encode(config
.get('i18n.commitencoding'))
465 cd
= auto_edit_patch(
472 new_patch_name
= None
474 cd
, new_patch_name
, failed_diff
= interactive_edit_patch(
475 stack
.repository
, cd
, patch_name
, edit_diff
, diff_flags
477 assert not failed_diff
478 if not no_verify
and (invoke_editor
or cd
.message
!= orig_msg
):
479 cd
= run_commit_msg_hook(stack
.repository
, cd
, invoke_editor
)
480 # Refresh the committer information
481 return cd
.set_committer(None), new_patch_name
483 return absorb(stack
, patch_name
, temp_name
, edit_fun
, annotate
=annotate
)
486 def func(parser
, options
, args
):
487 """Generate a new commit for the current or given patch."""
491 # TODO: would be nice if path limiting could be used with spill.
492 raise CmdException('Cannot use path limiting with --spill')
493 for opt_name
, opt_value
in [
494 ('--index', options
.index
),
495 ('--edit', options
.edit
),
496 ('--update', options
.update
),
497 ('--patch', options
.patch
),
498 ('--force', options
.force
),
499 ('--no-verify', options
.no_verify
),
500 ('--sign', options
.trailers
),
501 ('--ack', options
.trailers
),
502 ('--review', options
.trailers
),
505 raise CmdException('Cannot combine --spill with %s' % opt_name
)
506 return __refresh_spill(annotate
=options
.annotate
)
508 # Catch illegal argument combinations.
509 is_path_limiting
= bool(args
or options
.update
)
510 if options
.index
and is_path_limiting
:
511 raise CmdException('Only full refresh is available with the --index option')
513 if options
.index
and options
.force
:
515 'You cannot --force a full refresh when using --index mode'
518 if options
.update
and options
.submodules
:
520 '--submodules is meaningless when only updating modified files'
523 if options
.index
and options
.submodules
:
525 '--submodules is meaningless when keeping the current index'
528 # If submodules was not specified on the command line, infer a default
529 # from configuration.
530 if options
.submodules
is None:
531 options
.submodules
= config
.getbool('stgit.refreshsubmodules')
536 target_patch
=options
.patch
,
537 message
=options
.message
,
538 author
=options
.author
,
539 trailers
=options
.trailers
,
540 annotate
=options
.annotate
,
541 use_temp_index
=is_path_limiting
,
542 refresh_from_index
=options
.index
,
543 only_update_patchfiles
=options
.update
,
544 include_submodules
=options
.submodules
,
545 no_verify
=options
.no_verify
,
546 invoke_editor
=options
.edit
,
547 edit_diff
=options
.diff
,
548 diff_flags
=options
.diff_flags
,