This repository has been archived by the owner on Apr 21, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
build.go
143 lines (117 loc) · 4.3 KB
/
build.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
138
139
140
141
142
143
package main
import (
"encoding/json"
"fmt"
"os/exec"
"strconv"
"strings"
"time"
"github.com/logrusorgru/aurora"
)
// Build is a single build from LineageOS.
type Build struct {
Device string
Date BuildDate `json:"date"`
Datetime BuildDateTime `json:"datetime"`
Filename string `json:"filename"`
Filepath string `json:"filepath"`
Sha1 string `json:"sha1"`
Sha256 string `json:"sha256"`
Size int `json:"size"`
Type string `json:"type"`
Version string `json:"version"`
}
// BuildDate is the `Date` inside a `Build`.
type BuildDate struct{ time.Time }
// UnmarshalJSON parses a formatted string and returns the time value it represents.
func (bd *BuildDate) UnmarshalJSON(b []byte) error {
s := strings.Trim(string(b), `"`)
t, err := time.Parse("2006-01-02", s)
if err != nil {
return err
}
*bd = BuildDate{t.In(time.UTC)}
return nil
}
// MarshalJSON returns the JSON encoding of a `BuildDateTime`.
func (bd *BuildDate) MarshalJSON() ([]byte, error) {
return json.Marshal(bd)
}
// BuildDateTime is the `Datetime` inside a `Build`.
type BuildDateTime struct{ time.Time }
// UnmarshalJSON parses a formatted string and returns the time value it represents.
func (bdt *BuildDateTime) UnmarshalJSON(b []byte) error {
t := strings.Trim(string(b), `"`)
sec, err := strconv.ParseInt(t, 10, 64)
if err != nil {
return err
}
epochTime := time.Unix(sec, 0).In(time.UTC)
*bdt = BuildDateTime{epochTime}
return nil
}
// MarshalJSON returns the JSON encoding of a `BuildDateTime`.
func (bdt *BuildDateTime) MarshalJSON() ([]byte, error) {
return json.Marshal(bdt)
}
// Select this build from the database.
func (build *Build) Select() (bh BuildHash, err error) {
// Prevent null pointers
bh = BuildHash{Build: &Build{}}
var t1 time.Time
var t2 time.Time
err = db.QueryRow("select `device`, `date`, `datetime`, `filename`, `filepath`, `sha1`, `sha256`, `size`, `type`, `version`, `ipfs` from `builds` where `device` = ? and `date` = ? and `datetime` = ? and `filename` = ? and `filepath` = ? and `sha1` = ? and `sha256` = ? and `size` = ? and `type` = ? and `version` = ?;", build.Device, build.Date.Time, build.Datetime.Time, build.Filename, build.Filepath, build.Sha1, build.Sha256, build.Size, build.Type, build.Version).Scan(&bh.Build.Device, &t1, &t2, &bh.Build.Filename, &bh.Build.Filepath, &bh.Build.Sha1, &bh.Build.Sha256, &bh.Build.Size, &bh.Build.Type, &bh.Build.Version, &bh.IPFS)
bh.Build.Date = BuildDate{t1}
bh.Build.Datetime = BuildDateTime{t2}
return
}
// Hash this build then save it.
func (build *Build) Hash(index int, total int) (bh *BuildHash, err error) {
// Log
fmt.Println("Processing build", aurora.Green(build.Filename).String()+"...")
start := time.Now()
// Add the file to IPFS
filepath := mirrorbits + build.Filepath
out, err := exec.Command("ipfs-cluster-ctl", "add", "-w", "--chunker=rabin", "--name", build.Filename, "--replication-min", build.RMin(), "--replication-max", build.RMax(), filepath).Output()
if err != nil {
fmt.Println("Failed to download a build.")
fmt.Println(aurora.Bold("Command :"), "ipfs-cluster-ctl", "add", "-w", "--chunker=rabin", "--name", aurora.Green(build.Filename), "--replication-min", build.RMin(), "--replication-max", build.RMax(), aurora.Blue(filepath))
// Log the error from the command
ee, ok := err.(*exec.ExitError)
if ok {
fmt.Println(string(ee.Stderr))
}
fmt.Println(string(out))
return
}
// Remove garbage
slice := strings.Fields(string(out))
hash := slice[len(slice)-1]
hash = strings.Trim(hash, "\n")
if hash == hashEmptyFolder {
err = errHashEmptyFolder
fmt.Println("Empty folder hash :", hash)
unpin()
return nil, err
} else if !strings.Contains(hash, "Qm") {
err = errInvalidHash
fmt.Println("Invalid hash :", hash)
return nil, err
}
// Create the object
bh = &BuildHash{
Build: build,
IPFS: hash,
}
// Percentage
fmt.Println(aurora.Bold(percent(index, total)), "|", aurora.Green(build.Filename), "|", aurora.Cyan(bh.IPFS), "|", time.Since(start).String())
return
}
// RMin is the minimum replication factor for a given build.
func (build *Build) RMin() string {
return strconv.Itoa(1)
}
// RMax is the maximum replication factor for a given build.
func (build *Build) RMax() string {
return strconv.Itoa(build.Size/(speed*seconds) + 1)
}