Add vcs-load-dirs project to thirdparty directory.
[Melange.git] / thirdparty / vcs-load-dirs / vcs_support / vcs_interact.py
blobf3da8800d5b45c011280fa559d480f6131eaa55d
1 # Copyright (C) 2003-2007 John Goerzen
2 # <jgoerzen@complete.org>
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.
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.
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
18 import sys, os
19 import util
20 from commandver import isdarcs
21 from tempfile import mkdtemp
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
32 if os.path.isdir(importdir):
33 self.importdir = os.path.abspath(importdir)
34 self.importfile = None
35 self.tmpdir = None
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
43 try:
44 if self.verb:
45 print "Unpacking archive..."
47 if self.importfile.endswith(".tar.gz"):
48 util.chdircmd(self.importdir, util.safeexec, "tar",
49 ["-zxf", self.importfile])
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"
60 # Many tarballs expand into just one single directory.
61 # Check to see if that's the case.
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
71 def cleanup(self):
72 if not (self.tmpdir is None):
73 util.safeexec("rm", ["-rf", self.tmpdir])
74 self.tmpdir = None
76 def updateimportfiles(self):
77 if self.verb:
78 print "Scanning upstream tree..."
79 self.importfiles = util.maketree(self.importdir)
81 def updatewcfiles(self):
82 if self.verb:
83 print "Scanning working copy tree..."
84 self.wcfiles = self.wcobj.gettree()
86 def update(self):
87 self.updatewcfiles()
88 self.updatechangedfiles()
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
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)]
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
118 self.updateimportfiles()
119 needsupdate = 1
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
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."
155 self.catchup(needsupdate)
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)
171 if self.verb:
172 print "Copying upstream directory to working copy..."
173 util.copyfrom(self.importdir, self.wcobj.wcpath)
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()
184 def writelog(self):
185 logtext = ""
186 if not (self.importfile is None):
187 importname = self.importfile
188 else:
189 importname = self.importdir
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)
202 def addfile(self, file):
203 self.wcobj.addtag(file)
205 def delfile(self, file):
206 self.wcobj.deltag(file)
207 self.wcobj.delfile(file)
210 def mv(self, src, dest):
211 print "%s -> %s" % (src, dest)
212 self.wcobj.movefile(src, dest)
213 self.wcobj.movetag(src, dest)