/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 dir.py

  • Committer: Jelmer Vernooij
  • Date: 2018-03-04 20:28:19 UTC
  • mfrom: (0.200.1807 work)
  • mto: (0.200.1808 work)
  • mto: This revision was merged to the branch mainline in revision 6960.
  • Revision ID: jelmer@jelmer.uk-20180304202819-0dg57zuugpddt0ie
Merge trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
    urlutils,
31
31
    )
32
32
from ...controldir import RepositoryAcquisitionPolicy
33
 
from ...transport import do_catching_redirections
 
33
from ...transport import (
 
34
    do_catching_redirections,
 
35
    get_transport_from_path,
 
36
    )
34
37
 
35
38
from ...controldir import (
36
39
    ControlDir,
39
42
    RepositoryAcquisitionPolicy,
40
43
    )
41
44
 
 
45
from .transportgit import (
 
46
    OBJECTDIR,
 
47
    TransportObjectStore,
 
48
    )
 
49
 
42
50
 
43
51
class GitDirConfig(object):
44
52
 
108
116
    def checkout_metadir(self, stacked=False):
109
117
        return format_registry.make_controldir("git")
110
118
 
111
 
    def _get_default_ref(self):
112
 
        return "HEAD"
113
 
 
114
119
    def _get_selected_ref(self, branch, ref=None):
115
120
        if ref is not None and branch is not None:
116
121
            raise bzr_errors.BzrError("can't specify both ref and branch")
117
122
        if ref is not None:
118
123
            return ref
 
124
        if branch is not None:
 
125
            from .refs import branch_name_to_ref
 
126
            return branch_name_to_ref(branch)
119
127
        segment_parameters = getattr(
120
128
            self.user_transport, "get_segment_parameters", lambda: {})()
121
129
        ref = segment_parameters.get("ref")
123
131
            return urlutils.unescape(ref)
124
132
        if branch is None and getattr(self, "_get_selected_branch", False):
125
133
            branch = self._get_selected_branch()
126
 
        if branch is not None:
127
 
            from .refs import branch_name_to_ref
128
 
            return branch_name_to_ref(branch)
129
 
        return self._get_default_ref()
 
134
            if branch is not None:
 
135
                from .refs import branch_name_to_ref
 
136
                return branch_name_to_ref(branch)
 
137
        return b"HEAD"
130
138
 
131
139
    def get_config(self):
132
140
        return GitDirConfig()
145
153
        target_transport.ensure_base()
146
154
        cloning_format = self.cloning_metadir()
147
155
        # Create/update the result branch
148
 
        result = cloning_format.initialize_on_transport(target_transport)
 
156
        try:
 
157
            result = ControlDir.open_from_transport(target_transport)
 
158
        except bzr_errors.NotBranchError:
 
159
            result = cloning_format.initialize_on_transport(target_transport)
149
160
        source_branch = self.open_branch()
150
161
        source_repository = self.find_repository()
151
162
        try:
216
227
            target_git_repo.refs[name] = val
217
228
        return self.__class__(transport, target_git_repo, format)
218
229
 
 
230
    def _find_commondir(self):
 
231
        try:
 
232
            commondir = self.control_transport.get_bytes('commondir')
 
233
        except bzr_errors.NoSuchFile:
 
234
            return self
 
235
        else:
 
236
            commondir = commondir.rstrip('/.git/')
 
237
            return ControlDir.open_from_transport(get_transport_from_path(commondir))
 
238
 
219
239
    def find_repository(self):
220
240
        """Find the repository that should be used.
221
241
 
223
243
        new branches as well as to hook existing branches up to their
224
244
        repository.
225
245
        """
226
 
        return self._gitrepository_class(self)
 
246
        return self._gitrepository_class(self._find_commondir())
227
247
 
228
248
    def get_refs_container(self):
