~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/transform.py

  • Committer: Martin Packman
  • Date: 2012-01-05 09:50:04 UTC
  • mfrom: (6424 +trunk)
  • mto: This revision was merged to the branch mainline in revision 6426.
  • Revision ID: martin.packman@canonical.com-20120105095004-mia9xb7y0efmto0v
Merge bzr.dev to resolve conflicts in bzrlib.builtins

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
 
17
19
import os
18
20
import errno
19
21
from stat import S_ISREG, S_IEXEC
30
32
from bzrlib import (
31
33
    annotate,
32
34
    bencode,
33
 
    bzrdir,
 
35
    controldir,
34
36
    commit,
35
37
    conflicts,
36
38
    delta,
37
 
    errors,
38
39
    inventory,
39
40
    multiparent,
40
41
    osutils,
42
43
    ui,
43
44
    urlutils,
44
45
    )
 
46
from bzrlib.i18n import gettext
45
47
""")
46
 
from bzrlib.errors import (DuplicateKey, MalformedTransform, NoSuchFile,
 
48
from bzrlib.errors import (DuplicateKey, MalformedTransform,
47
49
                           ReusingTransform, CantMoveRoot,
48
50
                           ExistingLimbo, ImmortalLimbo, NoFinalPath,
49
51
                           UnableCreateSymlink)
561
563
        for trans_id in self._removed_id:
562
564
            file_id = self.tree_file_id(trans_id)
563
565
            if file_id is not None:
564
 
                # XXX: This seems like something that should go via a different
565
 
                #      indirection.
566
 
                if self._tree.inventory[file_id].kind == 'directory':
 
566
                if self._tree.stored_kind(file_id) == 'directory':
567
567
                    parents.append(trans_id)
568
568
            elif self.tree_kind(trans_id) == 'directory':
569
569
                parents.append(trans_id)
763
763
 
764
764
    def _set_executability(self, path, trans_id):
765
765
        """Set the executability of versioned files """
766
 
        if supports_executable():
 
766
        if self._tree._supports_executable():
767
767
            new_executability = self._new_executability[trans_id]
768
768
            abspath = self._tree.abspath(path)
769
769
            current_mode = os.stat(abspath).st_mode
778
778
                    to_mode |= 0010 & ~umask
779
779
            else:
780
780
                to_mode = current_mode & ~0111
781
 
            os.chmod(abspath, to_mode)
 
781
            osutils.chmod_if_possible(abspath, to_mode)
782
782
 
783
783
    def _new_entry(self, name, parent_id, file_id):
784
784
        """Helper function to create a new filesystem entry."""
1233
1233
        finally:
1234
1234
            TreeTransformBase.finalize(self)
1235
1235
 
 
1236
    def _limbo_supports_executable(self):
 
1237
        """Check if the limbo path supports the executable bit."""
 
1238
        # FIXME: Check actual file system capabilities of limbodir
 
1239
        return osutils.supports_executable()
 
1240
 
1236
1241
    def _limbo_name(self, trans_id):
1237
1242
        """Generate the limbo name of a file"""
1238
1243
        limbo_name = self._limbo_files.get(trans_id)
1557
1562
        try:
1558
1563
            limbodir = urlutils.local_path_from_url(
1559
1564
                tree._transport.abspath('limbo'))
1560
 
            try:
1561
 
                os.mkdir(limbodir)
1562
 
            except OSError, e:
1563
 
                if e.errno == errno.EEXIST:
1564
 
                    raise ExistingLimbo(limbodir)
 
1565
            osutils.ensure_empty_directory_exists(
 
1566
                limbodir,
 
1567
                errors.ExistingLimbo)
1565
1568
            deletiondir = urlutils.local_path_from_url(
1566
1569
                tree._transport.abspath('pending-deletion'))
1567
 
            try:
1568
 
                os.mkdir(deletiondir)
1569
 
            except OSError, e:
1570
 
                if e.errno == errno.EEXIST:
1571
 
                    raise errors.ExistingPendingDeletion(deletiondir)
 
1570
            osutils.ensure_empty_directory_exists(
 
1571
                deletiondir,
 
1572
                errors.ExistingPendingDeletion)
1572
1573
        except:
1573
1574
            tree.unlock()
1574
1575
            raise
1637
1638
            else:
1638
1639
                raise
1639
1640
        if typefunc(mode):
1640
 
            os.chmod(self._limbo_name(trans_id), mode)
 
1641
            osutils.chmod_if_possible(self._limbo_name(trans_id), mode)
1641
1642
 
1642
1643
    def iter_tree_children(self, parent_id):
1643
1644
        """Iterate through the entry's tree children, if any"""
