diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7e99e36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.pyc \ No newline at end of file diff --git a/p4Helper.py b/p4Helper.py index 937b13b..b11d768 100644 --- a/p4Helper.py +++ b/p4Helper.py @@ -57,6 +57,21 @@ def join( patha, pathb ): def splitdrive( path ): return ntpath.splitdrive( path ) +def p4FriendlyPath(path): + """ + Returns path with sanitized unsupported characters due to filename limitations. + """ + # http://www.perforce.com/perforce/doc.current/manuals/cmdref/filespecs.html#1041962 + replace_items = { + '@' : '%40', + '#' : '%23', + '*' : '%2A', + '%' : '%25' + } + def replace(c): + return replace_items[c] if c in replace_items else c + return ''.join(map(replace, path)) + #============================================================== def get_ignore_list( path, files_to_ignore ): # have to split path and test top directory diff --git a/p4Sync.py b/p4Sync.py new file mode 100644 index 0000000..fb52b18 --- /dev/null +++ b/p4Sync.py @@ -0,0 +1,62 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- +# author : Brian Ernst +# python_version : 2.7.6 and 3.4.0 +# ================================= + +from p4Helper import * + +import multiprocessing, subprocess, time, traceback + + +#============================================================== +class P4Sync: + def run( self, args ): + start = time.clock() + + fail_if_no_p4() + + #http://docs.python.org/library/optparse.html + parser = optparse.OptionParser( ) + + parser.add_option( "-d", "--dir", dest="directory", help="Desired directory to crawl.", default=None ) + parser.add_option( "-t", "--threads", dest="thread_count", help="Number of threads to crawl your drive and poll p4.", default=0 ) + parser.add_option( "-f", "--force", action="store_true", dest="force", help="Force sync files, even if you already have them.", default=False ) + parser.add_option( "-q", "--quiet", action="store_true", dest="quiet", help="This overrides verbose", default=False ) + parser.add_option( "-v", "--verbose", action="store_true", dest="verbose", default=False ) + + ( options, args ) = parser.parse_args( args ) + + directory = normpath( options.directory if options.directory is not None else os.getcwd( ) ) + thread_count = options.thread_count if options.thread_count > 0 else multiprocessing.cpu_count( ) + options.thread_count + + with Console( auto_flush_time=1 ) as c: + with P4Workspace( directory ): + if not options.quiet: + c.writeflush( "Syncing files..." ) + try: + # in progress, very ugly right now. + cmd = "p4 " + \ + ( "-vnet.maxwait=60 " if thread_count > 1 else '' ) + \ + "-r 100000 sync " + \ + ('-f ' if options.force else '') + \ + ("--parallel=threads=" + str(thread_count) + " " if thread_count > 1 else '') + \ + os.path.join(directory, "...") + c.writeflush(thread_count) + c.writeflush(cmd) + subprocess.check_output( cmd, shell=True ) + except subprocess.CalledProcessError: + pass + if not options.quiet: + end = time.clock() + delta = end - start + output = " Done. Finished in " + str(delta) + "s" + print( output ) + + +if __name__ == "__main__": + try: + P4Sync().run(sys.argv) + except: + print( "\nUnexpected error!" ) + traceback.print_exc( file = sys.stdout ) \ No newline at end of file diff --git a/p4SyncMissingFiles.py b/p4SyncMissingFiles.py index 15d418a..76e7ad0 100644 --- a/p4SyncMissingFiles.py +++ b/p4SyncMissingFiles.py @@ -26,7 +26,6 @@ class P4SyncMissing: parser.add_option( "-t", "--threads", dest="thread_count", help="Number of threads to crawl your drive and poll p4.", default=12 ) parser.add_option( "-q", "--quiet", action="store_true", dest="quiet", help="This overrides verbose", default=False ) parser.add_option( "-v", "--verbose", action="store_true", dest="verbose", default=False ) - parser.add_option( "-i", "--interactive", action="store_true", dest="interactive", default=False ) ( options, args ) = parser.parse_args( args ) @@ -45,7 +44,7 @@ class P4SyncMissing: return False def sync( files ): files_len = len(files) - files_flat = ' '.join('"' + f + '"' for f in files) + files_flat = ' '.join('"' + p4FriendlyPath( f ) + '"' for f in files) if options.verbose: files_len = len(files) @@ -82,7 +81,7 @@ class P4SyncMissing: } threads = [ ] - thread_count = options.thread_count if options.thread_count > 0 else multiprocessing.cpu_count( ) + threads + thread_count = options.thread_count if options.thread_count > 0 else multiprocessing.cpu_count( ) + options.thread_count count = 0 total = 0