122 lines
3.6 KiB
Python
122 lines
3.6 KiB
Python
|
#!/usr/bin/python
|
||
|
# -*- coding: utf8 -*-
|
||
|
|
||
|
# todo: have a backup feature, make sure files are moved to the recycle bin or a temporary file.
|
||
|
# todo: switch to faster method of calling p4 fstat on an entire directory and parsing it's output
|
||
|
# todo: add option of using send2trash
|
||
|
|
||
|
import inspect, os, re, subprocess, sys, traceback
|
||
|
|
||
|
|
||
|
modules_path = os.path.normpath( os.path.realpath( __file__ ) )
|
||
|
|
||
|
|
||
|
re_remove_comment = re.compile( "#.*$" )
|
||
|
def remove_comment( s ):
|
||
|
return re.sub( re_remove_comment, "", s )
|
||
|
|
||
|
|
||
|
try: input = raw_input
|
||
|
except: pass
|
||
|
|
||
|
def PressEnter( ):
|
||
|
print( "\nPress ENTER to continue..." )
|
||
|
s=input( "" )
|
||
|
|
||
|
def main( ):
|
||
|
# check requirement
|
||
|
if os.system( 'p4 > Nul' ) != 0:
|
||
|
print 'Perforce Command-line Client(p4) is required for this script.'
|
||
|
sys.exit( 1 )
|
||
|
|
||
|
# Files are added from .p4ignore
|
||
|
# Key is the file root, the value is the table of file regexes for that directory.
|
||
|
files_to_ignore = {}
|
||
|
|
||
|
def get_ignore_list( path ):
|
||
|
# have to split path and test top directory
|
||
|
dirs = path.split( os.sep )
|
||
|
|
||
|
ignore_list = [ ]
|
||
|
|
||
|
for i, val in enumerate( dirs ):
|
||
|
path_to_find = os.sep.join( dirs[ : i + 1] )
|
||
|
|
||
|
if path_to_find in files_to_ignore:
|
||
|
ignore_list = ignore_list + files_to_ignore[ path_to_find ]
|
||
|
|
||
|
# ignore_list = [ r for p in [ os.sep.join( dirs[ : i + 1] ) for i, val in enumerate( dirs ) ] if p in files_to_ignore for r in files_to_ignore[ p ] ]
|
||
|
|
||
|
return ignore_list
|
||
|
|
||
|
def match_in_ignore_list( path, ignore_list ):
|
||
|
for r in ignore_list:
|
||
|
if re.match( r, path ):
|
||
|
return True
|
||
|
return False
|
||
|
|
||
|
|
||
|
p4_ignore = ".p4ignore"
|
||
|
|
||
|
for root, dirs, files in os.walk( '.' ):
|
||
|
|
||
|
print ("\nChecking '" + root + "' ...")
|
||
|
|
||
|
if p4_ignore in files:
|
||
|
file_regexes = []
|
||
|
|
||
|
# Should automatically ignore .p4ignore even if it's not specified, otherwise it'll be deleted.
|
||
|
|
||
|
path = os.path.join( root, p4_ignore )
|
||
|
with open( path ) as f:
|
||
|
for line in f:
|
||
|
new_line = remove_comment( line.strip( ) )
|
||
|
if len( new_line ) > 0:
|
||
|
file_regexes.append( re.compile( os.path.join( re.escape( root + os.sep ), new_line ) ) )
|
||
|
|
||
|
print( " appending ignores from " + path )
|
||
|
files_to_ignore[ root ] = file_regexes
|
||
|
|
||
|
|
||
|
ignore_list = get_ignore_list( root )
|
||
|
|
||
|
for file in files:
|
||
|
path = os.path.join( root, file )
|
||
|
|
||
|
if match_in_ignore_list( path, ignore_list ):
|
||
|
print( " ignoring " + path )
|
||
|
continue
|
||
|
|
||
|
proc = subprocess.Popen( "p4 fstat \"" + path + "\"", stdout=subprocess.PIPE, stderr=subprocess.PIPE )
|
||
|
(out, err) = proc.communicate()
|
||
|
|
||
|
if len( err ) > 0:
|
||
|
print( " " + file + " is unversioned, removing it." )
|
||
|
os.remove( path )
|
||
|
|
||
|
dirs_copy = dirs
|
||
|
for d in dirs_copy:
|
||
|
path = os.path.join( root, d )
|
||
|
if match_in_ignore_list( path, ignore_list ):
|
||
|
# add option of using send2trash
|
||
|
print( " ignoring " + d )
|
||
|
dirs.remove( d )
|
||
|
|
||
|
# remove empty directories
|
||
|
for root, dirs, files in os.walk( '.', topdown=False ):
|
||
|
for d in dirs:
|
||
|
try:
|
||
|
os.rmdir(d)
|
||
|
print( " " + d + " was removed." )
|
||
|
except OSError:
|
||
|
# Fails on non-empty directory
|
||
|
pass
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
try:
|
||
|
main( )
|
||
|
except:
|
||
|
print( "Unexpected error!" )
|
||
|
traceback.print_exc( file = sys.stdout )
|
||
|
|
||
|
PressEnter()
|