Blame view

blimp.nim 4.58 KB
74272cdb   Göran Krampe   First commit
1
2
  import md5, os, osproc, parseopt2, strutils, parsecfg, streams
  
5fc367ad   Göran Krampe   Renamed to blimp,...
3
  # blimp is a little utility program for handling large files
74272cdb   Göran Krampe   First commit
4
  # in git repositories. Its inspired by git-fat and s3annex
5fc367ad   Göran Krampe   Renamed to blimp,...
5
6
  # but doesn't rely on S3 for storage, is a single binary without
  # need for Python, and has less features than git-fat. So far.
74272cdb   Göran Krampe   First commit
7
  #
5fc367ad   Göran Krampe   Renamed to blimp,...
8
9
10
11
  # Manual use:
  #
  # Use "blimp d mybigfile" to deflate it before commit.
  # Use "blimp i mybigfile" to inflate it back to original size.
74272cdb   Göran Krampe   First commit
12
13
14
15
  #
  # When deflated the file only has an md5sum string inside it.
  #
  # The file is copied over into:
5fc367ad   Göran Krampe   Renamed to blimp,...
16
17
18
19
20
  #  <homedir>/blimpStore/<originalfilename>-<md5sum>
  #
  # Configuration is in:
  #   <gitroot>/.blimp.conf
  #   ~/blimpstore/.blimp.conf
74272cdb   Göran Krampe   First commit
21
  
5fc367ad   Göran Krampe   Renamed to blimp,...
22
  var blimpStore, remoteBlimpStore: string
74272cdb   Göran Krampe   First commit
23
24
  
  
5fc367ad   Göran Krampe   Renamed to blimp,...
25
  # Load blimp.conf file, overkill for now but...
74272cdb   Göran Krampe   First commit
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
  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":
5fc367ad   Göran Krampe   Renamed to blimp,...
41
            remoteBlimpStore = e.value
74272cdb   Göran Krampe   First commit
42
43
44
45
46
47
48
49
50
          else:
            quit("Unknown configuration: " & e.key)
        of cfgOption:
          quit("Unknown configuration: " & e.key)
        of cfgError:
          quit("Parsing " & filename & ": " & e.msg)
      close(p)
  
  
5fc367ad   Göran Krampe   Renamed to blimp,...
51
52
53
54
  # Upload a file to the remote master blimpStore
  proc uploadFile(blimpFilename: string) =
    if remoteBlimpStore.isNil:
      echo("Remote blimpstore not set in configuration file, not uploading content:\n\t" & blimpFilename)
74272cdb   Göran Krampe   First commit
55
      return
5fc367ad   Göran Krampe   Renamed to blimp,...
56
57
    let errorCode = execCmd("rsync -a " & blimpStore / blimpFilename & " " & remoteBlimpStore)
    if errorCode != 0: quit("Something went wrong uploading content to " & remoteBlimpStore, 2)
74272cdb   Göran Krampe   First commit
58
    
5fc367ad   Göran Krampe   Renamed to blimp,...
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  # Download a file to the remote master blimpStore
  proc downloadFile(blimpFilename: string) =
    if remoteBlimpStore.isNil:
      quit("Remote blimpstore not set in configuration file, can not download content:\n\t" & blimpFilename)
    let errorCode = execCmd("rsync -a " & remoteBlimpStore / blimpFilename & " " & blimpStore / "")
    if errorCode != 0: quit("Something went wrong downloading " & blimpFilename & " from " & remoteBlimpStore, 3)
  
  
  # Copy content to blimpStore, no upload yet.
  proc copyToBlimpStore(filename, blimpFilename: string) =
    if not existsFile(blimpStore / blimpFilename):
      copyFile(filename, blimpStore / blimpFilename)
      uploadFile(blimpFilename)
  
  # Copy content from blimpStore, and downloading first if needed
  proc copyFromblimpStore(blimpFilename, filename: string) =
    if not existsFile(blimpStore / blimpFilename):
      downloadFile(blimpFilename)
    copyFile(blimpStore / blimpFilename, filename)
74272cdb   Göran Krampe   First commit
78
79
  
      
5fc367ad   Göran Krampe   Renamed to blimp,...
80
  # Copy original file to blimpStore and replace with hash stub in git.
74272cdb   Göran Krampe   First commit
81
82
83
84
85
  proc deflate(filename: string) =
    let content = readFile(filename)
    if content[0..4] == "hash:":
      quit("File is already deflated, ignored.", 5)
    let hash = getMD5(content)
5fc367ad   Göran Krampe   Renamed to blimp,...
86
87
88
    let blimpFilename = filename & "-" & hash
    copyToBlimpStore(filename, blimpFilename)
    writeFile(filename, "hash:" & blimpFilename)
74272cdb   Göran Krampe   First commit
89
  
5fc367ad   Göran Krampe   Renamed to blimp,...
90
  # Parse out hash from hash stub and copy back original content from blimpStore.
74272cdb   Göran Krampe   First commit
91
92
93
94
95
96
  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":
5fc367ad   Göran Krampe   Renamed to blimp,...
97
      let blimpfilename = hashline[1]
74272cdb   Göran Krampe   First commit
98
      #removeFile(filename)
5fc367ad   Göran Krampe   Renamed to blimp,...
99
      copyFromblimpStore(blimpfilename, filename)
74272cdb   Göran Krampe   First commit
100
    else:
5fc367ad   Göran Krampe   Renamed to blimp,...
101
102
103
104
105
106
107
108
109
110
111
112
      quit("File is not a blimp file.", 5)
  
  # Find git root dir or fall back on current dir
  proc gitRoot(): string =
    try:
      let tup = execCmdEx("git rev-parse --show-toplevel")
      if tup[1] == 0:
        result = tup[0]
      else:
        result = getCurrentDir()
    except:
      result = getCurrentDir()
74272cdb   Göran Krampe   First commit
113
114
115
  
  ################################ main #####################################
  
5fc367ad   Göran Krampe   Renamed to blimp,...
116
117
  # Hardwired to "blimpstore" directory in home dir.
  blimpStore = getHomeDir() / "blimpstore"
74272cdb   Göran Krampe   First commit
118
119
120
  
  # Make sure we have the dir, or create it.
  try:
5fc367ad   Göran Krampe   Renamed to blimp,...
121
    if not existsDir(blimpStore): createDir(blimpStore)
74272cdb   Göran Krampe   First commit
122
  except:
5fc367ad   Göran Krampe   Renamed to blimp,...
123
    quit("Could not create " & blimpStore & " directory.", 1)
74272cdb   Göran Krampe   First commit
124
125
  
  
5fc367ad   Göran Krampe   Renamed to blimp,...
126
127
128
  # Parse configuration files if they exist
  parseConfFile(gitRoot() / ".blimp.conf")
  parseConfFile(blimpStore / ".blimp.conf")
74272cdb   Göran Krampe   First commit
129
130
  
  # Only a command and a path as argument
5fc367ad   Göran Krampe   Renamed to blimp,...
131
  # TODO: Change to lapp
74272cdb   Göran Krampe   First commit
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
  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)