/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/git/commands.py

  • Committer: Jelmer Vernooij
  • Date: 2020-02-07 02:14:30 UTC
  • mto: This revision was merged to the branch mainline in revision 7492.
  • Revision ID: jelmer@jelmer.uk-20200207021430-m49iq3x4x8xlib6x
Drop python2 support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2006-2009 Canonical Ltd
 
2
# Copyright (C) 2012-2018 Jelmer Vernooij <jelmer@jelmer.uk>
2
3
 
3
4
# Authors: Robert Collins <robert.collins@canonical.com>
4
5
#          Jelmer Vernooij <jelmer@samba.org>
16
17
#
17
18
# You should have received a copy of the GNU General Public License
18
19
# along with this program; if not, write to the Free Software
19
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
 
 
 
20
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
21
 
22
22
"""Git-specific subcommands for Bazaar."""
23
23
 
24
 
from bzrlib.commands import Command
25
 
from bzrlib.option import Option
26
 
 
27
 
class cmd_git_serve(Command):
28
 
    """Provide access to a Bazaar branch using the git protocol.
29
 
 
30
 
    This command is experimental and doesn't do much yet.
31
 
    """
32
 
    takes_options = [
33
 
        Option('directory',
34
 
               help='serve contents of directory',
35
 
               type=unicode)
36
 
    ]
37
 
 
38
 
    def run(self, directory=None):
39
 
        lazy_check_versions()
40
 
        from dulwich.server import TCPGitServer
41
 
        from bzrlib.plugins.git.server import BzrBackend
42
 
        from bzrlib.trace import warning
43
 
        import os
44
 
 
45
 
        warning("server support in bzr-git is experimental.")
46
 
 
47
 
        if directory is None:
48
 
            directory = os.getcwd()
49
 
 
50
 
        backend = BzrBackend(directory)
51
 
 
52
 
        server = TCPGitServer(backend, 'localhost')
53
 
        server.serve_forever()
 
24
from __future__ import absolute_import
 
25
 
 
26
import breezy.bzr  # noqa: F401
 
27
from breezy import controldir
 
28
from ..commands import (
 
29
    Command,
 
30
    display_command,
 
31
    )
 
32
from ..option import (
 
33
    Option,
 
34
    RegistryOption,
 
35
    )
 
36
 
54
37
 
55
38
class cmd_git_import(Command):
56
39
    """Import all branches from a git repository.
57
40
 
58
41
    """
59
42
 
60
 
    takes_args = ["src_location", "dest_location"]
61
 
 
62
 
    def run(self, src_location, dest_location):
63
 
        from bzrlib.bzrdir import BzrDir, format_registry
64
 
        from bzrlib.errors import NoRepositoryPresent, NotBranchError
65
 
        from bzrlib.repository import Repository
 
43
    takes_args = ["src_location", "dest_location?"]
 
44
 
 
45
    takes_options = [
 
46
        Option('colocated', help='Create colocated branches.'),
 
47
        RegistryOption('dest-format',
 
48
                       help='Specify a format for this branch. '
 
49
                       'See "help formats" for a full list.',
 
50
                       lazy_registry=('breezy.controldir', 'format_registry'),
 
51
                       converter=lambda name: controldir.format_registry.make_controldir(
 
52
                            name),
 
53
                       value_switches=True,
 
54
                       title="Branch format",
 
55
                       ),
 
56
        ]
 
57
 
 
58
    def _get_colocated_branch(self, target_controldir, name):
 
59
        from ..errors import NotBranchError
 
60
        try:
 
61
            return target_controldir.open_branch(name=name)
 
62
        except NotBranchError:
 
63
            return target_controldir.create_branch(name=name)
 
64
 
 
65
    def _get_nested_branch(self, dest_transport, dest_format, name):
 
66
        from ..controldir import ControlDir
 
67
        from ..errors import NotBranchError
 
68
        head_transport = dest_transport.clone(name)
 
69
        try:
 
70
            head_controldir = ControlDir.open_from_transport(head_transport)
 
71
        except NotBranchError:
 
72
            head_controldir = dest_format.initialize_on_transport_ex(
 
73
                head_transport, create_prefix=True)[1]
 
