Documentation: Rename link macros
[stgit] / stgit / commands / sink.py
1
2 __copyright__ = """
3 Copyright (C) 2007, Yann Dirson <ydirson@altern.org>
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 import argparse, stack, git
24
25 help = 'Send patches deeper down the stack'
26 kind = 'stack'
27 usage = ['[-t <target patch>] [-n] [<patches>]']
28 description = """
29 This is the opposite operation of linkstg:float[]: move the specified
30 patches down the stack. It is for example useful to group stable
31 patches near the bottom of the stack, where they are less likely to be
32 impacted by the push of another patch, and from where they can be more
33 easily committed or pushed.
34
35 If no patch is specified on command-line, the current patch gets sunk.
36 By default patches are sunk to the bottom of the stack, but the '--to'
37 option allows to place them under any applied patch.
38
39 Sinking internally involves popping all patches (or all patches
40 including <target patch>), then pushing the patches to sink, and then
41 (unless '--nopush' is also given) pushing back into place the
42 formerly-applied patches."""
43
44 args = [argparse.patch_range(argparse.applied_patches,
45 argparse.unapplied_patches)]
46 options = [
47 opt('-n', '--nopush', action = 'store_true',
48 short = 'Do not push the patches back after sinking', long = """
49 Do not push back on the stack the formerly-applied patches.
50 Only the patches to sink are pushed."""),
51 opt('-t', '--to', metavar = 'TARGET', args = [argparse.applied_patches],
52 short = 'Sink patches below the TARGET patch', long = """
53 Specify a target patch to place the patches below, instead of
54 sinking them to the bottom of the stack.""")]
55
56 directory = DirectoryGotoToplevel(log = True)
57
58 def func(parser, options, args):
59 """Sink patches down the stack.
60 """
61
62 check_local_changes()
63 check_conflicts()
64 check_head_top_equal(crt_series)
65
66 oldapplied = crt_series.get_applied()
67 unapplied = crt_series.get_unapplied()
68 all = oldapplied + unapplied
69
70 if options.to and not options.to in oldapplied:
71 raise CmdException('Cannot sink below %s, since it is not applied'
72 % options.to)
73
74 if len(args) > 0:
75 patches = parse_patches(args, all)
76 else:
77 current = crt_series.get_current()
78 if not current:
79 raise CmdException('No patch applied')
80 patches = [current]
81
82 before_patches = after_patches = []
83
84 # pop necessary patches
85 if oldapplied:
86 if options.to:
87 pop_idx = oldapplied.index(options.to)
88 else:
89 pop_idx = 0
90 after_patches = [p for p in oldapplied[pop_idx:] if p not in patches]
91
92 # find the deepest patch to pop
93 sink_applied = [p for p in oldapplied if p in patches]
94 if sink_applied:
95 sinked_idx = oldapplied.index(sink_applied[0])
96 if sinked_idx < pop_idx:
97 # this is the case where sink brings patches forward
98 before_patches = [p for p in oldapplied[sinked_idx:pop_idx]
99 if p not in patches]
100 pop_idx = sinked_idx
101
102 crt_series.pop_patch(oldapplied[pop_idx])
103
104 push_patches(crt_series, before_patches)
105 push_patches(crt_series, patches)
106 if not options.nopush:
107 push_patches(crt_series, after_patches)