2017-10-30 11:44:12 +01:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
import argparse
|
2018-10-06 10:27:36 +02:00
|
|
|
import coloredlogs
|
|
|
|
import logging
|
|
|
|
import os
|
|
|
|
import sys
|
|
|
|
|
|
|
|
coloredlogs.install(level='DEBUG', fmt='%(levelname)s %(message)s')
|
|
|
|
log = logging.getLogger()
|
2017-10-30 11:44:12 +01:00
|
|
|
|
2018-10-06 10:27:36 +02:00
|
|
|
# Coding conventions:
|
|
|
|
# No leading or trailing slashes. Let os.path.join do its job
|
|
|
|
|
|
|
|
# TODO Config arparse and pass args to the functions. No globals
|
2017-10-30 11:44:12 +01:00
|
|
|
|
|
|
|
# Finding directories
|
2018-10-06 10:27:36 +02:00
|
|
|
assert 'HOME' in os.environ, "Home directory unknown"
|
|
|
|
DOCS = os.path.realpath(os.path.join(os.environ['HOME'], 'Documents'))
|
|
|
|
assert os.path.isdir(DOCS), "Documents folder not found"
|
|
|
|
ARCS = os.path.realpath(os.path.join(os.environ['HOME'], 'Archives'))
|
|
|
|
assert os.path.isdir(ARCS), "Archives folder not found"
|
|
|
|
|
|
|
|
|
|
|
|
def dirRange(relpath):
|
|
|
|
splits = relpath.split(os.path.sep)
|
|
|
|
res = list()
|
|
|
|
|
|
|
|
for p in range(len(splits)):
|
|
|
|
partPath = os.path.join(*splits[:p+1])
|
|
|
|
|
|
|
|
arcPath = os.path.join(os.path.join(ARCS, partPath))
|
|
|
|
docPath = os.path.join(os.path.join(DOCS, partPath))
|
|
|
|
|
|
|
|
res.append((docPath, arcPath))
|
|
|
|
|
|
|
|
return res
|
|
|
|
|
|
|
|
def travel(relpath):
|
|
|
|
"""
|
|
|
|
Dunno what this will do, let's write code and see.
|
|
|
|
"""
|
|
|
|
wholeRange = dirRange(relpath)
|
|
|
|
for tup in wholeRange:
|
|
|
|
isLast = wholeRange[-1] == tup
|
|
|
|
docPath, arcPath = tup
|
|
|
|
linkPath = os.path.relpath(arcPath, start=docPath)
|
|
|
|
|
|
|
|
log.debug(f"47 {tup}")
|
|
|
|
|
|
|
|
if not os.path.exists(docPath) and not os.path.exists(arcPath):
|
|
|
|
log.error("Not existing")
|
|
|
|
sys.exit(1)
|
|
|
|
elif os.path.isdir(docPath) and os.path.isdir(arcPath) and not isLast:
|
|
|
|
log.debug("Both folder")
|
|
|
|
continue
|
|
|
|
elif os.path.isdir(docPath) and os.path.isdir(arcPath) and isLast:
|
|
|
|
log.error("This should fail for some reason, maybe")
|
|
|
|
sys.exit(1)
|
|
|
|
elif os.path.islink(docPath) and os.path.exists(arcPath):
|
|
|
|
currentLink = os.readlink(docPath)
|
|
|
|
if currentLink != linkPath:
|
|
|
|
log.warning(f"'{docPath}' is pointing to '{currentLink}' " +
|
|
|
|
f"but should point to '{linkPath}'.")
|
|
|
|
# TODO Fixing if asked for
|
|
|
|
sys.exit(1)
|
|
|
|
log.debug("Early link already exists {docPath} → {arcPath}")
|
|
|
|
return
|
|
|
|
elif not os.path.exists(docPath) and os.path.exists(arcPath):
|
|
|
|
log.debug("Only existing on archive side, linking")
|
|
|
|
print(f"ln -s {linkPath} {docPath}")
|
|
|
|
elif os.path.exists(docPath) and not os.path.exists(arcPath) \
|
|
|
|
and isLast:
|
|
|
|
log.debug("Only existing on doc side, moving and linking")
|
|
|
|
print(f"mv {docPath} {arcPath}")
|
|
|
|
print(f"ln -s {linkPath} {docPath}")
|
|
|
|
elif os.path.exists(docPath) and not os.path.exists(arcPath) \
|
|
|
|
and not isLast:
|
|
|
|
raise NotImplementedError("Here comes the trouble")
|
|
|
|
else:
|
|
|
|
log.error("Unhandled case")
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
|
|
|
|
def ensureLink(relpath):
|
|
|
|
"""
|
|
|
|
Ensure that ~/Documents/$relpath points to ~/Archives/$relpath
|
|
|
|
"""
|
|
|
|
arcPath = os.path.join(os.path.join(ARCS, relpath))
|
|
|
|
docPath = os.path.join(os.path.join(DOCS, relpath))
|
|
|
|
assert os.path.exists(arcPath)
|
|
|
|
|
|
|
|
# For each tree element of the path
|
|
|
|
for docPath, arcPath in dirRange(relpath):
|
|
|
|
linkPath = os.path.relpath(arcPath, start=docPath)
|
|
|
|
|
|
|
|
def installLink():
|
|
|
|
if args.dry:
|
|
|
|
print(f"ln -s {linkPath} {docPath}")
|
|
|
|
else:
|
|
|
|
os.symlink(linkPath, docPath)
|
|
|
|
|
|
|
|
if os.path.islink(docPath):
|
|
|
|
currentLink = os.readlink(docPath)
|
|
|
|
if currentLink != linkPath:
|
|
|
|
log.warning(f"'{docPath}' is pointing to '{currentLink}' " +
|
|
|
|
f"but should point to '{linkPath}'. Fixing")
|
|
|
|
if args.dry:
|
|
|
|
print(f"rm {docPath}")
|
|
|
|
else:
|
|
|
|
os.unlink(docPath)
|
|
|
|
installLink()
|
|
|
|
return
|
|
|
|
elif not os.path.exists(docPath):
|
|
|
|
installLink()
|
|
|
|
return
|
|
|
|
elif os.path.isdir(docPath):
|
|
|
|
continue
|
|
|
|
else:
|
|
|
|
raise RuntimeError(f"'{docPath}' exists and is not a directory " +
|
|
|
|
f"or a link. Unable to link it to '{linkPath}'")
|
|
|
|
raise RuntimeError(f"'{docPath}' is a directory. Unable to link it to " +
|
|
|
|
f"'{linkPath}'")
|
|
|
|
|
2017-10-30 11:44:12 +01:00
|
|
|
|
2018-01-08 12:26:49 +01:00
|
|
|
def archive(docdir):
|
|
|
|
docdir = os.path.realpath(args.dir)
|
2018-10-06 10:27:36 +02:00
|
|
|
assert os.path.isdir(docdir), docdir + " must be a directory"
|
2018-01-08 12:26:49 +01:00
|
|
|
|
2018-10-06 10:27:36 +02:00
|
|
|
assert docdir.startswith(DOCS), "Directory is not in the document folder"
|
|
|
|
assert not docdir.startswith(ARCS), "Directory is already in the archive folder"
|
2018-01-08 12:26:49 +01:00
|
|
|
|
2018-10-06 10:27:36 +02:00
|
|
|
reldir = os.path.relpath(docdir, DOCS)
|
2018-01-08 12:26:49 +01:00
|
|
|
print("ARC", reldir)
|
|
|
|
|
2018-10-06 10:27:36 +02:00
|
|
|
arcdir = os.path.join(ARCS, reldir)
|
2018-01-08 12:26:49 +01:00
|
|
|
parentArcdir = os.path.realpath(os.path.join(arcdir, '..'))
|
|
|
|
parentDocdir = os.path.realpath(os.path.join(docdir, '..'))
|
|
|
|
linkDest = os.path.relpath(arcdir, parentDocdir)
|
|
|
|
|
|
|
|
# BULLSHIT
|
|
|
|
|
|
|
|
# If the directory exists
|
|
|
|
if os.path.isdir(arcdir):
|
|
|
|
return
|
2018-10-06 10:27:36 +02:00
|
|
|
# for f in os.listdir(arcdir):
|
|
|
|
# assert os.path.isdir(f), "Something unknown in Archive dir")
|
|
|
|
# archive(os.path.join(arcdir, f))
|
2018-01-08 12:26:49 +01:00
|
|
|
|
|
|
|
# If the directory doesn't exist, create the directories under it and move all the folder
|
|
|
|
else:
|
|
|
|
|
|
|
|
if args.dry:
|
|
|
|
print("mkdir -p", parentArcdir)
|
|
|
|
else:
|
|
|
|
os.makedirs(parentArcdir, exist_ok=True)
|
|
|
|
|
|
|
|
if args.dry:
|
|
|
|
print("mv", docdir, arcdir)
|
|
|
|
else:
|
|
|
|
os.rename(docdir, arcdir)
|
|
|
|
|
|
|
|
if args.dry:
|
|
|
|
print("ln -s", linkDest, docdir)
|
|
|
|
else:
|
|
|
|
os.symlink(linkDest, docdir)
|
|
|
|
|
|
|
|
|
|
|
|
def unarchive(arcdir):
|
2018-10-06 10:27:36 +02:00
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser(description="Place a folder in ~/Documents in ~/Documents/Archives and symlink it")
|
|
|
|
parser.add_argument('dir', metavar='DIRECTORY', type=str, help="The directory to archive")
|
|
|
|
parser.add_argument('-d', '--dry', action='store_true')
|
|
|
|
args = parser.parse_args()
|
|
|
|
args.dry = True # DEBUG
|
2017-10-30 11:44:12 +01:00
|
|
|
|
2018-10-06 10:27:36 +02:00
|
|
|
# archive(args.dir)
|
|
|
|
ensureLink(args.dir)
|