Added more debug info at the end for files processed, cleaned up formatting. At some point will strive to make the output more UNIX friendly, parsable.
I also fixed a bug where the script would crash instead of setting the P4Client. I need to fix the script to use a `with` construct so if you terminate the program the P4Client is returned to what it was.
This commit is contained in:
parent
06b0cbe426
commit
e7bb65874e
|
@ -1,7 +1,10 @@
|
||||||
p4RemoveUnversioned
|
p4RemoveUnversioned
|
||||||
===================
|
===================
|
||||||
|
|
||||||
Removes unversioned files from perforce repository. Script is in beta, though it works. It's a little slow due to the way fstat is used, but that will be changed soon, so the speed up should be enormous once that's done, up to 100x or more.
|
Removes unversioned files from perforce repository. Script is in beta, works well, but still going through continued testing. There are a few stats at the end, will be putting in more, like number of files/directories checked, so you have an idea how much work was required.
|
||||||
|
|
||||||
|
Concerning benchmarks: I used to have a HDD, now a SSD. So I can't provide valid comparisons to the old numbers until I do them on a computer with a HDD. That said, this single worker implementation runs faster than the old multi-threaded version. Can't wait to further update it, will only continue to get faster.
|
||||||
|
|
||||||
|
|
||||||
This script does parse __.p4ignore__ ignore files, compiles the fields as regex, and scans every directory and file against the local and parent __.p4ignore__ files. This is my first time doing something like this, and I just realized this isn't actually correct; I need to update how things are ignored to follow the [spec](http://www.perforce.com/perforce/r12.1/manuals/cmdref/env.P4IGNORE.html), since it's not straight up regex.
|
This script does parse __.p4ignore__ ignore files, compiles the fields as regex, and scans every directory and file against the local and parent __.p4ignore__ files. This is my first time doing something like this, and I just realized this isn't actually correct; I need to update how things are ignored to follow the [spec](http://www.perforce.com/perforce/r12.1/manuals/cmdref/env.P4IGNORE.html), since it's not straight up regex.
|
||||||
|
|
||||||
|
|
|
@ -237,8 +237,8 @@ class Console( threading.Thread ):
|
||||||
self.buffer_write_times.clear( )
|
self.buffer_write_times.clear( )
|
||||||
self.queue.task_done( )
|
self.queue.task_done( )
|
||||||
|
|
||||||
print(self.queue.qsize())
|
#print(self.queue.qsize())
|
||||||
print(self.queue.empty())
|
#print(self.queue.empty())
|
||||||
break
|
break
|
||||||
|
|
||||||
elif event == Console.MSG.WRITE:
|
elif event == Console.MSG.WRITE:
|
||||||
|
@ -347,7 +347,7 @@ def main( args ):
|
||||||
client_root = get_client_root()
|
client_root = get_client_root()
|
||||||
ldirectory = directory.lower()
|
ldirectory = directory.lower()
|
||||||
workspace_name = None
|
workspace_name = None
|
||||||
if not ldirectory.startswith(client_root.lower()):
|
if client_root is None or not ldirectory.startswith(client_root.lower()):
|
||||||
print("\nCurrent directory not in client view, checking other workspaces for user '" + username + "' ...")
|
print("\nCurrent directory not in client view, checking other workspaces for user '" + username + "' ...")
|
||||||
|
|
||||||
workspace_name = parse_info_from_command('p4 info', 'Client name: ')
|
workspace_name = parse_info_from_command('p4 info', 'Client name: ')
|
||||||
|
@ -386,6 +386,9 @@ def main( args ):
|
||||||
# Key is the file root, the value is the table of file regexes for that directory.
|
# Key is the file root, the value is the table of file regexes for that directory.
|
||||||
files_to_ignore = PDict()
|
files_to_ignore = PDict()
|
||||||
|
|
||||||
|
processed_file_count = 0
|
||||||
|
processed_directory_count = 0
|
||||||
|
|
||||||
remove_file_count = 0
|
remove_file_count = 0
|
||||||
remove_dir_count = 0
|
remove_dir_count = 0
|
||||||
warning_count = 0
|
warning_count = 0
|
||||||
|
@ -414,18 +417,21 @@ def main( args ):
|
||||||
ignore_list = get_ignore_list( root, files_to_ignore )
|
ignore_list = get_ignore_list( root, files_to_ignore )
|
||||||
|
|
||||||
if not options.quiet:
|
if not options.quiet:
|
||||||
c.write( "|Checking " + root )
|
c.write( "|Checking " + os.path.relpath( root, directory ) )
|
||||||
|
|
||||||
for d in dirs:
|
for d in dirs:
|
||||||
|
processed_directory_count += 1
|
||||||
path = join( root, d )
|
path = join( root, d )
|
||||||
|
rel_path = os.path.relpath( path, directory )
|
||||||
|
|
||||||
if match_in_ignore_list( path, ignore_list ):
|
if match_in_ignore_list( path, ignore_list ):
|
||||||
# add option of using send2trash
|
# add option of using send2trash
|
||||||
if not options.quiet:
|
if not options.quiet:
|
||||||
c.write( "| ignoring " + d )
|
c.write( "| ignoring " + rel_path )
|
||||||
dirs.remove( d )
|
dirs.remove( d )
|
||||||
|
|
||||||
for f in files:
|
for f in files:
|
||||||
|
processed_file_count += 1
|
||||||
path = normpath( join( root, f ) )
|
path = normpath( join( root, f ) )
|
||||||
|
|
||||||
if path not in files_in_depot:
|
if path not in files_in_depot:
|
||||||
|
@ -451,18 +457,20 @@ def main( args ):
|
||||||
ignore_list = get_ignore_list( root, files_to_ignore )
|
ignore_list = get_ignore_list( root, files_to_ignore )
|
||||||
|
|
||||||
for d in dirs:
|
for d in dirs:
|
||||||
|
processed_directory_count += 1
|
||||||
path = os.path.join( root, d )
|
path = os.path.join( root, d )
|
||||||
|
rel_path = os.path.relpath( path, directory )
|
||||||
|
|
||||||
if match_in_ignore_list( path, ignore_list ):
|
if match_in_ignore_list( path, ignore_list ):
|
||||||
# add option of using send2trash
|
# add option of using send2trash
|
||||||
if not options.quiet:
|
if not options.quiet:
|
||||||
c.write( "| ignoring " + path )
|
c.write( "| ignoring " + rel_path )
|
||||||
dirs.remove( d )
|
dirs.remove( d )
|
||||||
try:
|
try:
|
||||||
os.rmdir(path)
|
os.rmdir(path)
|
||||||
remove_dir_count += 1
|
remove_dir_count += 1
|
||||||
if not options.quiet:
|
if not options.quiet:
|
||||||
c.write( "| " + path + " was removed." )
|
c.write( "| " + rel_path + " was removed." )
|
||||||
except OSError:
|
except OSError:
|
||||||
# Fails on non-empty directory
|
# Fails on non-empty directory
|
||||||
pass
|
pass
|
||||||
|
@ -484,7 +492,10 @@ def main( args ):
|
||||||
c.write("|Done.")
|
c.write("|Done.")
|
||||||
|
|
||||||
if not options.quiet:
|
if not options.quiet:
|
||||||
output = "\n[ Removed " + str( remove_file_count ) + singular_pulural( remove_file_count, " file, ", " files, " )
|
output = "\nChecked " + str( processed_file_count ) + singular_pulural( processed_file_count, " file, ", " files, " )
|
||||||
|
output += str( processed_directory_count ) + singular_pulural( processed_directory_count, " directory", " directories")
|
||||||
|
|
||||||
|
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")
|
output += str( remove_dir_count ) + singular_pulural( remove_dir_count, " directory", " directories")
|
||||||
|
|
||||||
if warning_count > 0:
|
if warning_count > 0:
|
||||||
|
@ -494,9 +505,9 @@ def main( args ):
|
||||||
|
|
||||||
end = time.clock()
|
end = time.clock()
|
||||||
delta = end - start
|
delta = end - start
|
||||||
output += ", and finished in " + str(delta) + "s"
|
output += "\nFinished in " + str(delta) + "s"
|
||||||
|
|
||||||
c.write( output + " ]" )
|
c.write( output )
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
Stack trace:
|
|
||||||
Frame Function Args
|
|
||||||
000FD4FC6C0 0018006F733 (FFFFFFFFFFFFFFFF, 006002C2510, 005CCDD1850, 005CCDD1870)
|
|
||||||
00000000006 00180070C6A (000FD4FC8A0, 00000000000, 0000000035C, 00000000000)
|
|
||||||
000FD4FC8A0 00180118778 (00000000000, 00000000000, 000FD4FCA20, 00600000003)
|
|
||||||
00000000041 0018011587E (00180133B2D, 000000002CC, 00000000000, 00000000000)
|
|
||||||
00000000000 00180115D4B (001801362C0, 006002C2270, 000775D19A1, 00000000006)
|
|
||||||
00000000000 00180115F1C (00000000000, 0008FB10544, 7FEFD6464DA, 006002C2318)
|
|
||||||
00000000000 001801161DF (0018013B2FB, 00600000001, 001801CA2C0, 000FD4FD640)
|
|
||||||
00000000000 00180144816 (00180135C7F, 006002C2270, 006002C2270, 006002C2270)
|
|
||||||
00000000000 001800BFCE3 (0018013460D, 00000000000, 005CCDB7127, 006002C2318)
|
|
||||||
00000000000 001801629FC (00000000000, 00000000000, 00000000000, 006002C2270)
|
|
||||||
00000000000 00180136AEF (00000000000, 00000000000, 00000000000, 00000000000)
|
|
||||||
00000000000 00180136334 (000003A0000, 00000000000, 00000000000, 00000000000)
|
|
||||||
00000000000 001800C373B (000003A0000, 00000000000, 00000000000, 00000000000)
|
|
||||||
End of stack trace
|
|
Loading…
Reference in New Issue