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

Merge a bunch of fixes from store-roundtrip-info.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
from cStringIO import StringIO
20
20
 
 
21
import os
 
22
import urllib
 
23
 
21
24
from dulwich.errors import (
22
25
    NotGitRepository,
23
26
    NoIndexPresent,
33
36
    MemoryPackIndex,
34
37
    PackData,
35
38
    Pack,
36
 
    ThinPackData,
37
39
    iter_sha1,
38
40
    load_pack_index_file,
39
41
    write_pack_data,
42
44
from dulwich.repo import (
43
45
    BaseRepo,
44
46
    RefsContainer,
 
47
    BASE_DIRECTORIES,
45
48
    INDEX_FILENAME,
46
49
    OBJECTDIR,
47
50
    REFSDIR,
52
55
    write_packed_refs,
53
56
    )
54
57
 
 
58
from bzrlib import (
 
59
    transport as _mod_transport,
 
60
    )
55
61
from bzrlib.errors import (
56
62
    FileExists,
57
63
    NoSuchFile,
82
88
        keys = set()
83
89
        try:
84
90
            iter_files = self.transport.clone(base).iter_files_recursive()
85
 
            keys.update(("%s/%s" % (base, refname)).strip("/") for 
 
91
            keys.update(("%s/%s" % (base, urllib.unquote(refname))).strip("/") for 
86
92
                    refname in iter_files if check_ref_format("%s/%s" % (base, refname)))
87
93
        except (TransportNotPossible, NoSuchFile):
88
94
            pass
93
99
 
94
100
    def allkeys(self):
95
101
        keys = set()
96
 
        if self.transport.has("HEAD"):
 
102
        try:
 
103
            self.transport.get_bytes("HEAD")
 
104
        except NoSuchFile:
 
105
            pass
 
106
        else:
97
107
            keys.add("HEAD")
98
108
        try:
99
109
            iter_files = list(self.transport.clone("refs").iter_files_recursive())
100
110
            for filename in iter_files:
101
 
                refname = "refs/%s" % filename
 
111
                refname = "refs/%s" % urllib.unquote(filename)
102
112
                if check_ref_format(refname):
103
113
                    keys.add(refname)
104
114
        except (TransportNotPossible, NoSuchFile):
173
183
            f = self.transport.get(name)
174
184
        except NoSuchFile:
175
185
            return None
 
186
        f = StringIO(f.read())
176
187
        try:
177
188
            header = f.read(len(SYMREF))
178
189
            if header == SYMREF:
276
287
        self._remove_packed_ref(name)
277
288
        return True
278
289
 
 
290
    def get(self, name, default=None):
 
291
        try:
 
292
            return self[name]
 
293
        except KeyError:
 
294
            return default
 
295
 
279
296
 
280
297
class TransportRepo(BaseRepo):
281
298
 
282
 
    def __init__(self, transport):
 
299
    def __init__(self, transport, bare, refs_text=None):
283
300
        self.transport = transport
284
 
        try:
285
 
            if self.transport.has(".git/%s" % OBJECTDIR):
286
 
                self.bare = False
287
 
                self._controltransport = self.transport.clone('.git')
288
 
            elif self.transport.has_any(["info/refs", OBJECTDIR, REFSDIR]):
289
 
                self.bare = True
290
 
                self._controltransport = self.transport
291
 
            else:
292
 
                raise NotGitRepository(self.transport)
293
 
        except NoSuchFile:
294
 
            raise NotGitRepository(self.transport)
 
301
        self.bare = bare
 
302
        if self.bare:
 
303
            self._controltransport = self.transport
 
304
        else:
 
305
            self._controltransport = self.transport.clone('.git')
295
306
        object_store = TransportObjectStore(
296
307
            self._controltransport.clone(OBJECTDIR))
 
308
        if refs_text is not None:
 
309
            from dulwich.repo import InfoRefsContainer # dulwich >= 0.8.2
 
310
            refs_container = InfoRefsContainer(StringIO(refs_text))
 
311
            try:
 
312
                head = TransportRefsContainer(self._controltransport).read_loose_ref("HEAD")
 
313
            except KeyError:
 
314
                pass
 
315
            else:
 
316
                refs_container._refs["HEAD"] = head
 
317
        else:
 
318
            refs_container = TransportRefsContainer(self._controltransport)
297
319
        super(TransportRepo, self).__init__(object_store, 
298
 
                TransportRefsContainer(self._controltransport))
 
320
                refs_container)
299
321
 
300
322
    def get_named_file(self, path):
301
323
        """Get a file from the control dir with a specific name.
312
334
        except NoSuchFile:
313
335
            return None
314
336
 
 
337
    def _put_named_file(self, relpath, contents):
 
338
        self._controltransport.put_bytes(relpath, contents)
 
339
 
315
340
    def index_path(self):
316
341
        """Return the path to the index file."""
317
342
        return self._controltransport.local_abspath(INDEX_FILENAME)
329
354
        # missing index file, which is treated as empty.
330
355
        return not self.bare
331
356
 
 
357
    def get_config(self):
 
358
        from dulwich.config import ConfigFile
 
359
        try:
 
360
            return ConfigFile.from_file(self._controltransport.get('config'))
 
361
        except NoSuchFile:
 
362
            return ConfigFile()
 
363
 
 
364
    def get_config_stack(self):
 
365
        from dulwich.config import StackedConfig
 
366
        backends = []
 
367
        p = self.get_config()
 
368
        if p is not None:
 
369
            backends.append(p)
 
370
            writable = p
 
371
        else:
 
372
            writable = None
 
373
        backends.extend(StackedConfig.default_backends())
 
374
        return StackedConfig(backends, writable=writable)
 
375
 
332
376
    def __repr__(self):
333
377
        return "<%s for %r>" % (self.__class__.__name__, self.transport)
334
378
 
 
379
    @classmethod
 
380
    def init(cls, transport, bare=False):
 
381
        if not bare:
 
382
            transport.mkdir(".git")
 
383
            control_transport = transport.clone(".git")
 
384
        else:
 
385
            control_transport = transport
 
386
        for d in BASE_DIRECTORIES:
 
387
            control_transport.mkdir("/".join(d))
 
388
        control_transport.mkdir(OBJECTDIR)
 
389
        TransportObjectStore.init(control_transport.clone(OBJECTDIR))
 
390
        ret = cls(transport, bare)
 
391
        ret.refs.set_symbolic_ref("HEAD", "refs/heads/master")
 
392
        ret._init_files(bare)
 
393
        return ret
 
394
 
335
395
 
336
396
class TransportObjectStore(PackBasedObjectStore):
337
397
    """Git-style object store that exists on disk."""
344
404
        super(TransportObjectStore, self).__init__()
345
405
        self.transport = transport
346
406
        self.pack_transport = self.transport.clone(PACKDIR)
 
407
        self._alternates = None
347
408
 
348
409
    def __repr__(self):
349
410
        return "%s(%r)" % (self.__class__.__name__, self.transport)
351
412
    def _pack_cache_stale(self):
352
413
        return False # FIXME
353
414
 
 
415
    @property
 
416
    def alternates(self):
 
417
        if self._alternates is not None:
 
418
            return self._alternates
 
419
        self._alternates = []
 
420
        for path in self._read_alternate_paths():
 
421
            # FIXME: Check path
 
422
            t = _mod_transport.get_transport_from_path(path)
 
423
            self._alternates.append(self.__class__(t))
 
424
        return self._alternates
 
425
 
 
426
    def _read_alternate_paths(self):
 
427
        try:
 
428
            f = self.transport.get("info/alternates")
 
429
        except NoSuchFile:
 
430
            return []
 
431
        ret = []
 
432
        try:
 
433
            for l in f.read().splitlines():
 
434
                if l[0] == "#":
 
435
                    continue
 
436
                if os.path.isabs(l):
 
437
                    continue
 
438
                ret.append(l)
 
439
            return ret
 
440
        finally:
 
441
            f.close()
 
442
 
354
443
    def _pack_names(self):
355
444
        try:
356
445
            f = self.transport.get('info/packs')
358
447
            return self.pack_transport.list_dir(".")
359
448
        else:
360
449
            ret = []
361
 
            for line in f.readlines():
362
 
                line = line.rstrip("\n")
 
450
            for line in f.read().splitlines():
363
451
                if not line:
364
452
                    continue
365
453
                (kind, name) = line.split(" ", 1)
473
561
        :param path: Path to the pack file.
474
562
        """
475
563
        f.seek(0)
476
 
        data = ThinPackData.from_file(self.get_raw, f, len(f.getvalue()))
 
564
        data = PackData.from_file(self.get_raw, f, len(f.getvalue()))
477
565
        idx = MemoryPackIndex(data.sorted_entries(), data.get_stored_checksum())
478
566
        p = Pack.from_objects(data, idx)
479
567
 
480
568
        pack_sha = idx.objects_sha1()
481
569
 
482
 
        datafile = self.pack_transport.open_write_stream("pack-%s.pack" % pack_sha)
 
570
        datafile = self.pack_transport.open_write_stream(
 
571
                "pack-%s.pack" % pack_sha)
483
572
        try:
484
 
            entries, data_sum = write_pack_data(datafile, ((o, None) for o in p.iterobjects()), len(p))
 
573
            entries, data_sum = write_pack_data(datafile, p.pack_tuples())
485
574
        finally:
486
575
            datafile.close()
487
576
        entries.sort()
488
 
        idxfile = self.pack_transport.open_write_stream("pack-%s.idx" % pack_sha)
 
577
        idxfile = self.pack_transport.open_write_stream(
 
578
            "pack-%s.idx" % pack_sha)
489
579
        try:
490
580
            write_pack_index_v2(idxfile, data.sorted_entries(), data_sum)
491
581
        finally:
494
584
        self._add_known_pack(final_pack)
495
585
        return final_pack
496
586
 
497
 
 
498
 
 
499
587
    def add_pack(self):
500
588
        """Add a new pack to this object store. 
501
589