/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 breezy/transform.py

  • Committer: Breezy landing bot
  • Author(s): Jelmer Vernooij
  • Date: 2018-11-16 18:59:44 UTC
  • mfrom: (7143.15.15 more-cleanups)
  • Revision ID: breezy.the.bot@gmail.com-20181116185944-biefv1sub37qfybm
Sprinkle some PEP8iness.

Merged from https://code.launchpad.net/~jelmer/brz/more-cleanups/+merge/358611

Show diffs side-by-side

added added

removed removed

Lines of Context:
77
77
 
78
78
ROOT_PARENT = "root-parent"
79
79
 
 
80
 
80
81
def unique_add(map, key, value):
81
82
    if key in map:
82
83
        raise DuplicateKey(key=key)
83
84
    map[key] = value
84
85
 
85
86
 
86
 
 
87
87
class _TransformResults(object):
88
88
    def __init__(self, modified_paths, rename_count):
89
89
        object.__init__(self)
175
175
    def _assign_id(self):
176
176
        """Produce a new tranform id"""
177
177
        new_id = "new-%s" % self._id_number
178
 
        self._id_number +=1
 
178
        self._id_number += 1
179
179
        return new_id
180
180
 
181
181
    def create_path(self, name, parent):
259
259
            self.unversion_file(old_new_root)
260
260
        # if, at this stage, root still has an old file_id, zap it so we can
261
261
        # stick a new one in.
262
 
        if (self.tree_file_id(self._new_root) is not None and
263
 
            self._new_root not in self._removed_id):
 
262
        if (self.tree_file_id(self._new_root) is not None
 
263
                and self._new_root not in self._removed_id):
264
264
            self.unversion_file(self._new_root)
265
265
        if file_id is not None:
266
266
            self.version_file(file_id, self._new_root)
425
425
        changed_ids.update(changed_kind)
426
426
        # To find entries with changed parent_ids, find parents which existed,
427
427
        # but changed file_id.
428
 
        changed_file_id = set(t for t in new_file_id if t in self._removed_id)
429
428
        # Now add all their children to the set.
430
429
        for parent_trans_id in new_file_id:
431
430
            changed_ids.update(self.iter_tree_children(parent_trans_id))
512
511
        by_parent = {}
513
512
        items = list(viewitems(self._new_parent))
514
513
        items.extend((t, self.final_parent(t))
515
 
            for t in list(self._tree_id_paths))
 
514
                     for t in list(self._tree_id_paths))
516
515
        for trans_id, parent_id in items:
517
516
            if parent_id not in by_parent:
518
517
                by_parent[parent_id] = set()
643
642
            for child_id in children:
644
643
                if self.final_file_id(child_id) is not None:
645
644
                    conflicts.append(('unversioned parent', parent_id))
646
 
                    break;
 
645
                    break
647
646
        return conflicts
648
647
 
649
648
    def _improper_versioning(self):
686
685
                continue
687
686
            if trans_id not in self._removed_contents:
688
687
                conflicts.append(('overwrite', trans_id,
689
 
                                 self.final_name(trans_id)))
 
688
                                  self.final_name(trans_id)))
690
689
        return conflicts
691
690
 
692
691
    def _duplicate_entries(self, by_parent):
713
712
                    continue
714
713
                if name == last_name:
715
714
                    conflicts.append(('duplicate', last_trans_id, trans_id,
716
 
                    name))
 
715
                                      name))
717
716
                last_name = name
718
717
                last_trans_id = trans_id
719
718
        return conflicts
903
902
        if from_versioned:
904
903
            # get data from working tree if versioned
905
904
            from_entry = next(self._tree.iter_entries_by_dir(
906
 
                    specific_files=[from_path]))[1]
 
905
                specific_files=[from_path]))[1]
907
906
            from_name = from_entry.name
908
907
            from_parent = from_entry.parent_id
909
908
        else:
990
989
            if from_kind != to_kind:
991
990
                modified = True
992
991
            elif to_kind in ('file', 'symlink') and (
993
 
                to_trans_id != from_trans_id or
994
 
                to_trans_id in self._new_contents):
 
992
                    to_trans_id != from_trans_id
 
993
                    or to_trans_id in self._new_contents):
995
994
                modified = True
996
 
            if (not modified and from_versioned == to_versioned and
997
 
                from_parent==to_parent and from_name == to_name and
998
 
                from_executable == to_executable):
 
