Changeset 1536 in tailor for vcpx/repository/darcs/target.py


Ignore:
Timestamp:
05/23/08 22:18:56 (5 years ago)
Author:
lele@…
Hash name:
20080523201856-97f81-c04d8df6320a24983c6df55ff2fd41b5e3bf04fa
Message:

Write directly into the pending file instead of using darcs commands
This is may be a dirty trick, or simply a clever idea: it allows the
backend to ignore the fact that the source already has
moved/deleted/renamed stuff around. It now just takes note of what
happend, and thus is able to handle difficult cases such as

$ bzr mv A B
$ touch A
$ bzr add A
File:
1 edited

Legend:

Unmodified
Added
Removed
  • vcpx/repository/darcs/target.py

    r1519 r1536  
    2929    A target working directory under ``darcs``. 
    3030    """ 
    31  
    32     def _addPathnames(self, names): 
    33         """ 
    34         Add some new filesystem objects. 
    35         """ 
    36  
    37         cmd = self.repository.command("add", "--case-ok", "--not-recursive", 
    38                                       "--quiet") 
    39         add = ExternalCommand(cwd=self.repository.basedir, command=cmd) 
    40         output = add.execute(names, stdout=PIPE, stderr=STDOUT)[0] 
    41         if add.exit_status: 
    42             self.log.warning("%s returned status %d, saying %s", 
    43                              str(add), add.exit_status, output.read()) 
    4431 
    4532    def _addSubtree(self, subdir): 
     
    10592                    "Changes left in working dir after commit:\n%s" % output.read()) 
    10693 
    107     def _removePathnames(self, names): 
    108         """ 
    109         Remove some filesystem object. 
    110         """ 
    111  
    112         from os.path import join, exists 
    113  
    114         # darcs raises status 512 when it does not find the entry, 
    115         # removed by source. Since sometime a directory is left there 
    116         # because it's not empty, darcs fails. So, do an explicit 
    117         # remove on items that are still there. 
    118  
    119         c = ExternalCommand(cwd=self.repository.basedir, 
    120                             command=self.repository.command("remove")) 
    121         existing = [n for n in names if exists(join(self.repository.basedir, n))] 
    122         if existing: 
    123             output = c.execute(existing, stdout=PIPE, stderr=STDOUT)[0] 
    124             if c.exit_status: 
    125                 self.log.warning("%s returned status %d, saying %s", 
    126                                  str(c), c.exit_status, output.read()) 
    127  
    128     def _renamePathname(self, oldname, newname): 
    129         """ 
    130         Rename a filesystem object. 
    131         """ 
    132  
    133         cmd = self.repository.command("mv") 
    134         mv = ExternalCommand(cwd=self.repository.basedir, command=cmd) 
    135         output = mv.execute(oldname, newname, stdout=PIPE, stderr=STDOUT)[0] 
    136         if mv.exit_status: 
    137             self.log.warning("%s returned status %d, saying %s", 
    138                              str(mv), mv.exit_status, output.read()) 
     94    def _replayChangesetEntries(self, changeset): 
     95        """ 
     96        Instead of using the "darcs mv" command, manually add 
     97        the rename to the pending file: this is a dirty trick, that 
     98        allows darcs to handle the case when the source changeset 
     99        is something like:: 
     100          $ bzr mv A B 
     101          $ touch A 
     102          $ bzr add A 
     103        where A is actually replaced, and old A is now B. Since by the 
     104        time the changeset gets replayed, the source has already replaced 
     105        A with its new content, darcs would move the *wrong* A to B... 
     106        """ 
     107 
     108        from os.path import join 
     109 
     110        # The "_darcs/patches/pending" file is basically a patch containing 
     111        # only the changes (hunks, adds...) not yet recorded by darcs: it does 
     112        # contain either a single change (that is, exactly one line), or a 
     113        # collection of changes, with opening and closing curl braces. 
     114        # Filenames must begin with "./", and eventual spaces replaced by '\32\'. 
     115        # Order is significant! 
     116 
     117        pending = join(self.repository.basedir, '_darcs', 'patches', 'pending') 
     118        p = open(pending).readlines() 
     119        if p[0] != '{\n': 
     120            p.insert(0, '{\n') 
     121            p.append('}\n') 
     122 
     123        changed = False 
     124        adapted = self._adaptChangeset(changeset) 
     125        for e in adapted.entries: 
     126            if e.action_kind == e.RENAMED: 
     127                self.log.debug('Mimicing "darcs mv %s %s"', 
     128                               e.old_name, e.name) 
     129                oname = e.old_name.replace(' ', '\\32\\') 
     130                nname = e.name.replace(' ', '\\32\\') 
     131                p.insert(-1, 'move ./%s ./%s\n' % (oname, nname)) 
     132                changed = True 
     133            elif e.action_kind == e.ADDED: 
     134                self.log.debug('Mimicing "darcs add %s"', e.name) 
     135                name = e.name.replace(' ', '\\32\\') 
     136                if e.is_directory: 
     137                    p.insert(-1, 'adddir ./%s\n' % name) 
     138                else: 
     139                    p.insert(-1, 'addfile ./%s\n' % name) 
     140                changed = True 
     141            elif e.action_kind == e.DELETED: 
     142                self.log.debug('Mimicing "darcs rm %s"', e.name) 
     143                name = e.name.replace(' ', '\\32\\') 
     144                if e.is_directory: 
     145                    p.insert(-1, 'rmdir ./%s\n' % name) 
     146                else: 
     147                    p.insert(-1, 'rmfile ./%s\n' % name) 
     148                changed = True 
     149        if changed: 
     150            open(pending, 'w').writelines(p) 
     151        return True 
    139152 
    140153    def _prepareTargetRepository(self): 
Note: See TracChangeset for help on using the changeset viewer.