74
        try:
 
75
            return head_controldir.open_branch()
 
76
        except NotBranchError:
 
77
            return head_controldir.create_branch()
 
78
 
 
79
    def run(self, src_location, dest_location=None, colocated=False, dest_format=None):
 
80
        import os
 
81
        from .. import (
 
82
            controldir,
 
83
            trace,
 
84
            ui,
 
85
            urlutils,
 
86
            )
 
87
        from ..controldir import (
 
88
            ControlDir,
 
89
            )
 
90
        from ..errors import (
 
91
            BzrError,
 
92
            BzrCommandError,
 
93
            NoRepositoryPresent,
 
94
            NotBranchError,
 
95
            )
 
96
        from ..i18n import gettext
 
97
        from ..repository import (
 
98
            InterRepository,
 
99
            Repository,
 
100
            )
 
101
        from ..transport import get_transport
 
102
        from .branch import (
 
103
            LocalGitBranch,
 
104
            )
 
105
        from .refs import (
 
106
            ref_to_branch_name,
 
107
            )
 
108
        from .repository import GitRepository
 
109
 
 
110
        if dest_format is None:
 
111
            dest_format = controldir.format_registry.make_controldir('default')
 
112
 
 
113
        if dest_location is None:
 
114
            dest_location = os.path.basename(src_location.rstrip("/\\"))
 
115
 
 
116
        dest_transport = get_transport(dest_location)
 
117
 
66
118
        source_repo = Repository.open(src_location)
67
 
        format = format_registry.make_bzrdir('rich-root-pack')
 
119
        if not isinstance(source_repo, GitRepository):
 
120
            raise BzrCommandError(
 
121
                gettext("%r is not a git repository") % src_location)
68
122
        try:
69
 
            target_bzrdir = BzrDir.open(dest_location)
 
123
            target_controldir = ControlDir.open_from_transport(dest_transport)
70
124
        except NotBranchError:
71
 
            target_bzrdir = BzrDir.create(dest_location, format=format)
 
125
            target_controldir = dest_format.initialize_on_transport_ex(
 
126
                dest_transport, shared_repo=True)[1]
72
127
        try:
73
 
            target_repo = target_bzrdir.open_repository()
 
128
            target_repo = target_controldir.find_repository()
74
129
        except NoRepositoryPresent:
75
 
            target_repo = target_bzrdir.create_repository(shared=True)
76
 
 
77
 
        target_repo.fetch(source_repo)
78
 
        for name, ref in source_repo._git.heads().iteritems():
79
 
            head_loc = os.path.join(dest_location, name)
80
 
            try:
81
 
                head_bzrdir = BzrDir.open(head_loc)
82
 
            except NotBranchError:
83
 
                head_bzrdir = BzrDir.create(head_loc, format=format)
84
 
            try:
85
 
                head_branch = head_bzrdir.open_branch()
86
 
            except NotBranchError:
87
 
                head_branch = head_bzrdir.create_branch()
88
 
            head_branch.generate_revision_history(source_repo.get_mapping().revision_id_foreign_to_bzr(ref))
89
 
 
 
130
            target_repo = target_controldir.create_repository(shared=True)
 
131
 
 
132
        if not target_repo.supports_rich_root():
 
133
            raise BzrCommandError(
 
134
                gettext("Target repository doesn't support rich roots"))
 
135
 
 
136
        interrepo = InterRepository.get(source_repo, target_repo)
 
137
        mapping = source_repo.get_mapping()
 
138
        result = interrepo.fetch()
 
139
        with ui.ui_factory.nested_progress_bar() as pb:
 
140
            for i, (name, sha) in enumerate(result.refs.items()):
 
141
                try:
 
142
                    branch_name = ref_to_branch_name(name)
 
143
                except ValueError:
 
144
                    # Not a branch, ignore
 
145
                    continue
 
146
                pb.update(gettext("creating branches"), i, len(result.refs))
 
147
                if (getattr(target_controldir._format, "colocated_branches",
 
148
                            False) and colocated):
 
149
                    if name == "HEAD":
 
150
                        branch_name = None
 
151
                    head_branch = self._get_colocated_branch(
 
152
                        target_controldir, branch_name)
 