995
            if (not modified and from_versioned == to_versioned
 
996
                and from_parent == to_parent and from_name == to_name
 
997
                    and from_executable == to_executable):
999
998
                continue
1000
999
            results.append((file_id, (from_path, to_path), modified,
1001
 
                   (from_versioned, to_versioned),
1002
 
                   (from_parent, to_parent),
1003
 
                   (from_name, to_name),
1004
 
                   (from_kind, to_kind),
1005
 
                   (from_executable, to_executable)))
 
1000
                            (from_versioned, to_versioned),
 
1001
                            (from_parent, to_parent),
 
1002
                            (from_name, to_name),
 
1003
                            (from_kind, to_kind),
 
1004
                            (from_executable, to_executable)))
1006
1005
 
1007
1006
        def path_key(t):
1008
1007
            paths = t[1]
1146
1145
                if not isinstance(content, bytes):
1147
1146
                    content = content.encode('utf-8')
1148
1147
            yield serializer.bytes_record(
1149
 
                    content, ((trans_id.encode('utf-8'), kind.encode('ascii')),))
 
1148
                content, ((trans_id.encode('utf-8'), kind.encode('ascii')),))
1150
1149
 
1151
1150
    def deserialize(self, records):
1152
1151
        """Deserialize a stored TreeTransform.
1161
1160
                          for k, v in viewitems(attribs[b'_new_name'])}
1162
1161
        self._new_parent = {k.decode('utf-8'): v.decode('utf-8')
1163
1162
                            for k, v in viewitems(attribs[b'_new_parent'])}
1164
 
        self._new_executability = {k.decode('utf-8'): bool(v)
 
1163
        self._new_executability = {
 
1164
            k.decode('utf-8'): bool(v)
1165
1165
            for k, v in viewitems(attribs[b'_new_executability'])}
1166
1166
        self._new_id = {k.decode('utf-8'): v
1167
1167
                        for k, v in viewitems(attribs[b'_new_id'])}
1175
1175
            self._tree_id_paths[trans_id] = path
1176
1176
        self._removed_id = {trans_id.decode('utf-8')
1177
1177
                            for trans_id in attribs[b'_removed_id']}
1178
 
        self._removed_contents = set(trans_id.decode('utf-8')
1179
 
                                     for trans_id in attribs[b'_removed_contents'])
1180
 
        self._non_present_ids = {k: v.decode('utf-8')
1181
 
                                 for k, v in viewitems(attribs[b'_non_present_ids'])}
 
1178
        self._removed_contents = set(
 
1179
            trans_id.decode('utf-8')
 
1180
            for trans_id in attribs[b'_removed_contents'])
 
1181
        self._non_present_ids = {
 
1182
            k: v.decode('utf-8')
 
1183
            for k, v in viewitems(attribs[b'_non_present_ids'])}
1182
1184
        for ((trans_id, kind),), content in records:
1183
1185
            trans_id = trans_id.decode('utf-8')
1184
1186
            kind = kind.decode('ascii')
1281
1283
        previous_parent = self._new_parent.get(trans_id)
1282
1284
        previous_name = self._new_name.get(trans_id)
1283
1285
        TreeTransformBase.adjust_path(self, name, parent, trans_id)
1284
 
        if (trans_id in self._limbo_files and
1285
 
            trans_id not in self._needs_rename):
 
1286
        if (trans_id in self._limbo_files
 
1287
                and trans_id not in self._needs_rename):
1286
1288
            self._rename_in_limbo([trans_id])
1287
1289
            if previous_parent != parent:
1288
1290
                self._limbo_children[previous_parent].remove(trans_id)
1370
1372
            raise errors.HardLinkNotSupported(path)
1371
1373
        try:
1372
1374
            unique_add(self._new_contents, trans_id, 'file')
1373
 
        except:
 
1375
        except BaseException:
1374
1376
            # Clean up the file, it never got registered so
1375
1377
            # TreeTransform.finalize() won't clean it up.
1376
1378
            os.unlink(name)
1556
1558
    FileMover does not delete files until it is sure that a rollback will not
1557
1559
    happen.
1558
1560
    """
 
1561
 
1559
1562
    def __init__(self, tree, pb=None):
