-
Notifications
You must be signed in to change notification settings - Fork 4
/
jarpatch.go
137 lines (128 loc) · 3.35 KB
/
jarpatch.go
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
128
129
130
131
132
133
134
135
136
137
package main
import (
"errors"
"flag"
"fmt"
"hash/crc32"
"io/ioutil"
"os"
"path"
"strings"
)
const JAR_SUFFIX = ".jar"
func getFileCrc32(filePath string) (uint32, error) {
// TODO: don't read the whole file into memory here
bs, err := ioutil.ReadFile(filePath)
if err != nil {
return 0, err
}
h := crc32.NewIEEE()
h.Write(bs)
return h.Sum32(), nil
}
type Jar struct {
name string
jarPath string
}
func (j *Jar) Compare(o *Jar) (bool, error) {
var statJ, statO os.FileInfo
var err error
statJ, err = os.Stat(j.jarPath); if err != nil {
return false, err
}
statO, err = os.Stat(o.jarPath); if err != nil {
return false, err
}
if statJ.Size() != statO.Size() {
return false, nil
}
var crcJ, crcO uint32
crcJ, err = getFileCrc32(j.jarPath); if err != nil {
return false, err
}
crcO, err = getFileCrc32(o.jarPath); if err != nil {
return false, err
}
return crcJ == crcO, nil
}
var installedPath *string = flag.String("i", "", "the install path")
var updatePath *string = flag.String("u", "", "the update path")
var dryRun *bool = flag.Bool("d", false, "Do a dry-run (don't copy anything)")
var verbose *bool = flag.Bool("v", false, "Be verbose")
func locateJars(curPath string, jars map[string]Jar) error {
stat, err := os.Stat(curPath); if err != nil {
return err
}
if (stat.IsDir()) {
var infos []os.FileInfo
infos, err = ioutil.ReadDir(curPath); if err != nil {
return err
}
for idx := range(infos) {
locateJars(curPath + "/" + infos[idx].Name(), jars)
}
} else {
if strings.HasSuffix(curPath, JAR_SUFFIX) {
name := path.Base(curPath)
if _, ok := jars[name]; ok {
return errors.New("There were two locations for " + name +
" one at " + curPath + ", and another at " +
jars[name].jarPath)
}
jars[name] = Jar { name, curPath }
}
}
return nil
}
func main() {
flag.Parse()
var err error
if *installedPath == "" {
fmt.Fprintf(os.Stderr, "You must give an installed path. -h " +
"for help.\n")
os.Exit(1)
}
if *updatePath == "" {
fmt.Fprintf(os.Stderr, "You must give an update path. -h " +
"for help.\n")
os.Exit(1)
}
installedJars := make(map[string]Jar)
err = locateJars(*installedPath, installedJars); if err != nil {
fmt.Fprintf(os.Stderr, "Error locating installed jars in %s: %s\n",
*installedPath, err.Error())
os.Exit(1)
}
updateJars := make(map[string]Jar)
err = locateJars(*updatePath, updateJars); if err != nil {
fmt.Fprintf(os.Stderr, "Error locating update jars in %s: %s\n",
*updatePath, err.Error())
os.Exit(1)
}
for updateJarName, updateJar := range(updateJars) {
if installedJar, ok := installedJars[updateJarName]; ok {
var same bool
same, err = installedJar.Compare(&updateJar); if err != nil {
fmt.Fprintf(os.Stderr, "Error comparing jars " +
"%s and %s: %s\n", installedJar.jarPath,
updateJar.jarPath, err.Error())
os.Exit(1)
}
if (same) {
if (*verbose) {
fmt.Printf("update jar " + updateJar.jarPath +
" matches installed jar " + installedJar.jarPath + "\n")
}
} else {
fmt.Printf("update jar " + updateJar.jarPath +
" does not match installed jar " + installedJar.jarPath + "\n")
// TODO: copy update jar over when dry-run == false
}
} else {
if (*verbose) {
fmt.Printf("ignoring update jar " + updateJarName +
" because there is no matching installed jar.\n")
}
}
}
}