stg import now extracts Message-ID header
[stgit.git] / stgit / commands / fold.py
blobc7931f4f586640a59170ed01c8542f7db9643d0b
1 import io
2 import os
3 import sys
5 from stgit.argparse import opt
6 from stgit.commands.common import (
7 CmdException,
8 DirectoryHasRepository,
9 apply_patch,
10 check_conflicts,
11 check_head_top_equal,
12 check_local_changes,
13 git_commit,
15 from stgit.out import out
17 __copyright__ = """
18 Copyright (C) 2005, Catalin Marinas <catalin.marinas@gmail.com>
20 This program is free software; you can redistribute it and/or modify
21 it under the terms of the GNU General Public License version 2 as
22 published by the Free Software Foundation.
24 This program is distributed in the hope that it will be useful,
25 but WITHOUT ANY WARRANTY; without even the implied warranty of
26 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 GNU General Public License for more details.
29 You should have received a copy of the GNU General Public License
30 along with this program; if not, see http://www.gnu.org/licenses/.
31 """
33 help = 'Integrate a GNU diff patch into the current patch'
34 kind = 'patch'
35 usage = ['[options] [--] [<file>]']
36 description = """
37 Apply the given GNU diff file (or the standard input) onto the top of
38 the current patch. With the '--threeway' option, the patch is applied
39 onto the bottom of the current patch and a three-way merge is
40 performed with the current top. With the --base option, the patch is
41 applied onto the specified base and a three-way merged is performed
42 with the current top."""
44 args = ['files']
45 options = [
46 opt(
47 '-t',
48 '--threeway',
49 action='store_true',
50 short='Perform a three-way merge with the current patch',
52 opt(
53 '-b',
54 '--base',
55 args=['commit'],
56 short='Use BASE instead of HEAD when applying the patch',
58 opt(
59 '-p',
60 '--strip',
61 type='int',
62 metavar='N',
63 short='Remove N leading slashes from diff paths (default 1)',
65 opt(
66 '-C',
67 dest='context_lines',
68 type='int',
69 metavar='N',
70 short='Ensure N lines of surrounding context for each change',
72 opt(
73 '--reject',
74 action='store_true',
75 short='Leave the rejected hunks in corresponding *.rej files',
79 directory = DirectoryHasRepository()
82 def func(parser, options, args):
83 """Integrate a GNU diff patch into the current patch"""
84 if len(args) > 1:
85 parser.error('incorrect number of arguments')
87 repository = directory.repository
88 stack = repository.get_stack()
90 check_local_changes(repository)
91 check_conflicts(repository.default_iw)
92 check_head_top_equal(stack)
94 if len(args) == 1:
95 filename = args[0]
96 else:
97 filename = None
99 applied = stack.patchorder.applied
100 if not applied:
101 raise CmdException('No patches applied')
103 current = applied[-1]
105 if filename:
106 if os.path.exists(filename):
107 out.start('Folding patch "%s"' % filename)
108 with io.open(filename, 'rb') as f:
109 diff = f.read()
110 else:
111 raise CmdException('No such file: %s' % filename)
112 else:
113 out.start('Folding patch from stdin')
114 diff = sys.stdin.buffer.read()
116 if options.threeway:
117 apply_patch(
118 stack,
119 diff,
120 base=stack.patches[current].data.parent,
121 strip=options.strip,
122 reject=options.reject,
123 context_lines=options.context_lines,
125 elif options.base:
126 apply_patch(
127 stack,
128 diff,
129 base=git_commit(options.base, repository),
130 reject=options.reject,
131 strip=options.strip,
132 context_lines=options.context_lines,
134 else:
135 apply_patch(
136 stack,
137 diff,
138 strip=options.strip,
139 reject=options.reject,
140 context_lines=options.context_lines,
143 out.done()