1560
1563
        """Note: a tree_write lock is taken on the tree.
1561
1564
 
1574
1577
            osutils.ensure_empty_directory_exists(
1575
1578
                deletiondir,
1576
1579
                errors.ExistingPendingDeletion)
1577
 
        except:
 
1580
        except BaseException:
1578
1581
            tree.unlock()
1579
1582
            raise
1580
1583
 
1653
1656
        try:
1654
1657
            children = os.listdir(self._tree.abspath(path))
1655
1658
        except OSError as e:
1656
 
            if not (osutils._is_error_enotdir(e)
1657
 
                    or e.errno in (errno.ENOENT, errno.ESRCH)):
 
1659
            if not (osutils._is_error_enotdir(e) or
 
1660
                    e.errno in (errno.ENOENT, errno.ESRCH)):
1658
1661
                raise
1659
1662
            return
1660
1663
 
1691
1694
                # if it is already associated with this trans_id.
1692
1695
                elif self._case_sensitive_target:
1693
1696
                    if (self._limbo_children_names[parent].get(filename)
1694
 
                        in (trans_id, None)):
 
1697
                            in (trans_id, None)):
1695
1698
                        use_direct_path = True
1696
1699
                else:
1697
1700
                    for l_filename, l_trans_id in viewitems(
1746
1749
                self._apply_removals(mover)
1747
1750
                child_pb.update(gettext('Apply phase'), 1 + offset, 2 + offset)
1748
1751
                modified_paths = self._apply_insertions(mover)
1749
 
            except:
 
1752
            except BaseException:
1750
1753
                mover.rollback()
1751
1754
                raise
1752
1755
            else:
1767
1770
        with ui.ui_factory.nested_progress_bar() as child_pb:
1768
1771
            for num, trans_id in enumerate(self._removed_id):
1769
1772
                if (num % 10) == 0:
1770
 
                    child_pb.update(gettext('removing file'), num, total_entries)
 
1773
                    child_pb.update(gettext('removing file'),
 
1774
                                    num, total_entries)
1771
1775
                if trans_id == self._new_root:
1772
1776
                    file_id = self._tree.get_root_id()
1773
1777
                else:
1779
1783
                inventory_delta.append((path, None, file_id, None))
1780
1784
            new_path_file_ids = dict((t, self.final_file_id(t)) for p, t in
1781
1785
                                     new_paths)
1782
 
            final_kinds = {}
1783
1786
            for num, (path, trans_id) in enumerate(new_paths):
1784
1787
                if (num % 10) == 0:
1785
1788
                    child_pb.update(gettext('adding file'),
1787
1790
                file_id = new_path_file_ids[trans_id]
1788
1791
                if file_id is None:
1789
1792
                    continue
1790
 
                needs_entry = False
1791
1793
                kind = self.final_kind(trans_id)
1792
1794
                if kind is None:
1793
1795
                    kind = self._tree.stored_kind(
1794
 
                            self._tree.id2path(file_id), file_id)
 
1796
                        self._tree.id2path(file_id), file_id)
1795
1797
                parent_trans_id = self.final_parent(trans_id)
1796
1798
                parent_file_id = new_path_file_ids.get(parent_trans_id)
1797
1799
                if parent_file_id is None:
1804
1806
                        None, self._new_reference_revision[trans_id])
1805
1807
                else:
1806
1808
                    new_entry = inventory.make_entry(kind,
1807
 
                        self.final_name(trans_id),
1808
 
                        parent_file_id, file_id)
 
1809
                                                     self.final_name(trans_id),
 
1810
                                                     parent_file_id, file_id)
1809
1811
                try:
1810
1812
                    old_path = self._tree.id2path(new_entry.file_id)
1811
1813
                except errors.NoSuchId:
1837
1839
                if trans_id in self._removed_contents:
1838
1840
                    delete_path = os.path.join(self._deletiondir, trans_id)
1839
1841
                    mover.pre_delete(full_path, delete_path)
1840
 
                elif (trans_id in self._new_name
1841
 
                      or trans_id in self._new_parent):
 
1842
                elif (trans_id in self._new_name or
 
1843
                      trans_id in self._new_parent):
1842
1844
                    try:
1843
1845
                        mover.rename(full_path, self._limbo_name(trans_id))
1844
1846
                    except errors.TransformRenameFailed as e:
1859
1861
        """
1860
1862
        new_paths = self.new_paths(filesystem_only=True)