1726
1727
        child_pb = ui.ui_factory.nested_progress_bar()
1727
1728
        try:
1728
1729
            if precomputed_delta is None:
1729
 
                child_pb.update('Apply phase', 0, 2)
 
1730
                child_pb.update(gettext('Apply phase'), 0, 2)
1730
1731
                inventory_delta = self._generate_inventory_delta()
1731
1732
                offset = 1
1732
1733
            else:
1737
1738
            else:
1738
1739
                mover = _mover
1739
1740
            try:
1740
 
                child_pb.update('Apply phase', 0 + offset, 2 + offset)
 
1741
                child_pb.update(gettext('Apply phase'), 0 + offset, 2 + offset)
1741
1742
                self._apply_removals(mover)
1742
 
                child_pb.update('Apply phase', 1 + offset, 2 + offset)
 
1743
                child_pb.update(gettext('Apply phase'), 1 + offset, 2 + offset)
1743
1744
                modified_paths = self._apply_insertions(mover)
1744
1745
            except:
1745
1746
                mover.rollback()
1765
1766
        try:
1766
1767
            for num, trans_id in enumerate(self._removed_id):
1767
1768
                if (num % 10) == 0:
1768
 
                    child_pb.update('removing file', num, total_entries)
 
1769
                    child_pb.update(gettext('removing file'), num, total_entries)
1769
1770
                if trans_id == self._new_root:
1770
1771
                    file_id = self._tree.get_root_id()
1771
1772
                else:
1783
1784
            final_kinds = {}
1784
1785
            for num, (path, trans_id) in enumerate(new_paths):
1785
1786
                if (num % 10) == 0:
1786
 
                    child_pb.update('adding file',
 
1787
                    child_pb.update(gettext('adding file'),
1787
1788
                                    num + len(self._removed_id), total_entries)
1788
1789
                file_id = new_path_file_ids[trans_id]
1789
1790
                if file_id is None:
1833
1834
                # do not attempt to move root into a subdirectory of itself.
1834
1835
                if path == '':
1835
1836
                    continue
1836
 
                child_pb.update('removing file', num, len(tree_paths))
 
1837
                child_pb.update(gettext('removing file'), num, len(tree_paths))
1837
1838
                full_path = self._tree.abspath(path)
1838
1839
                if trans_id in self._removed_contents:
1839
1840
                    delete_path = os.path.join(self._deletiondir, trans_id)
1868
1869
        try:
1869
1870
            for num, (path, trans_id) in enumerate(new_paths):
1870
1871
                if (num % 10) == 0:
1871
 
                    child_pb.update('adding file', num, len(new_paths))
 
1872
                    child_pb.update(gettext('adding file'), num, len(new_paths))
1872
1873
                full_path = self._tree.abspath(path)
1873
1874
                if trans_id in self._needs_rename:
1874
1875
                    try:
2325
2326
            if kind == 'file':
2326
2327
                statval = os.lstat(limbo_name)
2327
2328
                size = statval.st_size
2328
 
                if not supports_executable():
 
2329
                if not tt._limbo_supports_executable():
2329
2330
                    executable = False
2330
2331
                else:
2331
2332
                    executable = statval.st_mode & S_IEXEC
2546
2547
    file_trans_id = {}
2547
2548
    top_pb = ui.ui_factory.nested_progress_bar()
2548
2549
    pp = ProgressPhase("Build phase", 2, top_pb)
2549
 
    if tree.inventory.root is not None:
 
2550
    if tree.get_root_id() is not None:
2550
2551
        # This is kind of a hack: we should be altering the root
2551
2552
        # as part of the regular tree shape diff logic.
2552
2553
        # The conditional test here is to avoid doing an
2567
2568
        try:
2568
2569
            deferred_contents = []
2569
2570
            num = 0
2570
 
            total = len(tree.inventory)
 
2571
            total = len(tree.all_file_ids())
2571
2572
            if delta_from_tree:
2572
2573
                precomputed_delta = []
2573
2574
            else:
2582
2583
                for dir, files in wt.walkdirs():
2583
2584
                    existing_files.update(f[0] for f in files)
2584
2585
            for num, (tree_path, entry) in \
2585
 
                enumerate(tree.inventory.iter_entries_by_dir()):
2586
 
                pb.update("Building tree", num - len(deferred_contents), total)
 
2586
                enumerate(tree.iter_entries_by_dir()):
 
2587
                pb.update(gettext("Building tree"), num - len(deferred_contents), total)
2587
2588
                if entry.parent_id is None:
2588
2589
                    continue
2589
2590
                reparent = False
2595
2596
                    kind = file_kind(target_path)
2596
2597
                    if kind == "directory":
2597
2598
                        try:
2598
 
                            bzrdir.BzrDir.open(target_path)
 
2599
                            controldir.ControlDir.open(target_path)
2599
2600
                        except errors.NotBranchError:
2600
2601
                            pass
2601
2602
                        else:
2673
2674
                new_desired_files.append((file_id,
2674
2675
                    (trans_id, tree_path, text_sha1)))
2675
2676
                continue
2676
 
            pb.update('Adding file contents', count + offset, total)
 
2677
            pb.update(gettext('Adding file contents'), count + offset, total)
2677
2678
            if hardlink:
2678
2679
                tt.create_hardlink(accelerator_tree.abspath(accelerator_path),
2679
2680
                                   trans_id)
2700
2701
            contents = filtered_output_bytes(contents, filters,
2701
2702
                ContentFilterContext(tree_path, tree))
2702
2703
        tt.create_file(contents, trans_id, sha1=text_sha1)
2703
 
        pb.update('Adding file contents', count + offset, total)
 
2704
        pb.update(gettext('Adding file contents'), count + offset, total)
2704
2705
 
2705
2706
 
2706
2707
def _reparent_children(tt, old_parent, new_parent):
2838
2839
            return new_name
2839
2840
 
2840
2841
 
2841
 
def _entry_changes(file_id, entry, working_tree):
2842
 
    """Determine in which ways the inventory entry has changed.
2843
 
 
2844
 
    Returns booleans: has_contents, content_mod, meta_mod
2845
 
    has_contents means there are currently contents, but they differ
2846
 
    contents_mod means contents need to be modified
2847
 
    meta_mod means the metadata needs to be modified
2848
 
    """
2849
 
    cur_entry = working_tree.inventory[file_id]
2850
 
    try:
2851
 
        working_kind = working_tree.kind(file_id)
2852
 
        has_contents = True
2853
 
    except NoSuchFile:
2854
 
        has_contents = False
2855
 
        contents_mod = True
2856
 
        meta_mod = False
2857
 
    if has_contents is True:
2858
 
        if entry.kind != working_kind:
2859
 
            contents_mod, meta_mod = True, False
2860
 
        else:
2861
 
            cur_entry._read_tree_state(working_tree.id2path(file_id),
2862
 
                                       working_tree)
2863
 
            contents_mod, meta_mod = entry.detect_changes(cur_entry)
2864
 
            cur_entry._forget_tree_state()
2865
 
    return has_contents, contents_mod, meta_mod
2866
 
 
2867
 
 
2868
2842
def revert(working_tree, target_tree, filenames, backups=False,
2869
2843
           pb=None, change_reporter=None):
2870
2844
    """Revert a working tree's contents to those of a target tree."""
3047
3021
    pb = ui.ui_factory.nested_progress_bar()
3048
3022
    try:
3049
3023
        for n in range(10):
3050
 
            pb.update('Resolution pass', n+1, 10)
 
3024
            pb.update(gettext('Resolution pass'), n+1, 10)
3051
3025
            conflicts = tt.find_conflicts()
3052
3026
            if len(conflicts) == 0:
3053
3027
                return new_conflicts
3077
3051
                existing_file, new_file = conflict[2], conflict[1]
3078
3052
            else:
3079
3053
                existing_file, new_file = conflict[1], conflict[2]
3080
 
            new_name = tt.final_name(existing_file)+'.moved'
 
3054
            new_name = tt.final_name(existing_file) + '.moved'
3081
3055
            tt.adjust_path(new_name, final_parent, existing_file)
3082
3056
            new_conflicts.add((c_type, 'Moved existing file to',
3083
3057
                               existing_file, new_file))