예제 #1
0
def main():
	global err
	try:
		if len(argv) > 1:
			args = ParseArguments.parse()
		else:
			try:
				from nsz.gui.NSZ_GUI import GUI
			except ImportError:
				Print.error("Failed to import the GUI - is it installed?")
				return
			args = GUI().run()
			if args == None:
				Print.info("Done!")
				return
		
		if args.output:
			outfolderToPharse = args.output
			if not outfolderToPharse.endswith('/') and not outfolderToPharse.endswith('\\'):
				outfolderToPharse += "/"
			if not Path(outfolderToPharse).is_dir():
				Print.error('Error: Output directory "{0}" does not exist!'.format(args.output))
				return
		outfolder = Path(outfolderToPharse).resolve() if args.output else Path('.').resolve()
		
		Print.info('')
		Print.info('             NSZ v3.1   ,;:;;,')
		Print.info('                       ;;;;;')
		Print.info('               .=\',    ;:;;:,')
		Print.info('              /_\', "=. \';:;:;')
		Print.info('              @=:__,  \,;:;:\'')
		Print.info('                _(\.=  ;:;;\'')
		Print.info('               `"_(  _/="`')
		Print.info('                `"\'')
		Print.info('')
		
		barManager = enlighten.get_manager()
		poolManager = Manager()
		statusReport = poolManager.list()
		readyForWork = Counter(0)
		pleaseNoPrint = Counter(0)
		pleaseKillYourself = Counter(0)
		pool = []
		work = poolManager.Queue()
		amountOfTastkQueued = Counter(0)
		
		if args.titlekeys:
			extractTitlekeys(args.file)
		
		if args.extract:
			for f_str in args.file:
				for filePath in expandFiles(Path(f_str)):
					filePath_str = str(filePath)
					Print.info('Extracting "{0}" to {1}'.format(filePath_str, outfolder))
					dir = outfolder.joinpath(filePath.stem)
					container = factory(filePath)
					container.open(filePath_str, 'rb')
					if isXciXcz(filePath):
						for hfs0 in container.hfs0:
							secureIn = hfs0
							secureIn.unpack(dir.joinpath(hfs0._path), args.extractregex)
					else:
						container.unpack(dir, args.extractregex)
					container.close()

		if args.create:
			Print.info('Creating "{0}"'.format(args.create))
			nsp = Nsp.Nsp(None, None)
			nsp.path = args.create
			nsp.pack(args.file)

		if args.C:
			targetDictNsz = CreateTargetDict(outfolder, args.parseCnmt, ".nsz")
			targetDictXcz = CreateTargetDict(outfolder, args.parseCnmt, ".xcz")
			sourceFileToDelete = []
			for f_str in args.file:
				for filePath in expandFiles(Path(f_str)):
					if not isUncompressedGame(filePath):
						continue
					try:
						if filePath.suffix == '.nsp':
							if not AllowedToWriteOutfile(filePath, ".nsz", targetDictNsz, args.rm_old_version, args.overwrite, args.parseCnmt):
								continue
						elif filePath.suffix == '.xci':
							if not AllowedToWriteOutfile(filePath, ".xcz", targetDictXcz, args.rm_old_version, args.overwrite, args.parseCnmt):
								continue
						compress(filePath, outfolder, args, work, amountOfTastkQueued)
						if args.rm_source:
							sourceFileToDelete.append(filePath)
					except KeyboardInterrupt:
						raise
					except BaseException as e:
						Print.error('Error when compressing file: %s' % filePath)
						err.append({"filename":filePath,"error":format_exc() })
						print_exc()
			
			bars = []
			compressedSubBars = []
			BAR_FMT = u'{desc}{desc_pad}{percentage:3.0f}%|{bar}| {count:{len_total}d}/{total:d} {unit} [{elapsed}<{eta}, {rate:.2f}{unit_pad}{unit}/s]'
			parallelTasks = min(args.multi, amountOfTastkQueued.value())
			if parallelTasks < 0:
				parallelTasks = 4
			for i in range(parallelTasks):
				statusReport.append([0, 0, 100])
				p = Process(target=solidCompressTask, args=(work, statusReport, readyForWork, pleaseNoPrint, pleaseKillYourself, i))
				p.start()
				pool.append(p)
			for i in range(parallelTasks):
				bar = barManager.counter(total=100, desc='Compressing', unit='MiB', color='cyan', bar_format=BAR_FMT)
				compressedSubBars.append(bar.add_subcounter('green'))
				bars.append(bar)
			#Ensures that all threads are started and compleaded before being requested to quit
			while readyForWork.value() < parallelTasks:
				sleep(0.2)
				if pleaseNoPrint.value() > 0:
					continue
				pleaseNoPrint.increment()
				for i in range(parallelTasks):
					compressedRead, compressedWritten, total = statusReport[i]
					if bars[i].total != total:
						bars[i].total = total//1048576
					bars[i].count = compressedRead//1048576
					compressedSubBars[i].count = compressedWritten//1048576
					bars[i].refresh()
				pleaseNoPrint.decrement()
			pleaseKillYourself.increment()
			for i in range(readyForWork.value()):
				work.put(None)
			
			while readyForWork.value() > 0:
				sleep(0.02)
			
			for i in range(parallelTasks):
				bars[i].close(clear=True)
			#barManager.stop() #We aren’t using stop because of it printing garbage to the console.

			for filePath in sourceFileToDelete:
				delete_source_file(filePath)

		if args.D:
			targetDictNsz = CreateTargetDict(outfolder, args.parseCnmt, ".nsp")
			targetDictXcz = CreateTargetDict(outfolder, args.parseCnmt, ".xci")
			for f_str in args.file:
				for filePath in expandFiles(Path(f_str)):
					if not isCompressedGame(filePath) and not isCompressedGameFile(filePath):
						continue
					try:
						if filePath.suffix == '.nsz':
							if not AllowedToWriteOutfile(filePath, ".nsp", targetDictNsz, args.rm_old_version, args.overwrite, args.parseCnmt):
								continue
						elif filePath.suffix == '.xcz':
							if not AllowedToWriteOutfile(filePath, ".xci", targetDictXcz, args.rm_old_version, args.overwrite, args.parseCnmt):
								continue
						elif filePath.suffix == '.ncz':
							outfile = Path(changeExtension(outfolder.joinpath(filePath.name), ".nca"))
							if not args.overwrite and outfile.is_file():
								Print.info('{0} with the same file name already exists in the output directory.\n'\
								'If you want to overwrite it use the -w parameter!'.format(outfile.name))
								continue
						decompress(filePath, outfolder)
						if args.rm_source:
							delete_source_file(filePath)
					except KeyboardInterrupt:
						raise
					except BaseException as e:
						Print.error('Error when decompressing file: {0}'.format(filePath))
						err.append({"filename":filePath, "error":format_exc()})
						print_exc()

		if args.info:
			for f_str in args.file:
				for filePath in expandFiles(Path(f_str)):
					filePath_str = str(filePath)
					Print.info(filePath_str)
					f = factory(filePath)
					f.open(filePath_str, 'r+b')
					f.printInfo(args.depth+1)
					f.close()

		if args.verify and not args.C and not args.D:
			for f_str in args.file:
				for filePath in expandFiles(Path(f_str)):
					try:
						if isGame(filePath):
							Print.info("[VERIFY {0}] {1}".format(getExtensionName(filePath), filePath.name))
							verify(filePath, False)
					except KeyboardInterrupt:
						raise
					except BaseException as e:
						Print.error('Error when verifying file: {0}'.format(filePath))
						err.append({"filename":filePath,"error":format_exc()})
						print_exc()

		if len(argv) == 1:
			pass
	except KeyboardInterrupt:
		Print.info('Keyboard exception')
	except BaseException as e:
		Print.info('nut exception: {0}'.format(str(e)))
		raise
	if err:
		Print.info('\n\033[93m\033[1mSummary of errors which occurred while processing files:')
		
		for e in err:
			Print.info('\033[0mError while processing {0}'.format(e["filename"]))
			Print.info(e["error"])

	Print.info('Done!')
	_exit(0)
