2020-07-01 03:30:11 +00:00
|
|
|
import argparse
|
2021-04-01 02:40:47 +00:00
|
|
|
import collections
|
2020-07-01 03:30:11 +00:00
|
|
|
import os
|
|
|
|
import shutil
|
|
|
|
import sys
|
|
|
|
|
|
|
|
from voussoirkit import passwordy
|
|
|
|
from voussoirkit import pathclass
|
2021-04-01 02:40:47 +00:00
|
|
|
from voussoirkit import vlogging
|
2020-07-01 03:30:11 +00:00
|
|
|
|
2021-04-01 02:40:47 +00:00
|
|
|
log = vlogging.getLogger(__name__, 'sole_subdir_lift')
|
2020-07-01 03:30:11 +00:00
|
|
|
|
2021-04-01 02:40:47 +00:00
|
|
|
def sole_lift_argparse(args):
|
|
|
|
starting = pathclass.Path(args.starting)
|
|
|
|
queue = collections.deque()
|
2022-01-10 05:49:47 +00:00
|
|
|
queue.extend(starting.walk_directories())
|
2021-04-01 02:40:47 +00:00
|
|
|
while len(queue) > 0:
|
|
|
|
directory = queue.popleft()
|
2020-07-01 03:30:11 +00:00
|
|
|
|
2021-04-01 02:40:47 +00:00
|
|
|
if not directory.exists:
|
|
|
|
log.debug('%s no longer exists.', directory)
|
|
|
|
continue
|
2020-07-01 03:30:11 +00:00
|
|
|
|
2021-04-01 02:40:47 +00:00
|
|
|
if directory not in starting:
|
|
|
|
log.debug('%s is outside of starting.', directory)
|
|
|
|
continue
|
2020-07-01 03:30:11 +00:00
|
|
|
|
2021-04-01 02:40:47 +00:00
|
|
|
children = directory.listdir()
|
|
|
|
child_count = len(children)
|
|
|
|
if child_count != 1:
|
|
|
|
log.debug('%s has %d children.', directory, child_count)
|
|
|
|
continue
|
2020-07-01 03:30:11 +00:00
|
|
|
|
2021-04-01 02:40:47 +00:00
|
|
|
child = children[0]
|
2020-07-01 03:30:11 +00:00
|
|
|
|
2021-04-01 02:40:47 +00:00
|
|
|
if not child.is_dir:
|
|
|
|
log.debug('%s contains a file, not a dir.', directory)
|
|
|
|
continue
|
|
|
|
|
|
|
|
log.info('Lifting contents of %s.', child.absolute_path)
|
|
|
|
# child is renamed to random hex so that the grandchildren we are about
|
|
|
|
# to lift don't have name conflicts with the child dir itself.
|
|
|
|
# Consider .\abc\abc where the grandchild can't be moved.
|
2022-01-10 01:08:56 +00:00
|
|
|
temp_dir = directory.with_child(passwordy.random_hex(32))
|
2021-12-03 03:34:28 +00:00
|
|
|
os.rename(child, temp_dir)
|
2021-04-01 02:40:47 +00:00
|
|
|
for grandchild in temp_dir.listdir():
|
2021-12-03 03:34:28 +00:00
|
|
|
shutil.move(grandchild, directory)
|
2021-04-01 02:40:47 +00:00
|
|
|
|
|
|
|
if temp_dir.listdir():
|
2022-01-10 05:49:47 +00:00
|
|
|
raise Exception('The temp dir is supposed to be empty by this point.')
|
2021-04-01 02:40:47 +00:00
|
|
|
|
2021-12-03 03:34:28 +00:00
|
|
|
os.rmdir(temp_dir)
|
2021-04-01 02:40:47 +00:00
|
|
|
queue.append(directory.parent)
|
2020-07-01 03:30:11 +00:00
|
|
|
|
2021-09-24 06:42:34 +00:00
|
|
|
return 0
|
|
|
|
|
2021-06-22 05:11:19 +00:00
|
|
|
@vlogging.main_decorator
|
2020-07-01 03:30:11 +00:00
|
|
|
def main(argv):
|
|
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
|
|
|
2021-04-01 02:40:47 +00:00
|
|
|
parser.add_argument('starting', nargs='?', default='.')
|
2020-07-01 03:30:11 +00:00
|
|
|
parser.set_defaults(func=sole_lift_argparse)
|
|
|
|
|
|
|
|
args = parser.parse_args(argv)
|
|
|
|
return args.func(args)
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
raise SystemExit(main(sys.argv[1:]))
|