153
                else:
 
154
                    head_branch = self._get_nested_branch(
 
155
                        dest_transport, dest_format, branch_name)
 
156
                revid = mapping.revision_id_foreign_to_bzr(sha)
 
157
                source_branch = LocalGitBranch(
 
158
                    source_repo.controldir, source_repo, sha)
 
159
                if head_branch.last_revision() != revid:
 
160
                    head_branch.generate_revision_history(revid)
 
161
                source_branch.tags.merge_to(head_branch.tags)
 
162
                if not head_branch.get_parent():
 
163
                    url = urlutils.join_segment_parameters(
 
164
                        source_branch.base,
 
165
                        {"branch": urlutils.escape(branch_name)})
 
166
                    head_branch.set_parent(url)
 
167
        trace.note(gettext(
 
168
            "Use 'bzr checkout' to create a working tree in "
 
169
            "the newly created branches."))
 
170
 
 
171
 
 
172
class cmd_git_object(Command):
 
173
    """List or display Git objects by SHA.
 
174
 
 
175
    Cat a particular object's Git representation if a SHA is specified.
 
176
    List all available SHAs otherwise.
 
177
    """
 
178
 
 
179
    hidden = True
 
180
 
 
181
    aliases = ["git-objects", "git-cat"]
 
182
    takes_args = ["sha1?"]
 
183
    takes_options = [Option('directory',
 
184
                            short_name='d',
 
185
                            help='Location of repository.', type=str),
 
186
                     Option('pretty', help='Pretty-print objects.')]
 
187
    encoding_type = 'exact'
 
188
 
 
189
    @display_command
 
190
    def run(self, sha1=None, directory=".", pretty=False):
 
191
        from ..errors import (
 
192
            BzrCommandError,
 
193
            )
 
194
        from ..controldir import (
 
195
            ControlDir,
 
196
            )
 
197
        from .object_store import (
 
198
            get_object_store,
 
199
            )
 
200
        from ..i18n import gettext
 
201
        controldir, _ = ControlDir.open_containing(directory)
 
202
        repo = controldir.find_repository()
 
203
        object_store = get_object_store(repo)
 
204
        with object_store.lock_read():
 
205
            if sha1 is not None:
 
206
                try:
 
207
                    obj = object_store[sha1.encode('ascii')]
 
208
                except KeyError:
 
209
                    raise BzrCommandError(
 
210
                        gettext("Object not found: %s") % sha1)
 
211
                if pretty:
 
212
                    text = obj.as_pretty_string()
 
213
                else:
 
214
                    text = obj.as_raw_string()
 
215
                self.outf.write(text)
 
216
            else:
 
217
                for sha1 in object_store:
 
218
                    self.outf.write("%s\n" % sha1.decode('ascii'))
 
219
 
 
220
 
 
221
class cmd_git_refs(Command):
 
222
    """Output all of the virtual refs for a repository.
 
223
 
 
224
    """
 
225
 
 
226
    hidden = True
 
227
 
 
228
    takes_args = ["location?"]
 
229
 
 
230
    @display_command
 
231
    def run(self, location="."):
 
232
        from ..controldir import (
 
233
            ControlDir,
 
234
            )
 
235
        from .refs import (
 
236
            get_refs_container,
 
237
            )
 
238
        from .object_store import (
 
239
            get_object_store,
 
240
            )
 
241
        controldir, _ = ControlDir.open_containing(location)
 
242
        repo = controldir.find_repository()
 
243
        object_store = get_object_store(repo)
 
244
        with object_store.lock_read():
 
245
            refs = get_refs_container(controldir, object_store)
 
246
            for k, v in sorted(refs.as_dict().items()):
 
247
                self.outf.write("%s -> %s\n" %
 
248
                                (k.decode('utf-8'), v.decode('utf-8')))
 
249
 
 
250
 
 
251
class cmd_git_apply(Command):
 
252
    """Apply a series of git-am style patches.
 
253
 
 
254
    This command will in the future probably be integrated into "bzr pull".
 
255
    """
 
256
 
 
257
    takes_options = [
 
258
        Option('signoff', short_name='s', help='Add a Signed-off-by line.'),
 
259
        Option('force',
 
260
               help='Apply patches even if tree has uncommitted changes.')
 
261
        ]
 
