~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/workingtree.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2008-06-05 04:05:05 UTC
  • mfrom: (3473.1.1 ianc-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20080605040505-i9kqxg2fps2qjdi0
Add the 'alias' command (Tim Penhey)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006, 2007, 2008 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
246
246
            # permitted to do this.
247
247
            self._set_inventory(_inventory, dirty=False)
248
248
        self._detect_case_handling()
249
 
        self._rules_searcher = None
250
249
 
251
250
    def _detect_case_handling(self):
252
251
        wt_trans = self.bzrdir.get_workingtree_transport(None)
303
302
 
304
303
        """
305
304
        if path is None:
306
 
            path = osutils.getcwd()
 
305
            path = os.path.getcwdu()
307
306
        control = bzrdir.BzrDir.open(path, _unsupported)
308
307
        return control.open_workingtree(_unsupported)
309
 
 
 
308
        
310
309
    @staticmethod
311
310
    def open_containing(path=None):
312
311
        """Open an existing working tree which has its root about path.
313
 
 
 
312
        
314
313
        This probes for a working tree at path and searches upwards from there.
315
314
 
316
315
        Basically we keep looking up until we find the control directory or
379
378
        """Return RevisionTree for the current last revision.
380
379
        
381
380
        If the left most parent is a ghost then the returned tree will be an
382
 
        empty tree - one obtained by calling 
383
 
        repository.revision_tree(NULL_REVISION).
 
381
        empty tree - one obtained by calling repository.revision_tree(None).
384
382
        """
385
383
        try:
386
384
            revision_id = self.get_parent_ids()[0]
388
386
            # no parents, return an empty revision tree.
389
387
            # in the future this should return the tree for
390
388
            # 'empty:' - the implicit root empty tree.
391
 
            return self.branch.repository.revision_tree(
392
 
                       _mod_revision.NULL_REVISION)
 
389
            return self.branch.repository.revision_tree(None)
393
390
        try:
394
391
            return self.revision_tree(revision_id)
395
392
        except errors.NoSuchRevision:
399
396
        # at this point ?
400
397
        try:
401
398
            return self.branch.repository.revision_tree(revision_id)
402
 
        except (errors.RevisionNotPresent, errors.NoSuchRevision):
 
399
        except errors.RevisionNotPresent:
403
400
            # the basis tree *may* be a ghost or a low level error may have
404
401
            # occured. If the revision is present, its a problem, if its not
405
402
            # its a ghost.
406
403
            if self.branch.repository.has_revision(revision_id):
407
404
                raise
408
405
            # the basis tree is a ghost so return an empty tree.
409
 
            return self.branch.repository.revision_tree(
410
 
                       _mod_revision.NULL_REVISION)
 
406
            return self.branch.repository.revision_tree(None)
411
407
 
412
408
    def _cleanup(self):
413
409
        self._flush_ignore_list_cache()
424
420
        return osutils.lexists(self.abspath(filename))
425
421
 
426
422
    def get_file(self, file_id, path=None):
427
 
        return self.get_file_with_stat(file_id, path)[0]
428
 
 
429
 
    def get_file_with_stat(self, file_id, path=None, _fstat=os.fstat):
430
 
        """See MutableTree.get_file_with_stat."""
431
423
        if path is None:
432
424
            path = self.id2path(file_id)
433
 
        file_obj = self.get_file_byname(path)
434
 
        return (file_obj, _fstat(file_obj.fileno()))
 
425
        return self.get_file_byname(path)
 
426
 
 
427
    def get_file_text(self, file_id):
 
428
        return self.get_file(file_id).read()
435
429
 
436
430
    def get_file_byname(self, filename):
437
431
        return file(self.abspath(filename), 'rb')
438
432
 
439
 
    def get_file_lines(self, file_id, path=None):
440
 
        """See Tree.get_file_lines()"""
441
 
        file = self.get_file(file_id, path)
442
 
        try:
443
 
            return file.readlines()
444
 
        finally:
445
 
            file.close()
446
 
 
447
433
    @needs_read_lock
448
434
    def annotate_iter(self, file_id, default_revision=CURRENT_REVISION):
449
435
        """See Tree.annotate_iter
533
519
            and this one merged in.
534
520
        """
535
521
        # assumes the target bzr dir format is compatible.
536
 
        result = to_bzrdir.create_workingtree()
 
522
        result = self._format.initialize(to_bzrdir)
537
523
        self.copy_content_into(result, revision_id)
538
524
        return result
539
525
 
910
896
            hashfile = self._transport.get('merge-hashes')
911
897
        except errors.NoSuchFile:
912
898
            return {}
 
899
        merge_hashes = {}
913
900
        try:
914
 
            merge_hashes = {}
915
 
            try:
916
 
                if hashfile.next() != MERGE_MODIFIED_HEADER_1 + '\n':
917
 
                    raise errors.MergeModifiedFormatError()
918
 
            except StopIteration:
 
901
            if hashfile.next() != MERGE_MODIFIED_HEADER_1 + '\n':
919
902
                raise errors.MergeModifiedFormatError()
920
 
            for s in RioReader(hashfile):
921
 
                # RioReader reads in Unicode, so convert file_ids back to utf8
922
 
                file_id = osutils.safe_file_id(s.get("file_id"), warn=False)
923
 
                if file_id not in self.inventory:
924
 
                    continue
925
 
                text_hash = s.get("hash")
926
 
                if text_hash == self.get_file_sha1(file_id):
927
 
                    merge_hashes[file_id] = text_hash
928
 
            return merge_hashes
929
 
        finally:
930
 
            hashfile.close()
 
903
        except StopIteration:
 
904
            raise errors.MergeModifiedFormatError()
 
905
        for s in RioReader(hashfile):
 
906
            # RioReader reads in Unicode, so convert file_ids back to utf8
 
907
            file_id = osutils.safe_file_id(s.get("file_id"), warn=False)
 
908
            if file_id not in self.inventory:
 
909
                continue
 
910
            text_hash = s.get("hash")
 
911
            if text_hash == self.get_file_sha1(file_id):
 
912
                merge_hashes[file_id] = text_hash
 
913
        return merge_hashes
931
914
 
932
915
    @needs_write_lock
933
916
    def mkdir(self, path, file_id=None):
1332
1315
                only_change_inv = True
1333
1316
            elif self.has_filename(from_rel) and not self.has_filename(to_rel):
1334
1317
                only_change_inv = False
1335
 
            elif (not self.case_sensitive
1336
 
                  and from_rel.lower() == to_rel.lower()
1337
 
                  and self.has_filename(from_rel)):
 
1318
            elif (sys.platform == 'win32'
 
1319
                and from_rel.lower() == to_rel.lower()
 
1320
                and self.has_filename(from_rel)):
1338
1321
                only_change_inv = False
1339
1322
            else:
1340
1323
                # something is wrong, so lets determine what exactly
1608
1591
                if subf == '.bzr':
1609
1592
                    continue
1610
1593
                if subf not in dir_entry.children:
1611
 
                    try:
1612
 
                        (subf_norm,
1613
 
                         can_access) = osutils.normalized_filename(subf)
1614
 
                    except UnicodeDecodeError:
1615
 
                        path_os_enc = path.encode(osutils._fs_enc)
1616
 
                        relpath = path_os_enc + '/' + subf
1617
 
                        raise errors.BadFilenameEncoding(relpath,
1618
 
                                                         osutils._fs_enc)
 
1594
                    subf_norm, can_access = osutils.normalized_filename(subf)
1619
1595
                    if subf_norm != subf and can_access:
1620
1596
                        if subf_norm not in dir_entry.children:
1621
1597
                            fl.append(subf_norm)
1875
1851
            # Recurse directory and add all files
1876
1852
            # so we can check if they have changed.
1877
1853
            for parent_info, file_infos in\
1878
 
                self.walkdirs(directory):
1879
 
                for relpath, basename, kind, lstat, fileid, kind in file_infos:
 
1854
                osutils.walkdirs(self.abspath(directory),
 
1855
                    directory):
 
1856
                for relpath, basename, kind, lstat, abspath in file_infos:
1880
1857
                    # Is it versioned or ignored?
1881
1858
                    if self.path2id(relpath) or self.is_ignored(relpath):
1882
1859
                        # Add nested content for deletion.
1892
1869
            filename = self.relpath(abspath)
1893
1870
            if len(filename) > 0:
1894
1871
                new_files.add(filename)
1895
 
                recurse_directory_to_add_files(filename)
 
1872
                if osutils.isdir(abspath):
 
1873
                    recurse_directory_to_add_files(filename)
1896
1874
 
1897
1875
        files = list(new_files)
1898
1876
 
2336
2314
                    # value.
2337
2315
                    bzrdir_loc = bisect_left(cur_disk_dir_content,
2338
2316
                        ('.bzr', '.bzr'))
2339
 
                    if (bzrdir_loc < len(cur_disk_dir_content)
2340
 
                        and cur_disk_dir_content[bzrdir_loc][0] == '.bzr'):
 
2317
                    if cur_disk_dir_content[bzrdir_loc][0] == '.bzr':
2341
2318
                        # we dont yield the contents of, or, .bzr itself.
2342
2319
                        del cur_disk_dir_content[bzrdir_loc]
2343
2320
            if inv_finished:
2433
2410
                relroot = ""
2434
2411
            # FIXME: stash the node in pending
2435
2412
            entry = inv[top_id]
2436
 
            if entry.kind == 'directory':
2437
 
                for name, child in entry.sorted_children():
2438
 
                    dirblock.append((relroot + name, name, child.kind, None,
2439
 
                        child.file_id, child.kind
2440
 
                        ))
 
2413
            for name, child in entry.sorted_children():
 
2414
                dirblock.append((relroot + name, name, child.kind, None,
 
2415
                    child.file_id, child.kind
 
2416
                    ))
2441
2417
            yield (currentdir[0], entry.file_id), dirblock
2442
2418
            # push the user specified dirs from dirblock
2443
2419
            for dir in reversed(dirblock):
2476
2452
        self.set_conflicts(un_resolved)
2477
2453
        return un_resolved, resolved
2478
2454
 
2479
 
    @needs_read_lock
2480
 
    def _check(self):
2481
 
        tree_basis = self.basis_tree()
2482
 
        tree_basis.lock_read()
2483
 
        try:
2484
 
            repo_basis = self.branch.repository.revision_tree(
2485
 
                self.last_revision())
2486
 
            if len(list(repo_basis.iter_changes(tree_basis))) > 0:
2487
 
                raise errors.BzrCheckError(
2488
 
                    "Mismatched basis inventory content.")
2489
 
            self._validate()
2490
 
        finally:
2491
 
            tree_basis.unlock()
2492
 
 
2493
2455
    def _validate(self):
2494
2456
        """Validate internal structures.
2495
2457
 
2501
2463
        """
2502
2464
        return
2503
2465
 
2504
 
    @needs_read_lock
2505
 
    def _get_rules_searcher(self, default_searcher):
2506
 
        """See Tree._get_rules_searcher."""
2507
 
        if self._rules_searcher is None:
2508
 
            self._rules_searcher = super(WorkingTree,
2509
 
                self)._get_rules_searcher(default_searcher)
2510
 
        return self._rules_searcher
2511
 
 
2512
2466
 
2513
2467
class WorkingTree2(WorkingTree):
2514
2468
    """This is the Format 2 working tree.
2610
2564
        except errors.NoSuchFile:
2611
2565
            return _mod_conflicts.ConflictList()
2612
2566
        try:
2613
 
            try:
2614
 
                if confile.next() != CONFLICT_HEADER_1 + '\n':
2615
 
                    raise errors.ConflictFormatError()
2616
 
            except StopIteration:
 
2567
            if confile.next() != CONFLICT_HEADER_1 + '\n':
2617
2568
                raise errors.ConflictFormatError()
2618
 
            return _mod_conflicts.ConflictList.from_stanzas(RioReader(confile))
2619
 
        finally:
2620
 
            confile.close()
 
2569
        except StopIteration:
 
2570
            raise errors.ConflictFormatError()
 
2571
        return _mod_conflicts.ConflictList.from_stanzas(RioReader(confile))
2621
2572
 
2622
2573
    def unlock(self):
2623
2574
        # do non-implementation specific cleanup
2734
2685
        """See WorkingTreeFormat.get_format_description()."""
2735
2686
        return "Working tree format 2"
2736
2687
 
2737
 
    def _stub_initialize_on_transport(self, transport, file_mode):
2738
 
        """Workaround: create control files for a remote working tree.
2739
 
 
 
2688
    def _stub_initialize_remote(self, branch):
 
2689
        """As a special workaround create critical control files for a remote working tree.
 
2690
        
2740
2691
        This ensures that it can later be updated and dealt with locally,
2741
 
        since BzrDirFormat6 and BzrDirFormat5 cannot represent dirs with
 
2692
        since BzrDirFormat6 and BzrDirFormat5 cannot represent dirs with 
2742
2693
        no working tree.  (See bug #43064).
2743
2694
        """
2744
2695
        sio = StringIO()
2745
2696
        inv = Inventory()
2746
2697
        xml5.serializer_v5.write_inventory(inv, sio, working=True)
2747
2698
        sio.seek(0)
2748
 
        transport.put_file('inventory', sio, file_mode)
2749
 
        transport.put_bytes('pending-merges', '', file_mode)
 
2699
        branch._transport.put_file('inventory', sio,
 
2700
            mode=branch.control_files._file_mode)
 
2701
        branch._transport.put_bytes('pending-merges', '',
 
2702
            mode=branch.control_files._file_mode)
 
2703
        
2750
2704
 
2751
2705
    def initialize(self, a_bzrdir, revision_id=None, from_branch=None,
2752
2706
                   accelerator_tree=None, hardlink=False):