~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transform.py

  • Committer: Patch Queue Manager
  • Date: 2011-10-14 16:54:26 UTC
  • mfrom: (6216.1.1 remove-this-file)
  • Revision ID: pqm@pqm.ubuntu.com-20111014165426-tjix4e6idryf1r2z
(jelmer) Remove an accidentally committed .THIS file. (Jelmer Vernooij)

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
from __future__ import absolute_import
18
 
 
19
17
import os
20
18
import errno
21
19
from stat import S_ISREG, S_IEXEC
36
34
    commit,
37
35
    conflicts,
38
36
    delta,
 
37
    errors,
39
38
    inventory,
40
39
    multiparent,
41
40
    osutils,
45
44
    )
46
45
from bzrlib.i18n import gettext
47
46
""")
48
 
from bzrlib.errors import (DuplicateKey, MalformedTransform,
 
47
from bzrlib.errors import (DuplicateKey, MalformedTransform, NoSuchFile,
49
48
                           ReusingTransform, CantMoveRoot,
50
49
                           ExistingLimbo, ImmortalLimbo, NoFinalPath,
51
50
                           UnableCreateSymlink)
52
51
from bzrlib.filters import filtered_output_bytes, ContentFilterContext
53
 
from bzrlib.mutabletree import MutableTree
54
52
from bzrlib.osutils import (
55
53
    delete_any,
56
54
    file_kind,
58
56
    pathjoin,
59
57
    sha_file,
60
58
    splitpath,
 
59
    supports_executable,
61
60
    )
62
61
from bzrlib.progress import ProgressPhase
63
62
from bzrlib.symbol_versioning import (
156
155
        """
157
156
        if self._tree is None:
158
157
            return
159
 
        for hook in MutableTree.hooks['post_transform']:
160
 
            hook(self._tree, self)
161
158
        self._tree.unlock()
162
159
        self._tree = None
163
160
 
232
229
        irrelevant.
233
230
 
234
231
        """
235
 
        new_roots = [k for k, v in self._new_parent.iteritems() if v ==
 
232
        new_roots = [k for k, v in self._new_parent.iteritems() if v is
236
233
                     ROOT_PARENT]
237
234
        if len(new_roots) < 1:
238
235
            return
565
562
        for trans_id in self._removed_id:
566
563
            file_id = self.tree_file_id(trans_id)
567
564
            if file_id is not None:
568
 
                if self._tree.stored_kind(file_id) == 'directory':
 
565
                # XXX: This seems like something that should go via a different
 
566
                #      indirection.
 
567
                if self._tree.inventory[file_id].kind == 'directory':
569
568
                    parents.append(trans_id)
570
569
            elif self.tree_kind(trans_id) == 'directory':
571
570
                parents.append(trans_id)
628
627
        for trans_id in self._new_parent:
629
628
            seen = set()
630
629
            parent_id = trans_id
631
 
            while parent_id != ROOT_PARENT:
 
630
            while parent_id is not ROOT_PARENT:
632
631
                seen.add(parent_id)
633
632
                try:
634
633
                    parent_id = self.final_parent(parent_id)
644
643
        """If parent directories are versioned, children must be versioned."""
645
644
        conflicts = []
646
645
        for parent_id, children in by_parent.iteritems():
647
 
            if parent_id == ROOT_PARENT:
 
646
            if parent_id is ROOT_PARENT:
648
647
                continue
649
648
            if self.final_file_id(parent_id) is not None:
650
649
                continue
743
742
        """Children must have a directory parent"""
744
743
        conflicts = []
745
744
        for parent_id, children in by_parent.iteritems():
746
 
            if parent_id == ROOT_PARENT:
 
745
            if parent_id is ROOT_PARENT:
747
746
                continue
748
747
            no_children = True
749
748
            for child_id in children:
765
764
 
766
765
    def _set_executability(self, path, trans_id):
767
766
        """Set the executability of versioned files """
768
 
        if self._tree._supports_executable():
 
767
        if supports_executable():
769
768
            new_executability = self._new_executability[trans_id]
770
769
            abspath = self._tree.abspath(path)
771
770
            current_mode = os.stat(abspath).st_mode
780
779
                    to_mode |= 0010 & ~umask
781
780
            else:
782
781
                to_mode = current_mode & ~0111
783
 
            osutils.chmod_if_possible(abspath, to_mode)
 
782
            os.chmod(abspath, to_mode)
784
783
 
785
784
    def _new_entry(self, name, parent_id, file_id):
786
785
        """Helper function to create a new filesystem entry."""
1235
1234
        finally:
1236
1235
            TreeTransformBase.finalize(self)
1237
1236
 
1238
 
    def _limbo_supports_executable(self):
1239
 
        """Check if the limbo path supports the executable bit."""
1240
 
        # FIXME: Check actual file system capabilities of limbodir
1241
 
        return osutils.supports_executable()
1242
 
 
1243
1237
    def _limbo_name(self, trans_id):
1244
1238
        """Generate the limbo name of a file"""
1245
1239
        limbo_name = self._limbo_files.get(trans_id)
1564
1558
        try:
1565
1559
            limbodir = urlutils.local_path_from_url(
1566
1560
                tree._transport.abspath('limbo'))
1567
 
            osutils.ensure_empty_directory_exists(
1568
 
                limbodir,
1569
 
                errors.ExistingLimbo)
 
1561
            try:
 
1562
                os.mkdir(limbodir)
 
1563
            except OSError, e:
 
1564
                if e.errno == errno.EEXIST:
 
1565
                    raise ExistingLimbo(limbodir)
1570
1566
            deletiondir = urlutils.local_path_from_url(
1571
1567
                tree._transport.abspath('pending-deletion'))
1572
 
            osutils.ensure_empty_directory_exists(
1573
 
                deletiondir,
1574
 
                errors.ExistingPendingDeletion)
 
1568
            try:
 
1569
                os.mkdir(deletiondir)
 
1570
            except OSError, e:
 
1571
                if e.errno == errno.EEXIST:
 
1572
                    raise errors.ExistingPendingDeletion(deletiondir)
1575
1573
        except:
1576
1574
            tree.unlock()
1577
1575
            raise
1640
1638
            else:
1641
1639
                raise
1642
1640
        if typefunc(mode):
1643
 
            osutils.chmod_if_possible(self._limbo_name(trans_id), mode)
 
1641
            os.chmod(self._limbo_name(trans_id), mode)
1644
1642
 
1645
1643
    def iter_tree_children(self, parent_id):
1646
1644
        """Iterate through the entry's tree children, if any"""
