| #! /usr/bin/python |
| # |
| # repcacheman ver 0.44 |
| # |
| # Cache Manager for Http-Replicator |
| # deletes duplicate files in PORTDIR. |
| # imports authenticated (checksum + listed in portage) |
| # files from PORTDIR to replicator's cache directory. |
| # |
| # Uses portage to perform checksum and database functions. |
| # All else, Copyright(C)2004-2007 Tom Poplawski (poplawtm@earthlink.net) |
| # Distributed under the terms of the GNU General Public License v2 |
| # |
| # This program is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| # GNU General Public License for more details. |
| |
| # You should have received a copy of the GNU General Public License |
| # along with this program; if not, write to the Free Software |
| # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| |
| |
| import portage.manifest |
| import portage.checksum |
| import portage.exception |
| import portage |
| import string |
| import os |
| import pwd,sys,optparse |
| |
| if os.getuid(): |
| print"Must be root" |
| sys.exit(1) |
| |
| # Parse Options |
| |
| parser = optparse.OptionParser() |
| parser.add_option('-d', '--dir', type='string', default="/var/cache/http-replicator", help='http-replicators cache DIR') |
| parser.add_option('-u','--user', type='string', default="portage", help='http-replicator USER') |
| options, args = parser.parse_args() # parse command line |
| |
| if options.user: |
| try: |
| uid=pwd.getpwnam(options.user)[2] |
| gid=pwd.getpwnam(options.user)[3] |
| except: |
| print "User \'" + options.user + "\' Doesn't exist on system - edit config or add user to system." |
| sys.exit(1) |
| else: |
| print "Error\n\tunable to get USER from /etc/http-replicator.conf" |
| sys.exit(1) |
| |
| # dir is replicator's cache directory |
| dir=options.dir+"/" |
| |
| if os.path.isdir(dir) : |
| newdir=0 |
| else : |
| print"\n\nBegin Http-Replicator Setup...." |
| try: |
| os.makedirs(dir) |
| print "\tcreated " + dir |
| newdir=1 |
| except: |
| print "\tcreate " + dir + " failed" |
| print '\terror:', sys.exc_info()[1] |
| sys.exit(1) |
| try: |
| os.chown(dir,uid,gid) |
| print "\tchanged owner of " + dir + " to " + options.user |
| except: |
| print "\tchange owner " + dir + " to " + options.user + " failed:" |
| print '\terror:', sys.exc_info()[1] |
| |
| print "\n\nReplicator's cache directory: " + dir |
| |
| # Import Portage settings |
| |
| distdir=portage.settings["DISTDIR"]+"/" |
| if distdir: |
| print "Portage's DISTDIR: " + distdir |
| else: |
| print"Unable to get Portage's DISTDIR" |
| sys.exit(1) |
| |
| # Start Work |
| |
| print "\nComparing directories...." |
| |
| # Create filecmp object |
| import filecmp |
| dc=filecmp.dircmp (distdir,dir,['cvs-src','git-src','hg-src','egit-src','.locks']) |
| print "Done!" |
| |
| dupes=dc.common |
| deleted=0 |
| |
| if dupes: |
| print "\nDeleting duplicate file(s) in " + distdir |
| |
| for s in dupes: |
| print s |
| try: |
| os.remove(distdir + s ) |
| deleted +=1 |
| except: |
| print "\tdelete " + distdir + s + " failed:" |
| print '\terror:', sys.exc_info()[1] |
| |
| print "Done!" |
| |
| |
| newfiles=dc.left_only |
| nf=len(dc.left_only) |
| |
| if nf: |
| print "\nNew files in DISTDIR:" |
| for s in newfiles: |
| print s |
| print"\nChecking authenticity and integrity of new files..." |
| added=0 |
| errors=0 |
| badsum=0 |
| |
| # search all packages |
| |
| for mycp in portage.db["/"]["porttree"].dbapi.cp_all(): |
| manifest = portage.manifest.Manifest("/usr/portage/" + mycp , distdir) |
| if manifest == None: |
| portage.writemsg("Missing manifest: %s\n" % mycpv) |
| |
| remove=[] |
| for file in newfiles: |
| if manifest.hasFile("DIST",file): |
| try: |
| myok, myreason = manifest.checkFileHashes("DIST",file) |
| |
| try: |
| os.rename(distdir+file,dir+file) |
| added += 1 |
| except: |
| try: |
| import shutil |
| shutil.copyfile(distdir+file,dir+file) |
| added += 1 |
| os.remove(distdir+file) |
| except: |
| print "\tmove/copy " + file + " failed:" |
| print '\terror:', sys.exc_info()[1] |
| errors+=1 |
| |
| try: |
| os.chown(dir+file,uid,gid) |
| except: |
| print "\tchown " + file + " failed:" |
| print '\terror:', sys.exc_info()[1] |
| errors +=1 |
| |
| remove.append( file ) |
| |
| except portage.exception.DigestException, e: |
| print("\n!!! Digest verification failed:") |
| print("!!! %s" % e.value[0]) |
| print("!!! Reason: %s" % e.value[1]) |
| print("!!! Got: %s" % e.value[2]) |
| print("!!! Expected: %s" % e.value[3]) |
| badsum+=1 |
| if remove: |
| for rf in remove: |
| newfiles.remove ( rf ) |
| |
| |
| print "\nSUMMARY:" |
| print "Found " + str(len(dupes)) + " duplicate file(s)" |
| if deleted: |
| print "\tDeleted " + str(deleted) + " dupe(s)" |
| |
| if nf: |
| print "Found " + str(nf) + " new file(s)" |
| print "\tAdded " + str(added) + " of those file(s) to the cache" |
| |
| print "Rejected " +str(len(newfiles)) + " File(s) - ", |
| print str(badsum) + " failed checksum(s)" |
| for s in newfiles: |
| print "\t%s" %s |
| if errors: |
| print "Encountered " +str(errors) + " errors" |
| # if badsum: |
| # print str(badsum) + " partial/corrupted file(s)" |
| |
| if newdir: |
| print"\n\nexecute:\n/etc/init.d/http-replicator start" |
| print"to run http-replicator.\n\nexecute:\nrc-update add http-replicator default" |
| print"to make http-replicator start at boot" |
| print"\n\nexecute:\n/usr/bin/repcacheman\nafter emerge's on the server to delete" |
| print"dup files and add new files to the cache" |
| |
| print "\n\nHTTP-Replicator requires you delete any partial downloads in " + distdir |
| print "run rm -f " + distdir +'*' |
| |