1861
1863
        modified_paths = []
1862
 
        new_path_file_ids = dict((t, self.final_file_id(t)) for p, t in
1863
 
                                 new_paths)
1864
1864
        with ui.ui_factory.nested_progress_bar() as child_pb:
1865
1865
            for num, (path, trans_id) in enumerate(new_paths):
1866
1866
                if (num % 10) == 0:
1867
 
                    child_pb.update(gettext('adding file'), num, len(new_paths))
 
1867
                    child_pb.update(gettext('adding file'),
 
1868
                                    num, len(new_paths))
1868
1869
                full_path = self._tree.abspath(path)
1869
1870
                if trans_id in self._needs_rename:
1870
1871
                    try:
1878
1879
                    # TODO: if trans_id in self._observed_sha1s, we should
1879
1880
                    #       re-stat the final target, since ctime will be
1880
1881
                    #       updated by the change.
1881
 
                if (trans_id in self._new_contents or
1882
 
                    self.path_changed(trans_id)):
 
1882
                if (trans_id in self._new_contents
 
1883
                        or self.path_changed(trans_id)):
1883
1884
                    if trans_id in self._new_contents:
1884
1885
                        modified_paths.append(full_path)
1885
1886
                if trans_id in self._new_executability:
1959
1960
            return
1960
1961
        try:
1961
1962
            entry = next(self._tree.iter_entries_by_dir(
1962
 
                    specific_files=[path]))[1]
 
1963
                specific_files=[path]))[1]
1963
1964
        except StopIteration:
1964
1965
            return
1965
1966
        children = getattr(entry, 'children', {})
2069
2070
        if file_id in self._transform._r_new_id:
2070
2071
            return True
2071
2072
        elif file_id in {self._transform.tree_file_id(trans_id) for
2072
 
            trans_id in self._transform._removed_id}:
 
2073
                         trans_id in self._transform._removed_id}:
2073
2074
            return False
2074
2075
        else:
2075
2076
            return fallback_check(file_id)
2146
2147
            file_id = self._transform.final_file_id(trans_id)
2147
2148
            if file_id is None:
2148
2149
                continue
2149
 
            if (specific_files is not None and
2150
 
                self._final_paths.get_path(trans_id) not in specific_files):
 
2150
            if (specific_files is not None
 
2151
                    and self._final_paths.get_path(trans_id) not in specific_files):
2151
2152
                continue
2152
2153
            kind = self._transform.final_kind(trans_id)
2153
2154
            if kind is None:
2191
2192
        # position.
2192
2193
        ordered_ids = self._list_files_by_dir()
2193
2194
        for entry, trans_id in self._make_inv_entries(ordered_ids,
2194
 
            specific_files):
 
2195
                                                      specific_files):
2195
2196
            yield self._final_paths.get_path(trans_id), entry
2196
2197
 
2197
2198
    def _iter_entries_for_dir(self, dir_path):
2227
2228
        else:
2228
2229
            if from_dir is None and include_root is True:
2229
2230
                root_entry = inventory.make_entry('directory', '',
2230
 
                    ROOT_PARENT, self.get_root_id())
 
2231
                                                  ROOT_PARENT, self.get_root_id())
2231
2232
                yield '', 'V', 'directory', root_entry.file_id, root_entry
2232
2233
            entries = self._iter_entries_for_dir(from_dir or '')
2233
2234
            for path, entry in entries:
2255
2256
            raise errors.NoSuchFile(path)
2256
2257
        if not self._content_change(file_id):
2257
2258
            return self._transform._tree.get_file_mtime(
2258
 
                    self._transform._tree.id2path(file_id))
 
2259
                self._transform._tree.id2path(file_id))
2259
2260
        trans_id = self._path2trans_id(path)
2260
2261
        return self._stat_limbo_file(trans_id).st_mtime
2261
2262
 
2354
2355
        return kind, size, executable, link_or_sha1
2355
2356
 
2356
2357
    def iter_changes(self, from_tree, include_unchanged=False,
2357
 
                      specific_files=None, pb=None, extra_trees=None,
2358
 
                      require_versioned=True, want_unversioned=False):
 
2358
                     specific_files=None, pb=None, extra_trees=None,
 
2359
                     require_versioned=True, want_unversioned=False):