예제 #2
0
def undupe(args):
    filesAtTarget = {}
    alreadyExists = {}
    for f_str in args.file:
        (filesAtTarget, alreadyExists) = CreateTargetDict(
            Path(f_str).absolute(), True, None, filesAtTarget, alreadyExists)
    Print.info("")

    for (titleID_key, titleID_value) in alreadyExists.items():
        maxVersion = max(titleID_value.keys())
        for (version_key, version_value) in titleID_value.items():

            if args.undupe_old_versions and version_key < maxVersion:
                for file in list(version_value):
                    if not isOnWhitelist(args, file):
                        if args.undupe_dryrun:
                            Print.info("[DRYRUN] [DELETE] [OLD_VERSION]: " +
                                       file)
                        else:
                            os.remove(file)
                            Print.info("[DELETED] [OLD_VERSION]: " + file)
                continue

            if not args.undupe_blacklist == "":
                for file in list(version_value):
                    if not isOnWhitelist(args, file) and re.match(
                            args.undupe_blacklist, file):
                        version_value.remove(file)
                        if args.undupe_dryrun:
                            Print.info("[DRYRUN] [DELETE] [BLACKLIST]: " +
                                       file)
                        else:
                            os.remove(file)
                            Print.info("[DRYRUN] [DELETED] [BLACKLIST]: " +
                                       file)

            if not args.undupe_prioritylist == "":
                for file in list(version_value.reverse()):
                    if len(version_value) > 1 and not isOnWhitelisth(
                            args, file) and re.match(args.undupe_prioritylist,
                                                     file):
                        version_value.remove(file)
                        if args.undupe_dryrun:
                            Print.info("[DRYRUN] [DELETE] [PRIORITYLIST]: " +
                                       file)
                        else:
                            os.remove(file)
                            Print.info("[DRYRUN] [DELETED] [PRIORITYLIST]: " +
                                       file)

            firstDeleted = False
            for file in list(version_value[1:]):
                if not isOnWhitelist(args, file):
                    if args.undupe_dryrun:
                        Print.info("[DRYRUN] [DELETE] [DUPE]: " + file)
                        Print.info("Keeping " + version_value[0])
                    else:
                        os.remove(file)
                        Print.info("[DELETED] [DUPE]: " + file)
                        Print.info("Keeping " + version_value[0])
                elif not firstDeleted and not isOnWhitelist(
                        args, version_value[0]):
                    firstDeleted = True
                    if args.undupe_dryrun:
                        Print.info("[DRYRUN] [DELETE] [DUPE]: " +
                                   version_value[0])
                        Print.info("Keeping " + file)
                    else:
                        os.remove(version_value[0])
                        Print.info("[DELETED] [DUPE]: " + version_value[0])
                        Print.info("Keeping " + file)
