diff --git a/p4RemoveUnversioned.py b/p4RemoveUnversioned.py index 67ec4b8..913a650 100644 --- a/p4RemoveUnversioned.py +++ b/p4RemoveUnversioned.py @@ -77,6 +77,9 @@ def match_in_ignore_list( path, ignore_list ): return True return False +def call_process( args ): + return subprocess.call( args.split( ), stdout=subprocess.PIPE, stderr=subprocess.PIPE ) + use_bytearray_str_conversion = type( b"str" ) is not str def get_str_from_process_stdout( line ): if use_bytearray_str_conversion: @@ -84,6 +87,9 @@ def get_str_from_process_stdout( line ): else: return line +def singular_pulural( val, singular, plural ): + return singular if val == 1 else plural + # Keep these in mind if you have issues: # https://stackoverflow.com/questions/16557908/getting-output-of-a-process-at-runtime # https://stackoverflow.com/questions/4417546/constantly-print-subprocess-output-while-process-is-running @@ -109,6 +115,8 @@ def get_client_set( path ): files.add( local_path ) + # TODO: check error to see if the path is not in the client view. Prompt anyway? + return files class PTable( list ): @@ -206,7 +214,7 @@ class Console( threading.Thread ): def main( args ): # check requirements - if os.system( 'p4 -V' ) != 0: + if call_process( 'p4 -V' ) != 0: print( 'Perforce Command-line Client(p4) is required for this script.' ) sys.exit( 1 ) @@ -215,14 +223,19 @@ def main( args ): 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=100 ) - parser.add_option( "-q", "--quiet", action="store_false", dest="quiet", help="This overrides verbose", 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=True ) ( options, args ) = parser.parse_args( ) directory = normpath( options.directory if options.directory is not None else os.getcwd( ) ) - remove_count = 0 + # Files are added from .p4ignore + # Key is the file root, the value is the table of file regexes for that directory. + files_to_ignore = PDict() + + remove_file_count = 0 + remove_dir_count = 0 warning_count = 0 error_count = 0 @@ -234,7 +247,7 @@ def main( args ): if not options.quiet: c.writeflush( "Checking " + directory) for root, dirs, files in os.walk( directory ): - ignore_list = {}#get_ignore_list( root, files_to_ignore ) + ignore_list = get_ignore_list( root, files_to_ignore ) if not options.quiet: c.write( "|Checking " + root ) @@ -257,24 +270,49 @@ def main( args ): try: os.chmod( path, stat.S_IWRITE ) os.remove( path ) - remove_count += 1 + remove_file_count += 1 except OSError as ex: c.writeflush( "| " + type( ex ).__name__ ) c.writeflush( "| " + repr( ex ) ) c.writeflush( "| ^ERROR^" ) error_count += 1 - if not options.quiet: c.write( "|Done." ) - output = "\nRemoved " + str( remove_count ) + " file/s" + if not options.quiet: + c.write( os.linesep + "Removing empty directories...") + # remove empty directories in reverse order + for root, dirs, files in os.walk( directory, topdown=False ): + ignore_list = get_ignore_list( root, files_to_ignore ) + + for d in dirs: + path = os.path.join( root, d ) + + if match_in_ignore_list( path, ignore_list ): + # add option of using send2trash + if not options.quiet: + c.write( "| ignoring " + d ) + dirs.remove( d ) + try: + os.rmdir(path) + remove_dir_count += 1 + if not options.quiet: + c.write( "| " + d + " was removed." ) + except OSError: + # Fails on non-empty directory + pass + if not options.quiet: + c.write( "|Done." ) + + if not options.quiet: + output = "\nRemoved " + str( remove_file_count ) + singular_pulural( remove_file_count, " file, ", " files, " ) + output += str( remove_dir_count ) + singular_pulural( remove_dir_count, " directory", " directories") if warning_count > 0: - output += " w/ " + str( warning_count ) + " warning/s" - + output += " w/ " + str( warning_count ) + singular_pulural( warning_count, " warning", " warnings" ) if error_count > 0: - output += " w/ " + str( error_count ) + " error/s" + output += " w/ " + str( error_count ) + singular_pulural( error_count, " error", " errors" ) c.write( output + "." )