thirdparty/vcs-load-dirs/vcs_support/vcs_interact.py
changeset 2311 e8262ca32109
equal deleted inserted replaced
2310:d51331eaec15 2311:e8262ca32109
       
     1 # Copyright (C) 2003-2007 John Goerzen
       
     2 # <jgoerzen@complete.org>
       
     3 #
       
     4 #    This program is free software; you can redistribute it and/or modify
       
     5 #    it under the terms of the GNU General Public License as published by
       
     6 #    the Free Software Foundation; either version 2 of the License, or
       
     7 #    (at your option) any later version.
       
     8 #
       
     9 #    This program is distributed in the hope that it will be useful,
       
    10 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12 #    GNU General Public License for more details.
       
    13 #
       
    14 #    You should have received a copy of the GNU General Public License
       
    15 #    along with this program; if not, write to the Free Software
       
    16 #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    17 
       
    18 import sys, os
       
    19 import util
       
    20 from commandver import isdarcs
       
    21 from tempfile import mkdtemp
       
    22 
       
    23 class interaction:
       
    24     def __init__(self, wcobj, importdir, docommit, log = '', verbose = 0,
       
    25                  summary = None):
       
    26         self.wcobj = wcobj
       
    27         self.log = log
       
    28         self.docommit = docommit
       
    29         self.verb = verbose
       
    30         self.summary = summary
       
    31 
       
    32         if os.path.isdir(importdir):
       
    33             self.importdir = os.path.abspath(importdir)
       
    34             self.importfile = None
       
    35             self.tmpdir = None
       
    36 
       
    37         else:                           # Not a dir, try to unpack an archive.
       
    38             self.importfile = os.path.abspath(importdir)
       
    39             # mkdtemp returns an absolute path
       
    40             self.importdir = mkdtemp("-vcs-load-dirs", ",,unpack-", "..")
       
    41             self.tmpdir = self.importdir
       
    42 
       
    43             try:
       
    44                 if self.verb:
       
    45                     print "Unpacking archive..."
       
    46 
       
    47                 if self.importfile.endswith(".tar.gz"):
       
    48                     util.chdircmd(self.importdir, util.safeexec, "tar",
       
    49                                   ["-zxf", self.importfile])
       
    50 
       
    51                 elif self.importfile.endswith(".tar.bz2"):
       
    52                     util.chdircmd(self.importdir, util.safeexec, "tar",
       
    53                                   ["-jxf", self.importfile])
       
    54                 elif self.importfile.endswith(".zip"):
       
    55                     util.chdircmd(self.importdir, util.safeexec, "unzip",
       
    56                                   [self.importfile])
       
    57                 else:
       
    58                     raise IOError, "Unknown archive file type"
       
    59 
       
    60                 # Many tarballs expand into just one single directory.
       
    61                 # Check to see if that's the case.
       
    62 
       
    63                 dents = os.listdir(self.importdir)
       
    64                 if len(dents) == 1 and os.path.isdir(self.importdir + "/" +
       
    65                                                      dents[0]):
       
    66                     self.importdir = self.importdir + "/" + dents[0]
       
    67             except:
       
    68                 self.cleanup()
       
    69                 raise
       
    70 
       
    71     def cleanup(self):
       
    72         if not (self.tmpdir is None):
       
    73             util.safeexec("rm", ["-rf", self.tmpdir])
       
    74             self.tmpdir = None
       
    75 
       
    76     def updateimportfiles(self):
       
    77         if self.verb:
       
    78             print "Scanning upstream tree..."
       
    79         self.importfiles = util.maketree(self.importdir)
       
    80 
       
    81     def updatewcfiles(self):
       
    82         if self.verb:
       
    83             print "Scanning working copy tree..."
       
    84         self.wcfiles = self.wcobj.gettree()
       
    85 
       
    86     def update(self):
       
    87         self.updatewcfiles()
       
    88         self.updatechangedfiles()
       
    89 
       
    90     def updatechangedfiles(self):
       
    91         if self.verb:
       
    92             print "Calculating changes..."
       
    93         wcfilehash = {}
       
    94         for x in self.wcfiles:
       
    95             wcfilehash[x] = 1
       
    96         importfilehash = {}
       
    97         for x in self.importfiles:
       
    98             importfilehash[x] = 1
       
    99         
       
   100         self.addedfiles = [x for x in self.importfiles if not wcfilehash.has_key(x)]
       
   101         self.deletedfiles = [x for x in self.wcfiles if not importfilehash.has_key(x)]
       
   102         
       
   103 
       
   104     def main(self):
       
   105         def readloop():
       
   106             for command in sys.stdin.readline().strip().split(','):
       
   107                 command = command.strip()
       
   108                 if command == 'q':
       
   109                     return 0
       
   110                 if command == 'r':
       
   111                     return 1
       
   112                 src, dest = command.split(' ')
       
   113                 src = int(src, 16)
       
   114                 dest = int(dest, 16)
       
   115                 self.mv(self.deletedfiles[src], self.addedfiles[dest])
       
   116             return 1
       
   117 
       
   118         self.updateimportfiles()
       
   119         needsupdate = 1
       
   120         
       
   121         while 1:
       
   122             self.update()
       
   123             if self.wcobj.fsonly:
       
   124                 # Don't show this interface if we're not talking to the VCS
       
   125                 break
       
   126             if not (len(self.addedfiles) and len(self.deletedfiles)):
       
   127                 # Just ran update; don't do it again.
       
   128                 needsupdate = 0
       
   129                 break
       
   130 
       
   131             counter = 0
       
   132             print "%3s %-35s %3s %-35s" % ('Num', 'Source Files', 'Num',
       
   133                                              'Destination Files',)
       
   134             print "%s %s %s %s" % ("-" * 3, "-" * 35, "-" * 3, "-" * 35)
       
   135             while counter < max(len(self.addedfiles), len(self.deletedfiles)):
       
   136                 addfile = ''
       
   137                 delfile = ''
       
   138                 if counter < len(self.addedfiles):
       
   139                     addfile = self.addedfiles[counter]
       
   140                 if counter < len(self.deletedfiles):
       
   141                     delfile = self.deletedfiles[counter]
       
   142                 print "%3x %-35s %3x %-35s" % (counter, delfile, counter, addfile)
       
   143                 counter += 1
       
   144             print "Syntax: src dest [,src dest [,...]] to move, q to accept, r to redraw:"
       
   145             sys.stdout.write("Command: ")
       
   146             sys.stdout.flush()
       
   147             try:
       
   148                 if not readloop():
       
   149                     break
       
   150             except ValueError:
       
   151                 print "Error handling input; please try again."
       
   152             except IndexError:
       
   153                 print "Error handling input; please try again."
       
   154 
       
   155         self.catchup(needsupdate)
       
   156         
       
   157     def catchup(self, needsupdate = 1):
       
   158         if self.verb:
       
   159             print " *** Processing changes."
       
   160         if needsupdate:
       
   161             self.update()
       
   162         if self.verb:
       
   163             print "Deleting %d files" % len(self.deletedfiles)
       
   164         if isdarcs():
       
   165             for file in util.sorttree(self.deletedfiles, filesfirst = True):
       
   166                 self.delfile(file)
       
   167         else:
       
   168             for file in self.deletedfiles:
       
   169                 self.delfile(file)
       
   170 
       
   171         if self.verb:
       
   172             print "Copying upstream directory to working copy..."
       
   173         util.copyfrom(self.importdir, self.wcobj.wcpath)
       
   174 
       
   175         if self.verb:
       
   176             print "Adding %d files" % len(self.addedfiles)
       
   177         self.addedfiles.sort() # Make sure top-level dirs added before files
       
   178         for file in self.addedfiles:
       
   179             self.addfile(file)
       
   180         self.writelog()
       
   181         if self.docommit:
       
   182             self.wcobj.commit()
       
   183 
       
   184     def writelog(self):
       
   185         logtext = ""
       
   186         if not (self.importfile is None):
       
   187             importname = self.importfile
       
   188         else:
       
   189             importname = self.importdir
       
   190             
       
   191         if self.summary:
       
   192             summary = self.summary
       
   193         else:
       
   194             summary = "Imported %s" % os.path.basename(importname)
       
   195         logtext += "Imported %s\ninto %s\n\n" % \
       
   196                    (os.path.basename(importname),
       
   197                    self.wcobj.gettreeversion())
       
   198         logtext += self.log
       
   199         self.wcobj.makelog(summary, logtext)
       
   200         
       
   201 
       
   202     def addfile(self, file):
       
   203         self.wcobj.addtag(file)
       
   204 
       
   205     def delfile(self, file):
       
   206         self.wcobj.deltag(file)
       
   207         self.wcobj.delfile(file)
       
   208     
       
   209         
       
   210     def mv(self, src, dest):
       
   211         print "%s -> %s" % (src, dest)
       
   212         self.wcobj.movefile(src, dest)
       
   213         self.wcobj.movetag(src, dest)
       
   214