1724
1722
            calculating one.
1725
1723
        :param _mover: Supply an alternate FileMover, for testing
1726
1724
        """
1727
 
        for hook in MutableTree.hooks['pre_transform']:
1728
 
            hook(self._tree, self)
1729
1725
        if not no_conflicts:
1730
1726
            self._check_malformed()
1731
1727
        child_pb = ui.ui_factory.nested_progress_bar()
2330
2326
            if kind == 'file':
2331
2327
                statval = os.lstat(limbo_name)
2332
2328
                size = statval.st_size
2333
 
                if not tt._limbo_supports_executable():
 
2329
                if not supports_executable():
2334
2330
                    executable = False
2335
2331
                else:
2336
2332
                    executable = statval.st_mode & S_IEXEC
2551
2547
    file_trans_id = {}
2552
2548
    top_pb = ui.ui_factory.nested_progress_bar()
2553
2549
    pp = ProgressPhase("Build phase", 2, top_pb)
2554
 
    if tree.get_root_id() is not None:
 
2550
    if tree.inventory.root is not None:
2555
2551
        # This is kind of a hack: we should be altering the root
2556
2552
        # as part of the regular tree shape diff logic.
2557
2553
        # The conditional test here is to avoid doing an
2572
2568
        try:
2573
2569
            deferred_contents = []
2574
2570
            num = 0
2575
 
            total = len(tree.all_file_ids())
 
2571
            total = len(tree.inventory)
2576
2572
            if delta_from_tree:
2577
2573
                precomputed_delta = []
2578
2574
            else:
2587
2583
                for dir, files in wt.walkdirs():
2588
2584
                    existing_files.update(f[0] for f in files)
2589
2585
            for num, (tree_path, entry) in \
2590
 
                enumerate(tree.iter_entries_by_dir()):
 
2586
                enumerate(tree.inventory.iter_entries_by_dir()):
2591
2587
                pb.update(gettext("Building tree"), num - len(deferred_contents), total)
2592
2588
                if entry.parent_id is None:
2593
2589
                    continue
2843
2839
            return new_name
2844
2840
 
2845
2841
 
 
2842
def _entry_changes(file_id, entry, working_tree):
 
2843
    """Determine in which ways the inventory entry has changed.
 
2844
 
 
2845
    Returns booleans: has_contents, content_mod, meta_mod
 
2846
    has_contents means there are currently contents, but they differ
 
2847
    contents_mod means contents need to be modified
 
2848
    meta_mod means the metadata needs to be modified
 
2849
    """
 
2850
    cur_entry = working_tree.inventory[file_id]
 
2851
    try:
 
2852
        working_kind = working_tree.kind(file_id)
 
2853
        has_contents = True
 
2854
    except NoSuchFile:
 
2855
        has_contents = False
 
2856
        contents_mod = True
 
2857
        meta_mod = False
 
2858
    if has_contents is True:
 
2859
        if entry.kind != working_kind:
 
2860
            contents_mod, meta_mod = True, False
 
2861
        else:
 
2862
            cur_entry._read_tree_state(working_tree.id2path(file_id),
 
2863
                                       working_tree)
 
2864
            contents_mod, meta_mod = entry.detect_changes(cur_entry)
 
2865
            cur_entry._forget_tree_state()
 
2866
    return has_contents, contents_mod, meta_mod
 
2867
 
 
2868
 
2846
2869
def revert(working_tree, target_tree, filenames, backups=False,
2847
2870
           pb=None, change_reporter=None):
2848
2871
    """Revert a working tree's contents to those of a target tree."""
3055
3078
                existing_file, new_file = conflict[2], conflict[1]
3056
3079
            else:
3057
3080
                existing_file, new_file = conflict[1], conflict[2]
3058
 
            new_name = tt.final_name(existing_file) + '.moved'
 
3081
            new_name = tt.final_name(existing_file)+'.moved'
3059
3082
            tt.adjust_path(new_name, final_parent, existing_file)
3060
3083
            new_conflicts.add((c_type, 'Moved existing file to',
3061
3084
                               existing_file, new_file))