2359
2360
        """See InterTree.iter_changes.
2360
2361
 
2361
2362
        This has a fast path that is only used when the from_tree matches
2362
2363
        the transform tree, and no fancy options are supplied.
2363
2364
        """
2364
 
        if (from_tree is not self._transform._tree or include_unchanged or
2365
 
            specific_files or want_unversioned):
 
2365
        if (from_tree is not self._transform._tree or include_unchanged
 
2366
                or specific_files or want_unversioned):
2366
2367
            return tree.InterTree(from_tree, self).iter_changes(
2367
2368
                include_unchanged=include_unchanged,
2368
2369
                specific_files=specific_files,
2400
2401
            get_old = (kind[0] == 'file' and versioned[0])
2401
2402
        if get_old:
2402
2403
            old_annotation = self._transform._tree.annotate_iter(
2403
 
                    path, default_revision=default_revision)
 
2404
                path, default_revision=default_revision)
2404
2405
        else:
2405
2406
            old_annotation = []
2406
2407
        if changes is None:
2440
2441
                path_from_root = self._final_paths.get_path(child_id)
2441
2442
                basename = self._transform.final_name(child_id)
2442
2443
                file_id = self._transform.final_file_id(child_id)
2443
 
                kind  = self._transform.final_kind(child_id)
 
2444
                kind = self._transform.final_kind(child_id)
2444
2445
                if kind is not None:
2445
2446
                    versioned_kind = kind
2446
2447
                else:
2447
2448
                    kind = 'unknown'
2448
2449
                    versioned_kind = self._transform._tree.stored_kind(
2449
 
                            self._transform._tree.id2path(file_id))
 
2450
                        self._transform._tree.id2path(file_id))
2450
2451
                if versioned_kind == 'directory':
2451
2452
                    subdirs.append(child_id)