229
249
        """Retrieve the refs container.
278
298
        from .transportgit import TransportRepo
279
299
        gitrepo = TransportRepo(transport, self.bare,
280
300
                refs_text=getattr(self, "_refs_text", None))
 
301
        if not gitrepo._controltransport.has('HEAD'):
 
302
            raise bzr_errors.NotBranchError(path=transport.base)
281
303
        return LocalGitDir(transport, gitrepo, self)
282
304
 
283
305
    def get_format_description(self):
286
308
    def initialize_on_transport(self, transport):
287
309
        from .transportgit import TransportRepo
288
310
        repo = TransportRepo.init(transport, bare=self.bare)
289
 
        del repo.refs["HEAD"]
290
311
        return self.open(transport)
291
312
 
292
313
    def initialize_on_transport_ex(self, transport, use_existing_dir=False,
376
397
 
377
398
    def _get_symref(self, ref):
378
399
        from dulwich.repo import SYMREF
379
 
        refcontents = self._git.refs.read_ref(ref)
380
 
        if refcontents is None: # no such ref
 
400
        ref_chain, unused_sha = self._git.refs.follow(ref)
 
401
        if len(ref_chain) == 1:
381
402
            return None
382
 
        if refcontents.startswith(SYMREF):
383
 
            return refcontents[len(SYMREF):].rstrip("\n")
384
 
        return None
 
403
        return ref_chain[1]
385
404
 
386
405
    def set_branch_reference(self, target_branch, name=None):
387
 
        if self.control_transport.base != target_branch.controldir.control_transport.base:
388
 
            raise bzr_errors.IncompatibleFormat(target_branch._format, self._format)
389
406
        ref = self._get_selected_ref(name)
390
 
        self._git.refs.set_symbolic_ref(ref, target_branch.ref)
 
407
        if self.control_transport.base == target_branch.controldir.control_transport.base:
 
408
            self._git.refs.set_symbolic_ref(ref, target_branch.ref)
 
409
        else:
 
410
            try:
 
411
                target_path = target_branch.controldir.control_transport.local_abspath('.')
 
412
            except bzr_errors.NotLocalUrl:
 
413
                raise bzr_errors.IncompatibleFormat(target_branch._format, self._format)
 
414
            # TODO(jelmer): Do some consistency checking across branches..
 
415
            self.control_transport.put_bytes('commondir', target_path.encode('utf-8'))
 
416
            # TODO(jelmer): Urgh, avoid mucking about with internals.
 
417
            self._git._commontransport = target_branch.repository._git._commontransport.clone()
 
418
            self._git.object_store = TransportObjectStore(self._git._commontransport.clone(OBJECTDIR))
 
419
            self._git.refs.transport = self._git._commontransport
 
420
            target_ref_chain, unused_sha = target_branch.controldir._git.refs.follow(target_branch.ref)
 
421
            for target_ref in target_ref_chain:
 
422
                if target_ref == b'HEAD':
 
423
                    continue
 
424
                break
 
425
            else:
 
426
                # Can't create a reference to something that is not a in a repository.
 
427
                raise bzr_errors.IncompatibleFormat(self.set_branch_reference, self)
 
428
            self._git.refs.set_symbolic_ref(ref, target_ref)
391
429
 
392
430
    def get_branch_reference(self, name=None):
393
431
        ref = self._get_selected_ref(name)
394
432
        target_ref = self._get_symref(ref)
395
433
        if target_ref is not None:
396
 
            return urlutils.join_segment_parameters(
397
 
                self.user_url.rstrip("/"), {"ref": urllib.quote(target_ref, '')})
 
434
            from .refs import ref_to_branch_name
 
435
            try:
 
436
                branch_name = ref_to_branch_name(target_ref)
 
437
            except ValueError:
 
438
                params = {'ref': urllib.quote(target_ref, '')}
 
439
            else:
 
440
                if branch_name != b'':
 
441
                    params = {'branch': urllib.quote(branch_name.encode('utf-8'), '')}
 
442
                else:
 
443
                    params = {}
 
444
            try:
 
445
                base_url = urlutils.local_path_to_url(self.control_transport.get_bytes('commondir')).rstrip('/.git/')+'/'
 
446
            except bzr_errors.NoSuchFile:
 
447
                base_url = self.user_url.rstrip('/')
 
448
            return urlutils.join_segment_parameters(base_url, params)
398
449
        return None
399
450
 
400
451
    def find_branch_format(self, name=None):
430
481
        raise bzr_errors.IncompatibleFormat(format, self._format)
431
482
 
432
483
    def open_branch(self, name=None, unsupported=False, ignore_fallbacks=None,
433
 
            ref=None, possible_transports=None):
 
484
            ref=None, possible_transports=None, nascent_ok=False):
434
485
        """'create' a branch for this dir."""
435
486
        repo = self.find_repository()
436
487
        from .branch import LocalGitBranch
437
488
        ref = self._get_selected_ref(name, ref)
438
 
        ref_chain, sha = self._git.refs.follow(ref)
439
 
        if sha is None:
 
489
        if not nascent_ok and ref not in self._git.refs:
440
490
            raise bzr_errors.NotBranchError(self.root_transport.base,
441
491
                    controldir=self)
442
 
        return LocalGitBranch(self, repo, ref_chain[-1])
 
492
        ref_chain, unused_sha = self._git.refs.follow(ref)
 
493
        if ref_chain[-1] == b'HEAD':
 
494
            controldir = self
 
495
        else:
 
496
            controldir = self._find_commondir()
 
497
        return LocalGitBranch(controldir, repo, ref_chain[-1])
443
498
 
444
499
    def destroy_branch(self, name=None):
445
500
        refname = self._get_selected_ref(name)
 
501
        if refname == b'HEAD':
 
502
            # HEAD can't be removed
 
503
            raise bzr_errors.UnsupportedOperation(
 
504
                self.destroy_branch, self)
446
505
        try:
447
506
            del self._git.refs[refname]
448
507
        except KeyError:
453
512
        raise bzr_errors.UnsupportedOperation(self.destroy_repository, self)
454
513
 
455
514
    def destroy_workingtree(self):
456
 
        wt = self.open_workingtree(recommend_upgrade=False)
457
 
        repository = wt.branch.repository
458
 
        empty = repository.revision_tree(_mod_revision.NULL_REVISION)
459
 
        # We ignore the conflicts returned by wt.revert since we're about to
460
 
        # delete the wt metadata anyway, all that should be left here are
461
 
        # detritus. But see bug #634470 about subtree .bzr dirs.
462
 
        conflicts = wt.revert(old_tree=empty)
463
 
        self.destroy_workingtree_metadata()
 
515
        raise bzr_errors.UnsupportedOperation(self.destroy_workingtree, self)
464
516
 
465
517
    def destroy_workingtree_metadata(self):
466
 
        self.transport.delete('index')
 
518
        raise bzr_errors.UnsupportedOperation(self.destroy_workingtree_metadata, self)
467
519
 
468
520
    def needs_format_conversion(self, format=None):
469
521
        return not isinstance(self._format, format.__class__)
491
543
            raise bzr_errors.NoRepositoryPresent(self)
492
544
        return self._gitrepository_class(self)
493
545
 
 
546
    def has_workingtree(self):
 
547
        return not self._git.bare
 
548
 
494
549
    def open_workingtree(self, recommend_upgrade=True, unsupported=False):
495
550
        if not self._git.bare:
496
551
            from dulwich.errors import NoIndexPresent
501
556
                pass
502
557
            else:
503
558
                from .workingtree import GitWorkingTree
504
 
                try:
505
 
                    branch = self.open_branch()
506
 
                except bzr_errors.NotBranchError:
507
 
                    pass
508
 
                else:
509
 
                    return GitWorkingTree(self, repo, branch, index)
 
559
                branch = self.open_branch(ref=b'HEAD', nascent_ok=True)
 
560
                return GitWorkingTree(self, repo, branch, index)
510
561
        loc = urlutils.unescape_for_display(self.root_transport.base, 'ascii')
511
562
        raise bzr_errors.NoWorkingTree(loc)
512
563
 
519
570
    def create_branch(self, name=None, repository=None,
520
571
                      append_revisions_only=None, ref=None):
521
572
        refname = self._get_selected_ref(name, ref)
522
 
        from dulwich.protocol import ZERO_SHA
 
573
        if refname != b'HEAD' and refname in self._git.refs:
 
574
            raise bzr_errors.AlreadyBranchError(self.user_url)
 
575
        repo = self.open_repository()
 
576
        from dulwich.objects import ZERO_SHA
523
577
        if refname in self._git.refs:
524
 
            raise bzr_errors.AlreadyBranchError(self.user_url)
525
 
        self._git.refs[refname] = ZERO_SHA
526
 
        branch = self.open_branch(name)
 
578
            ref_chain, unused_sha = self._git.refs.follow(self._get_selected_ref(None))
 
579
            if ref_chain[0] == b'HEAD':
 
580
                refname = ref_chain[1]
 
581
            self._git.refs[refname] = ZERO_SHA
 
582
        from .branch import LocalGitBranch
 
583
        branch = LocalGitBranch(self, repo, refname)
527
584
        if append_revisions_only:
528
585
            branch.set_append_revisions_only(append_revisions_only)
529
586
        return branch
545
602
        from dulwich.index import build_index_from_tree
546
603
        from dulwich.objects import ZERO_SHA
547
604
        if from_branch is None:
548
 
            from_branch = self.open_branch()
 
605
            from_branch = self.open_branch(nascent_ok=True)
549
606
        if revision_id is None:
550
607
            revision_id = from_branch.last_revision()
551
608
        repo = self.find_repository()
557
614
            store,
558
615
            None if commit_id == ZERO_SHA else store[commit_id].tree)
559
616
        from .workingtree import GitWorkingTree
560
 
        index = repo._git.open_index()
 
617
        index = self._git.open_index()
561
618
        wt = GitWorkingTree(self, repo, from_branch, index)
562
619
        wt.set_last_revision(revision_id)
563
620
        return wt