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

  • Committer: Matt Nordhoff
  • Date: 2009-04-04 02:50:01 UTC
  • mfrom: (4253 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4256.
  • Revision ID: mnordhoff@mattnordhoff.com-20090404025001-z1403k0tatmc8l91
Merge bzr.dev, fixing conflicts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
17
import os
18
18
import errno
36
36
                           ReusingTransform, NotVersionedError, CantMoveRoot,
37
37
                           ExistingLimbo, ImmortalLimbo, NoFinalPath,
38
38
                           UnableCreateSymlink)
 
39
from bzrlib.filters import filtered_output_bytes, ContentFilterContext
39
40
from bzrlib.inventory import InventoryEntry
40
41
from bzrlib.osutils import (
41
42
    delete_any,
233
234
 
234
235
    def adjust_root_path(self, name, parent):
235
236
        """Emulate moving the root by moving all children, instead.
236
 
        
 
237
 
237
238
        We do this by undoing the association of root's transaction id with the
238
239
        current tree.  This allows us to create a new directory with that
239
 
        transaction id.  We unversion the root directory and version the 
 
240
        transaction id.  We unversion the root directory and version the
240
241
        physically new directory, and hope someone versions the tree root
241
242
        later.
242
243
        """
245
246
        # force moving all children of root
246
247
        for child_id in self.iter_tree_children(old_root):
247
248
            if child_id != parent:
248
 
                self.adjust_path(self.final_name(child_id), 
 
249
                self.adjust_path(self.final_name(child_id),
249
250
                                 self.final_parent(child_id), child_id)
250
251
            file_id = self.final_file_id(child_id)
251
252
            if file_id is not None:
252
253
                self.unversion_file(child_id)
253
254
            self.version_file(file_id, child_id)
254
 
        
 
255
 
255
256
        # the physical root needs a new transaction id
256
257
        self._tree_path_ids.pop("")
257
258
        self._tree_id_paths.pop(old_root)
265
266
 
266
267
    def trans_id_tree_file_id(self, inventory_id):
267
268
        """Determine the transaction id of a working tree file.
268
 
        
 
269
 
269
270
        This reflects only files that already exist, not ones that will be
270
271
        added by transactions.
271
272
        """
335
336
        """Schedule creation of a new file.
336
337
 
337
338
        See also new_file.
338
 
        
 
339
 
339
340
        Contents is an iterator of strings, all of which will be written
340
341
        to the target destination.
341
342
 
404
405
 
405
406
    def create_directory(self, trans_id):
406
407
        """Schedule creation of a new directory.
407
 
        
 
408
 
408
409
        See also new_directory.
409
410
        """
410
411
        os.mkdir(self._limbo_name(trans_id))
535
536
 
536
537
    def final_kind(self, trans_id):
537
538
        """Determine the final file kind, after any changes applied.
538
 
        
 
539
 
539
540
        Raises NoSuchFile if the file does not exist/has no contents.
540
541
        (It is conceivable that a path would be created without the
541
542
        corresponding contents insertion command)
561
562
 
562
563
    def final_file_id(self, trans_id):
563
564
        """Determine the file id after any changes are applied, or None.
564
 
        
 
565
 
565
566
        None indicates that the file will not be versioned after changes are
566
567
        applied.
567
568
        """
606
607
 
607
608
    def by_parent(self):
608
609
        """Return a map of parent: children for known parents.
609
 
        
 
610
 
610
611
        Only new paths and parents of tree files with assigned ids are used.
611
612
        """
612
613
        by_parent = {}
613
614
        items = list(self._new_parent.iteritems())
614
 
        items.extend((t, self.final_parent(t)) for t in 
 
615
        items.extend((t, self.final_parent(t)) for t in
615
616
                      self._tree_id_paths.keys())
616
617
        for trans_id, parent_id in items:
617
618
            if parent_id not in by_parent:
652
653
        removed.  This is a necessary first step in detecting conflicts.
653
654
        """
654
655
        parents = self.by_parent().keys()
655
 
        parents.extend([t for t in self._removed_contents if 
 
656
        parents.extend([t for t in self._removed_contents if
656
657
                        self.tree_kind(t) == 'directory'])
657
658
        for trans_id in self._removed_id:
658
659
            file_id = self.tree_file_id(trans_id)
745
746
 
746
747
    def _improper_versioning(self):
747
748
        """Cannot version a file with no contents, or a bad type.
748
 
        
 
749
 
749
750
        However, existing entries with no contents are okay.
750
751
        """
751
752
        conflicts = []
761
762
 
762
763
    def _executability_conflicts(self):
763
764
        """Check for bad executability changes.
764
 
        
 
765
 
765
766
        Only versioned files may have their executability set, because
766
767
        1. only versioned entries can have executability under windows
767
768
        2. only files can be executable.  (The execute bit on a directory
936
937
            self.version_file(file_id, trans_id)
937
938
        return trans_id
938
939
 
939
 
    def new_file(self, name, parent_id, contents, file_id=None, 
 
940
    def new_file(self, name, parent_id, contents, file_id=None,
940
941
                 executable=None):
941
942
        """Convenience method to create files.
942
 
        
 
943
 
943
944
        name is the name of the file to create.
944
945
        parent_id is the transaction id of the parent directory of the file.
945
946
        contents is an iterator of bytestrings, which will be used to produce
965
966
        """
966
967
        trans_id = self._new_entry(name, parent_id, file_id)
967
968
        self.create_directory(trans_id)
968
 
        return trans_id 
 
969
        return trans_id
969
970
 
970
971
    def new_symlink(self, name, parent_id, target, file_id=None):
971
972
        """Convenience method to create symbolic link.
972
 
        
 
973
 
973
974
        name is the name of the symlink to create.
974
975
        parent_id is the transaction id of the parent directory of the symlink.
975
976
        target is a bytestring of the target of the symlink.
1845
1846
                size = None
1846
1847
                executable = None
1847
1848
            if kind == 'symlink':
1848
 
                link_or_sha1 = os.readlink(limbo_name)
 
1849
                link_or_sha1 = os.readlink(limbo_name).decode(osutils._fs_enc)
1849
1850
        if supports_executable():
1850
1851
            executable = tt._new_executability.get(trans_id, executable)
1851
1852
        return kind, size, executable, link_or_sha1
2000
2001
def build_tree(tree, wt, accelerator_tree=None, hardlink=False,
2001
2002
               delta_from_tree=False):
2002
2003
    """Create working tree for a branch, using a TreeTransform.
2003
 
    
 
2004
 
2004
2005
    This function should be used on empty trees, having a tree root at most.
2005
2006
    (see merge and revert functionality for working with existing trees)
2006
2007
 
2007
2008
    Existing files are handled like so:
2008
 
    
 
2009
 
2009
2010
    - Existing bzrdirs take precedence over creating new items.  They are
2010
2011
      created as '%s.diverted' % name.
2011
2012
    - Otherwise, if the content on disk matches the content we are building,
2113
2114
                    executable = tree.is_executable(file_id, tree_path)
2114
2115
                    if executable:
2115
2116
                        tt.set_executability(executable, trans_id)
2116
 
                    deferred_contents.append((file_id, trans_id))
 
2117
                    trans_data = (trans_id, tree_path)
 
2118
                    deferred_contents.append((file_id, trans_data))
2117
2119
                else:
2118
2120
                    file_trans_id[file_id] = new_by_entry(tt, entry, parent_id,
2119
2121
                                                          tree)
2150
2152
def _create_files(tt, tree, desired_files, pb, offset, accelerator_tree,
2151
2153
                  hardlink):
2152
2154
    total = len(desired_files) + offset
 
2155
    wt = tt._tree
2153
2156
    if accelerator_tree is None:
2154
2157
        new_desired_files = desired_files
2155
2158
    else:
2158
2161
                         in iter if not (c or e[0] != e[1]))
2159
2162
        new_desired_files = []
2160
2163
        count = 0
2161
 
        for file_id, trans_id in desired_files:
 
2164
        for file_id, (trans_id, tree_path) in desired_files:
2162
2165
            accelerator_path = unchanged.get(file_id)
2163
2166
            if accelerator_path is None:
2164
 
                new_desired_files.append((file_id, trans_id))
 
2167
                new_desired_files.append((file_id, (trans_id, tree_path)))
2165
2168
                continue
2166
2169
            pb.update('Adding file contents', count + offset, total)
2167
2170
            if hardlink:
2169
2172
                                   trans_id)
2170
2173
            else:
2171
2174
                contents = accelerator_tree.get_file(file_id, accelerator_path)
 
2175
                if wt.supports_content_filtering():
 
2176
                    filters = wt._content_filter_stack(tree_path)
 
2177
                    contents = filtered_output_bytes(contents, filters,
 
2178
                        ContentFilterContext(tree_path, tree))
2172
2179
                try:
2173
2180
                    tt.create_file(contents, trans_id)
2174
2181
                finally:
2175
 
                    contents.close()
 
2182
                    try:
 
2183
                        contents.close()
 
2184
                    except AttributeError:
 
2185
                        # after filtering, contents may no longer be file-like
 
2186
                        pass
2176
2187
            count += 1
2177
2188
        offset += count
2178
 
    for count, (trans_id, contents) in enumerate(tree.iter_files_bytes(
2179
 
                                                 new_desired_files)):
 
2189
    for count, ((trans_id, tree_path), contents) in enumerate(
 
2190
            tree.iter_files_bytes(new_desired_files)):
 
2191
        if wt.supports_content_filtering():
 
2192
            filters = wt._content_filter_stack(tree_path)
 
2193
            contents = filtered_output_bytes(contents, filters,
 
2194
                ContentFilterContext(tree_path, tree))
2180
2195
        tt.create_file(contents, trans_id)
2181
2196
        pb.update('Adding file contents', count + offset, total)
2182
2197
 
2242
2257
    if kind == 'file':
2243
2258
        contents = tree.get_file(entry.file_id).readlines()
2244
2259
        executable = tree.is_executable(entry.file_id)
2245
 
        return tt.new_file(name, parent_id, contents, entry.file_id, 
 
2260
        return tt.new_file(name, parent_id, contents, entry.file_id,
2246
2261
                           executable)
2247
2262
    elif kind in ('directory', 'tree-reference'):
2248
2263
        trans_id = tt.new_directory(name, parent_id, entry.file_id)
2249
2264
        if kind == 'tree-reference':
2250
2265
            tt.set_tree_reference(entry.reference_revision, trans_id)
2251
 
        return trans_id 
 
2266
        return trans_id
2252
2267
    elif kind == 'symlink':
2253
2268
        target = tree.get_symlink_target(entry.file_id)
2254
2269
        return tt.new_symlink(name, parent_id, target, entry.file_id)
2333
2348
        if entry.kind != working_kind:
2334
2349
            contents_mod, meta_mod = True, False
2335
2350
        else:
2336
 
            cur_entry._read_tree_state(working_tree.id2path(file_id), 
 
2351
            cur_entry._read_tree_state(working_tree.id2path(file_id),
2337
2352
                                       working_tree)
2338
2353
            contents_mod, meta_mod = entry.detect_changes(cur_entry)
2339
2354
            cur_entry._forget_tree_state()
2528
2543
                existing_file, new_file = conflict[1], conflict[2]
2529
2544
            new_name = tt.final_name(existing_file)+'.moved'
2530
2545
            tt.adjust_path(new_name, final_parent, existing_file)
2531
 
            new_conflicts.add((c_type, 'Moved existing file to', 
 
2546
            new_conflicts.add((c_type, 'Moved existing file to',
2532
2547
                               existing_file, new_file))
2533
2548
        elif c_type == 'parent loop':
2534
2549
            # break the loop by undoing one of the ops that caused the loop
2538
2553
            new_conflicts.add((c_type, 'Cancelled move', cur,
2539
2554
                               tt.final_parent(cur),))
2540
2555
            tt.adjust_path(tt.final_name(cur), tt.get_tree_parent(cur), cur)
2541
 
            
 
2556
 
2542
2557
        elif c_type == 'missing parent':
2543
2558
            trans_id = conflict[1]
2544
2559
            try:
2545
2560
                tt.cancel_deletion(trans_id)
2546
 
                new_conflicts.add(('deleting parent', 'Not deleting', 
 
2561
                new_conflicts.add(('deleting parent', 'Not deleting',
2547
2562
                                   trans_id))
2548
2563
            except KeyError:
2549
2564
                create = True
2614
2629
        if len(conflict) == 3:
2615
2630
            yield Conflict.factory(c_type, action=action, path=modified_path,
2616
2631
                                     file_id=modified_id)
2617
 
             
 
2632
 
2618
2633
        else:
2619
2634
            conflicting_path = fp.get_path(conflict[3])
2620
2635
            conflicting_id = tt.final_file_id(conflict[3])
2621
2636
            yield Conflict.factory(c_type, action=action, path=modified_path,
2622
 
                                   file_id=modified_id, 
 
2637
                                   file_id=modified_id,
2623
2638
                                   conflict_path=conflicting_path,
2624
2639
                                   conflict_file_id=conflicting_id)
2625
2640