2452
2453
                children.append((path_from_root, basename, kind, None,
2481
2482
    The underlying tree must not be manipulated between calls, or else
2482
2483
    the results will likely be incorrect.
2483
2484
    """
 
2485
 
2484
2486
    def __init__(self, transform):
2485
2487
        object.__init__(self)
2486
2488
        self._known_paths = {}
2506
2508
        return [(self.get_path(t), t) for t in trans_ids]
2507
2509
 
2508
2510
 
2509
 
 
2510
2511
def topology_sorted_ids(tree):
2511
2512
    """Determine the topological order of the ids in a tree"""
2512
2513
    file_ids = list(tree)
2593
2594
                for dir, files in wt.walkdirs():
2594
2595
                    existing_files.update(f[0] for f in files)
2595
2596
            for num, (tree_path, entry) in \
2596
 
                enumerate(tree.iter_entries_by_dir()):
2597
 
                pb.update(gettext("Building tree"), num - len(deferred_contents), total)
 
2597
                    enumerate(tree.iter_entries_by_dir()):
 
2598
                pb.update(gettext("Building tree"), num
 
2599
                          - len(deferred_contents), total)
2598
2600
                if entry.parent_id is None:
2599
2601
                    continue
2600
2602
                reparent = False
2611
2613
                            pass
2612
2614
                        else:
2613
2615
                            divert.add(file_id)
2614
 
                    if (file_id not in divert and
2615
 
                        _content_match(tree, entry, tree_path, file_id, kind,
2616
 
                        target_path)):
 
2616
                    if (file_id not in divert
 
2617
                        and _content_match(tree, entry, tree_path, file_id, kind,
 
2618
                                       target_path)):
2617
2619
                        tt.delete_contents(tt.trans_id_tree_path(tree_path))
2618
2620
                        if kind == 'directory':
2619
2621
                            reparent = True
2627
2629
                    executable = tree.is_executable(tree_path)
2628
2630
                    if executable:
2629
2631
                        tt.set_executability(executable, trans_id)
2630
 
                    trans_data = (trans_id, file_id, tree_path, entry.text_sha1)
 
2632
                    trans_data = (trans_id, file_id,
 
2633
                                  tree_path, entry.text_sha1)
2631
2634
                    deferred_contents.append((tree_path, trans_data))
2632
2635
                else:
2633
2636
                    file_trans_id[file_id] = new_by_entry(
2634
 
                            tree_path, tt, entry, parent_id, tree)
 
2637
                        tree_path, tt, entry, parent_id, tree)
2635
2638
                if reparent:
2636
2639
                    new_trans_id = file_trans_id[file_id]
2637
2640
                    old_parent = tt.trans_id_tree_path(tree_path)
2641
2644
                          accelerator_tree, hardlink)
2642
2645
        pp.next_phase()
2643
2646
        divert_trans = set(file_trans_id[f] for f in divert)
2644
 
        resolver = lambda t, c: resolve_checkout(t, c, divert_trans)
 
2647
 
 
2648
        def resolver(t, c):
 
2649
            return resolve_checkout(t, c, divert_trans)
2645
2650
        raw_conflicts = resolve_conflicts(tt, pass_func=resolver)
2646
2651
        if len(raw_conflicts) > 0:
2647
2652
            precomputed_delta = None
2680
2685
            accelerator_path = unchanged.get(tree_path)
2681
2686
            if accelerator_path is None:
2682
2687
                new_desired_files.append((tree_path,
2683
 
                    (trans_id, file_id, tree_path, text_sha1)))
 
2688
                                          (trans_id, file_id, tree_path, text_sha1)))
2684
2689
                continue
2685
2690
            pb.update(gettext('Adding file contents'), count + offset, total)
2686
2691
            if hardlink:
2692
2697
                    if wt.supports_content_filtering():
2693
2698
                        filters = wt._content_filter_stack(tree_path)
2694
2699
                        chunks = filtered_output_bytes(chunks, filters,
2695
 
                            ContentFilterContext(tree_path, tree))
 
2700
                                                       ContentFilterContext(tree_path, tree))
2696
2701
                    tt.create_file(chunks, trans_id, sha1=text_sha1)
2697
2702
            count += 1
2698
2703
        offset += count
2701
2706
        if wt.supports_content_filtering():
2702
2707
            filters = wt._content_filter_stack(tree_path)
2703
2708
            contents = filtered_output_bytes(contents, filters,
2704
 
                ContentFilterContext(tree_path, tree))
 
2709
                                             ContentFilterContext(tree_path, tree))
2705
2710
        tt.create_file(contents, trans_id, sha1=text_sha1)
2706
2711
        pb.update(gettext('Adding file contents'), count + offset, total)
2707
2712
 
2725
2730
        return True
2726
2731
    if entry.kind == "file":
2727
2732
        with open(target_path, 'rb') as f1, \
2728
 
             tree.get_file(tree_path) as f2:
 
2733
                 tree.get_file(tree_path) as f2:
2729
2734
            if osutils.compare_files(f1, f2):
2730
2735
                return True
2731
2736
    elif entry.kind == "symlink":
2752
2757
        # resolved
2753
2758
        final_parent = tt.final_parent(old_file)
2754
2759
        if new_file in divert:
2755
 
            new_name = tt.final_name(old_file)+'.diverted'
 
2760
            new_name = tt.final_name(old_file) + '.diverted'
2756
2761
            tt.adjust_path(new_name, final_parent, new_file)
2757
2762
            new_conflicts.add((c_type, 'Diverted to',
2758
2763
                               new_file, old_file))
2759
2764
        else:
2760
 
            new_name = tt.final_name(old_file)+'.moved'
 
2765
            new_name = tt.final_name(old_file) + '.moved'
2761
2766
            tt.adjust_path(new_name, final_parent, old_file)
2762
2767
            new_conflicts.add((c_type, 'Moved existing file to',
2763
2768
                               old_file, new_file))
2772
2777
        with tree.get_file(path) as f:
2773
2778
            executable = tree.is_executable(path)
2774
2779
            return tt.new_file(
2775
 
                    name, parent_id, osutils.file_iterator(f), entry.file_id,
2776
 
                    executable)
 
2780
                name, parent_id, osutils.file_iterator(f), entry.file_id,
 
2781
                executable)
2777
2782
    elif kind in ('directory', 'tree-reference'):
2778
2783
        trans_id = tt.new_directory(name, parent_id, entry.file_id)
2779
2784
        if kind == 'tree-reference':
2787
2792
 
2788
2793
 
2789
2794
def create_from_tree(tt, trans_id, tree, path, file_id=None, chunks=None,
2790
 
    filter_tree_path=None):
 
2795
                     filter_tree_path=None):
2791
2796
    """Create new file contents according to tree contents.
2792
2797
 
2793
2798
    :param filter_tree_path: the tree path to use to lookup
2807
2812
            wt = tt._tree
2808
2813
            if wt.supports_content_filtering() and filter_tree_path is not None:
2809
2814
                filters = wt._content_filter_stack(filter_tree_path)
2810
 
                chunks = filtered_output_bytes(chunks, filters,
 
2815
                chunks = filtered_output_bytes(
 
2816
                    chunks, filters,
2811
2817
                    ContentFilterContext(filter_tree_path, tree))
2812
2818
            tt.create_file(chunks, trans_id)
2813
2819
        finally:
2859
2865
                                      child_pb, filenames, backups,
2860
2866
                                      merge_modified, basis_tree)
2861
2867
    with ui.ui_factory.nested_progress_bar() as child_pb:
2862
 
        raw_conflicts = resolve_conflicts(tt, child_pb,
2863
 
            lambda t, c: conflict_pass(t, c, target_tree))
 
2868
        raw_conflicts = resolve_conflicts(
 
2869
            tt, child_pb, lambda t, c: conflict_pass(t, c, target_tree))
2864
2870
    conflicts = cook_conflicts(raw_conflicts, tt)
2865
2871
    return conflicts, merge_modified
2866
2872
 
2873
2879
    # than the target changes relative to the working tree. Because WT4 has an
2874
2880
    # optimizer to compare itself to a target, but no optimizer for the
2875
2881
    # reverse.
2876
 
    change_list = working_tree.iter_changes(target_tree,
2877
 
        specific_files=specific_files, pb=pb)
 
2882
    change_list = working_tree.iter_changes(
 
2883
        target_tree, specific_files=specific_files, pb=pb)
2878
2884
    if not target_tree.is_versioned(u''):
2879
2885
        skip_root = True
2880
2886
    else:
2882
2888
    try:
2883
2889
        deferred_files = []
2884
2890
        for id_num, (file_id, path, changed_content, versioned, parent, name,
2885
 
                kind, executable) in enumerate(change_list):
 
2891
                     kind, executable) in enumerate(change_list):
2886
2892
            target_path, wt_path = path
2887
2893
            target_versioned, wt_versioned = versioned
2888
2894
            target_parent, wt_parent = parent
2904
2910
                        if basis_tree is None:
2905
2911
                            basis_tree = working_tree.basis_tree()
2906
2912
                            basis_tree.lock_read()
2907
 
                        basis_path = find_previous_path(working_tree, basis_tree, wt_path)
 
2913
                        basis_path = find_previous_path(
 
2914
                            working_tree, basis_tree, wt_path)
2908
2915
                        if basis_path is None:
2909
2916
                            if target_kind is None and not target_versioned:
2910
2917
                                keep_content = True
2931
2938
                    tt.create_directory(trans_id)
2932
2939
                    if target_kind == 'tree-reference':
2933
2940
                        revision = target_tree.get_reference_revision(
2934
 
                                target_path)
 
2941
                            target_path)