262
    takes_args = ["patches*"]
 
263
 
 
264
    def _apply_patch(self, wt, f, signoff):
 
265
        """Apply a patch.
 
266
 
 
267
        :param wt: A Bazaar working tree object.
 
268
        :param f: Patch file to read.
 
269
        :param signoff: Add Signed-Off-By flag.
 
270
        """
 
271
        from dulwich.patch import git_am_patch_split
 
272
        from breezy.patch import patch_tree
 
273
        (c, diff, version) = git_am_patch_split(f)
 
274
        # FIXME: Cope with git-specific bits in patch
 
275
        # FIXME: Add new files to working tree
 
276
        patch_tree(wt, [diff], strip=1, out=self.outf)
 
277
        message = c.message.decode('utf-8')
 
278
        if signoff:
 
279
            signed_off_by = wt.branch.get_config().username()
 
280
            message += "Signed-off-by: %s\n" % (signed_off_by, )
 
281
        wt.commit(authors=[c.author.decode('utf-8')], message=message)
 
282
 
 
283
    def run(self, patches_list=None, signoff=False, force=False):
 
284
        from ..errors import UncommittedChanges
 
285
        from ..workingtree import WorkingTree
 
286
        if patches_list is None:
 
287
            patches_list = []
 
288
 
 
289
        tree, _ = WorkingTree.open_containing(".")
 
290
        if tree.basis_tree().changes_from(tree).has_changed() and not force:
 
291
            raise UncommittedChanges(tree)
 
292
        with tree.lock_write():
 
293
            for patch in patches_list:
 
294
                with open(patch, 'r') as f:
 
295
                    self._apply_patch(tree, f, signoff=signoff)
 
296
 
 
297
 
 
298
class cmd_git_push_pristine_tar_deltas(Command):
 
299
    """Push pristine tar deltas to a git repository."""
 
300
 
 
301
    takes_options = [Option('directory',
 
302
                            short_name='d',
 
303
                            help='Location of repository.', type=str)]
 
304
    takes_args = ['target', 'package']
 
305
 
 
306
    def run(self, target, package, directory='.'):
 
307
        from ..branch import Branch
 
308
        from ..errors import (
 
309
            BzrCommandError,
 
310
            NoSuchRevision,
 
311
            )
 
312
        from ..trace import warning
 
313
        from ..repository import Repository
 
314
        from .object_store import get_object_store
 
315
        from .pristine_tar import (
 
316
            revision_pristine_tar_data,
 
317
            store_git_pristine_tar_data,
 
318
            )
 
319
        source = Branch.open_containing(directory)[0]
 
320
        target_bzr = Repository.open(target)
 
321
        target = getattr(target_bzr, '_git', None)
 
322
        if target is None:
 
323
            raise BzrCommandError("Target not a git repository")
 
324
        git_store = get_object_store(source.repository)
 
325
        with git_store.lock_read():
 
326
            tag_dict = source.tags.get_tag_dict()
 
327
            for name, revid in tag_dict.iteritems():
 
328
                try:
 
329
                    rev = source.repository.get_revision(revid)
 
330
                except NoSuchRevision:
 
331
                    continue
 
332
                try:
 
333
                    delta, kind = revision_pristine_tar_data(rev)
 
334
                except KeyError:
 
335
                    continue
 
336
                gitid = git_store._lookup_revision_sha1(revid)
 
337
                if (not (name.startswith('upstream/') or
 
338
                         name.startswith('upstream-'))):
 
339
                    warning(
 
340
                        "Unexpected pristine tar revision tagged %s. "
 
341
                        "Ignoring.", name)
 
342
                    continue
 
343
                upstream_version = name[len("upstream/"):]
 
344
                filename = '%s_%s.orig.tar.%s' % (
 
345
                    package, upstream_version, kind)
 
346
                if gitid not in target:
 
347
                    warning(
 
348
                        "base git id %s for %s missing in target repository",
 
349
                        gitid, filename)
 
350
                store_git_pristine_tar_data(target, filename.encode('utf-8'),
 
351
                                            delta, gitid)