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