2935
2942
                        tt.set_tree_reference(revision, trans_id)
2936
2943
                elif target_kind == 'symlink':
2937
2944
                    tt.create_symlink(target_tree.get_symlink_target(
2938
 
                            target_path), trans_id)
 
2945
                        target_path), trans_id)
2939
2946
                elif target_kind == 'file':
2940
 
                    deferred_files.append((target_path, (trans_id, mode_id, file_id)))
 
2947
                    deferred_files.append(
 
2948
                        (target_path, (trans_id, mode_id, file_id)))
2941
2949
                    if basis_tree is None:
2942
2950
                        basis_tree = working_tree.basis_tree()
2943
2951
                        basis_tree.lock_read()
2944
2952
                    new_sha1 = target_tree.get_file_sha1(target_path)
2945
2953
                    basis_path = find_previous_path(target_tree, basis_tree, target_path)
2946
2954
                    if (basis_path is not None and
2947
 
                        new_sha1 == basis_tree.get_file_sha1(basis_path)):
 
2955
                            new_sha1 == basis_tree.get_file_sha1(basis_path)):
2948
2956
                        if file_id in merge_modified:
2949
2957
                            del merge_modified[file_id]
2950
2958
                    else:
2959
2967
                tt.version_file(file_id, trans_id)
2960
2968
            if wt_versioned and not target_versioned:
2961
2969
                tt.unversion_file(trans_id)