예제 #3
0
def undupe(args, argOutFolder):
    filesAtTarget = {}
    alreadyExists = {}
    for f_str in args.file:
        (filesAtTarget, alreadyExists) = CreateTargetDict(
            Path(f_str).absolute(), args, None, filesAtTarget, alreadyExists)
    Print.info("")

    for (titleID_key, titleID_value) in alreadyExists.items():
        maxVersion = max(titleID_value.keys())
        for (version_key, version_value) in titleID_value.items():

            if args.undupe_old_versions and version_key < maxVersion:
                for file in list(version_value):
                    if not isOnWhitelist(args, file):
                        if args.undupe_dryrun:
                            Print.info("[DRYRUN] [DELETE] [OLD_VERSION]: " +
                                       file)
                        else:
                            os.remove(file)
                            Print.info("[DELETED] [OLD_VERSION]: " + file)
                continue

            if not args.undupe_blacklist == "":
                for file in list(version_value):
                    if not isOnWhitelist(args, file) and re.match(
                            args.undupe_blacklist, file):
                        version_value.remove(file)
                        if args.undupe_dryrun:
                            Print.info("[DRYRUN] [DELETE] [BLACKLIST]: " +
                                       file)
                        else:
                            os.remove(file)
                            Print.info("[DRYRUN] [DELETED] [BLACKLIST]: " +
                                       file)

            if not args.undupe_prioritylist == "":
                for file in list(version_value.reverse()):
                    if len(version_value) > 1 and not isOnWhitelisth(
                            args, file) and re.match(args.undupe_prioritylist,
                                                     file):
                        version_value.remove(file)
                        if args.undupe_dryrun:
                            Print.info("[DRYRUN] [DELETE] [PRIORITYLIST]: " +
                                       file)
                        else:
                            os.remove(file)
                            Print.info("[DRYRUN] [DELETED] [PRIORITYLIST]: " +
                                       file)

            firstDeleted = False
            for file in list(version_value[1:]):
                if not isOnWhitelist(args, file):
                    if args.undupe_dryrun:
                        Print.info("[DRYRUN] [DELETE] [DUPE]: " + file)
                        Print.info("Keeping " + version_value[0])
                    else:
                        os.remove(file)
                        Print.info("[DELETED] [DUPE]: " + file)
                        Print.info("Keeping " + version_value[0])
                elif not firstDeleted and not isOnWhitelist(
                        args, version_value[0]):
                    firstDeleted = True
                    if args.undupe_dryrun:
                        Print.info("[DRYRUN] [DELETE] [DUPE]: " +
                                   version_value[0])
                        Print.info("Keeping " + file)
                    else:
                        os.remove(version_value[0])
                        Print.info("[DELETED] [DUPE]: " + version_value[0])
                        Print.info("Keeping " + file)
            if args.undupe_rename or args.undupe_hardlink:
                for file in version_value:
                    if not isOnWhitelist(args, file):
                        newName = str(
                            argOutFolder.joinpath("[" + titleID_key + "][v" +
                                                  str(version_key) + "]" +
                                                  Path(file).suffix))
                        if args.undupe_hardlink:
                            if Path(newName).is_file():
                                if Path(file).samefile(Path(newName)):
                                    Print.info("[HARDLINK] [SKIPPED] " +
                                               newName)
                                else:
                                    Print.info(
                                        "[HARDLINK] [ERROR_ALREADY_EXIST] " +
                                        newName)
                            else:
                                if args.undupe_dryrun:
                                    Print.info("[DRYRUN] [HARDLINK]: " +
                                               "os.link(" + file + ", " +
                                               newName)
                                else:
                                    Print.info("[HARDLINK]: " + "os.link(" +
                                               file + ", " + newName)
                                    os.link(file, newName)
                        if args.undupe_rename:
                            if Path(newName).is_file():
                                if Path(file).samefile(Path(newName)):
                                    Print.info("[RENAME] [SKIPPED] " + newName)
                                else:
                                    Print.info(
                                        "[RENAME] [ERROR_ALREADY_EXIST] " +
                                        newName)
                            else:
                                if args.undupe_dryrun:
                                    Print.info("[DRYRUN] [RENAME]: " +
                                               "os.rename(" + file + ", " +
                                               newName)
                                else:
                                    Print.info("[RENAME]: " + "os.rename(" +
                                               file + ", " + newName)
                                    os.rename(file, newName)