Commit 74272cdbacfafba0ff73372af3eb1568da46571e

Authored by Göran Krampe
0 parents

First commit

Showing 2 changed files with 127 additions and 0 deletions
README.md 0 → 100644
  1 +++ a/README.md
fat.nim 0 → 100644
  1 +++ a/fat.nim
  1 +import md5, os, osproc, parseopt2, strutils, parsecfg, streams
  2 +
  3 +# This is a little utility program for handling large files
  4 +# in git repositories. Its inspired by git-fat and s3annex
  5 +# but doesn't rely on S3 for storage.
  6 +#
  7 +# Use "fat d mybigfile" to deflate it before commit.
  8 +# Use "fat i mybigfile" to inflate it back to original size.
  9 +#
  10 +# When deflated the file only has an md5sum string inside it.
  11 +#
  12 +# The file is copied over into:
  13 +# <homedir>/fatstore/<originalfilename>-<md5sum>
  14 +
  15 +var fatstore, remoteFatstore: string
  16 +
  17 +
  18 +# Load fatstore.conf file, overkill for now but...
  19 +proc parseConfFile(filename: string) =
  20 + echo filename
  21 + var f = newFileStream(filename, fmRead)
  22 + if f != nil:
  23 + var p: CfgParser
  24 + open(p, f, filename)
  25 + while true:
  26 + var e = next(p)
  27 + case e.kind
  28 + of cfgEof:
  29 + break
  30 + of cfgSectionStart:
  31 + continue # Ignore
  32 + of cfgKeyValuePair:
  33 + if e.key == "remote":
  34 + remoteFatstore = e.value
  35 + else:
  36 + quit("Unknown configuration: " & e.key)
  37 + of cfgOption:
  38 + quit("Unknown configuration: " & e.key)
  39 + of cfgError:
  40 + quit("Parsing " & filename & ": " & e.msg)
  41 + close(p)
  42 +
  43 +
  44 +# Upload a file to the remote master fatstore
  45 +proc uploadFile(fatfilename: string) =
  46 + if remoteFatstore.isNil:
  47 + echo("Remote fatstore not set in configuration file, not uploading content:\n\t" & fatfilename)
  48 + return
  49 + let errorCode = execCmd("rsync -a " & fatstore / fatfilename & " " & remoteFatstore)
  50 + if errorCode != 0: quit("Something went wrong uploading content to " & remoteFatstore, 2)
  51 +
  52 +# Download a file to the remote master fatstore
  53 +proc downloadFile(fatfilename: string) =
  54 + if remoteFatstore.isNil:
  55 + quit("Remote fatstore not set in configuration file, can not download content:\n\t" & fatfilename)
  56 + let errorCode = execCmd("rsync -a " & remoteFatstore / fatfilename & " " & fatstore / "")
  57 + if errorCode != 0: quit("Something went wrong downloading " & fatfilename & " from " & remoteFatstore, 3)
  58 +
  59 +
  60 +# Copy content to fatstore, no upload yet.
  61 +proc copyToFatstore(filename, fatfilename: string) =
  62 + if not existsFile(fatstore / fatfilename):
  63 + copyFile(filename, fatstore / fatfilename)
  64 + uploadFile(fatfilename)
  65 +
  66 +# Copy content from fatstore, and downloading first if needed
  67 +proc copyFromFatstore(fatfilename, filename: string) =
  68 + if not existsFile(fatstore / fatfilename):
  69 + downloadFile(fatfilename)
  70 + copyFile(fatstore / fatfilename, filename)
  71 +
  72 +
  73 +# Copy original file to fatstore and replace with hash stub in git.
  74 +proc deflate(filename: string) =
  75 + let content = readFile(filename)
  76 + if content[0..4] == "hash:":
  77 + quit("File is already deflated, ignored.", 5)
  78 + let hash = getMD5(content)
  79 + let fatfilename = filename & "-" & hash
  80 + copyToFatstore(filename, fatfilename)
  81 + writeFile(filename, "hash:" & fatfilename)
  82 +
  83 +# Parse out hash from hash stub and copy back original content from fatstore.
  84 +proc inflate(filename: string) =
  85 + var hashfile: File
  86 + if not open(hashfile, filename):
  87 + quit("Could not open file: " & filename, 4)
  88 + let hashline = split(string(readLine(hashfile)), {':'})
  89 + if hashline[0] == "hash":
  90 + let fatfilename = hashline[1]
  91 + #removeFile(filename)
  92 + copyFromFatstore(fatfilename, filename)
  93 + else:
  94 + quit("File is not a fat file.", 5)
  95 +
  96 +
  97 +################################ main #####################################
  98 +
  99 +# Hardwired to "fatstore" directory in home dir.
  100 +fatstore = getHomeDir() / "fatstore"
  101 +
  102 +# Make sure we have the dir, or create it.
  103 +try:
  104 + if not existsDir(fatstore): createDir(fatstore)
  105 +except:
  106 + quit("Could not create " & fatstore & " directory.", 1)
  107 +
  108 +
  109 +# Parse configuration if it exists
  110 +parseConfFile(fatstore / "fatstore.conf")
  111 +
  112 +# Only a command and a path as argument
  113 +let argv = commandLineParams()
  114 +let command = argv[0]
  115 +let filename = argv[1]
  116 +
  117 +
  118 +# Do the deed
  119 +if command == "d" or command == "deflate":
  120 + deflate(filename)
  121 +elif command == "i" or command == "inflate":
  122 + inflate(filename)
  123 +else:
  124 + quit("Unknown command, only (d)eflate or (i)inflate are valid.", 6)
  125 +
  126 +# All good
  127 +quit(0)