2962
 
            if (target_name is not None and
2963
 
                (wt_name != target_name or wt_parent != target_parent)):
 
2970
            if (target_name is not None
 
2971
                    and (wt_name != target_name or wt_parent != target_parent)):
2964
2972
                if target_name == '' and target_parent is None:
2965
2973
                    parent_trans = ROOT_PARENT
2966
2974
                else:
2973
2981
                tt.set_executability(target_executable, trans_id)
2974
2982
        if working_tree.supports_content_filtering():
2975
2983
            for (trans_id, mode_id, file_id), bytes in (
2976
 
                target_tree.iter_files_bytes(deferred_files)):
 
2984
                    target_tree.iter_files_bytes(deferred_files)):
2977
2985
                # We're reverting a tree to the target tree so using the
2978
2986
                # target tree to find the file path seems the best choice
2979
2987
                # here IMO - Ian C 27/Oct/2009
2980
2988
                filter_tree_path = target_tree.id2path(file_id)
2981
2989
                filters = working_tree._content_filter_stack(filter_tree_path)
2982
 
                bytes = filtered_output_bytes(bytes, filters,
 
2990
                bytes = filtered_output_bytes(
 
2991
                    bytes, filters,
2983
2992
                    ContentFilterContext(filter_tree_path, working_tree))
2984
2993
                tt.create_file(bytes, trans_id, mode_id)
2985
2994
        else:
2986
2995
            for (trans_id, mode_id, file_id), bytes in target_tree.iter_files_bytes(
2987
 
                deferred_files):
 
2996
                    deferred_files):
2988
2997
                tt.create_file(bytes, trans_id, mode_id)
2989
2998
        tt.fixup_new_roots()
2990
2999
    finally:
3000
3009
    new_conflicts = set()
3001
3010
    with ui.ui_factory.nested_progress_bar() as pb:
3002
3011
        for n in range(10):
3003
 
            pb.update(gettext('Resolution pass'), n+1, 10)
 
3012
            pb.update(gettext('Resolution pass'), n + 1, 10)
3004
3013
            conflicts = tt.find_conflicts()
3005
3014
            if len(conflicts) == 0:
3006
3015
                return new_conflicts
3099
3108
            # special-case the other tree root (move its children instead)
3100
3109
            if path_tree and path_tree.path2id('') == file_id:
3101
3110
                    # This is the root entry, skip it
3102
 
                    continue
 
3111
                continue
3103
3112
            tt.version_file(file_id, conflict[1])
3104
3113
            new_conflicts.add((c_type, 'Versioned directory', conflict[1]))
3105
3114
        elif c_type == 'non-directory parent':
3108
3117
            parent_name = tt.final_name(parent_id)
3109
3118
            parent_file_id = tt.final_file_id(parent_id)
3110
3119
            new_parent_id = tt.new_directory(parent_name + '.new',
3111
 
                parent_parent, parent_file_id)
 
3120
                                             parent_parent, parent_file_id)
3112
3121
            _reparent_transform_children(tt, parent_id, new_parent_id)
3113
3122
            if parent_file_id is not None:
3114
3123
                tt.unversion_file(parent_id)
3182
3191
            except OSError as e:
3183
3192
                raise errors.TransformRenameFailed(to, from_, str(e), e.errno)
3184
3193
        # after rollback, don't reuse _FileMover
3185
 
        past_renames = None
3186
 
        pending_deletions = None
 
3194
        self.past_renames = None
 
3195
        self.pending_deletions = None
3187
3196
 
3188
3197
    def apply_deletions(self):
3189
3198
        """Apply all marked deletions"""
3190
3199
        for path in self.pending_deletions:
3191
3200
            delete_any(path)
3192
3201
        # after apply_deletions, don't reuse _FileMover
3193
 
        past_renames = None
3194
 
        pending_deletions = None
 
3202
        self.past_renames = None
 
3203
        self.pending_deletions = None
3195
3204
 
3196
3205
 
3197
3206
def link_tree(target_tree, source_tree):
3204
3213
    try:
3205
3214
        for (file_id, paths, changed_content, versioned, parent, name, kind,
3206
3215
             executable) in target_tree.iter_changes(source_tree,
3207
 
             include_unchanged=True):
 
3216
                                                     include_unchanged=True):
3208
3217
            if changed_content:
3209
3218
                continue
3210
3219
            if kind != ('file', 'file'):