Skip to content

Commit ae096ff

Browse files
committed
init: create bundle list with one bundle
Create more helper packages in 'internal' space, including: * repo: Information about a repository including the Git dir and location of the web content. * core: Important information about the root of our filesystem data stores. * bundles: Information about working with a bundle or a list of bundles. Apply these new packages to complete the implementation of the 'init' subcommand. It now creates the 'bundle-list' file in the web directory and the 'bundle-list.json' file in the Git directory.
1 parent b96d4c2 commit ae096ff

File tree

5 files changed

+166
-43
lines changed

5 files changed

+166
-43
lines changed

cmd/git-bundle-server/init.go

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@ package main
33
import (
44
"errors"
55
"fmt"
6+
"git-bundle-server/internal/bundles"
7+
"git-bundle-server/internal/core"
68
"git-bundle-server/internal/git"
7-
"log"
8-
"os"
9-
"time"
109
)
1110

1211
type Init struct{}
@@ -24,28 +23,27 @@ func (Init) run(args []string) error {
2423
url := args[0]
2524
route := args[1]
2625

27-
repo := reporoot() + route
28-
web := webroot() + route
29-
30-
mkdirErr := os.MkdirAll(web, os.ModePerm)
31-
if mkdirErr != nil {
32-
log.Fatal("Failed to create web directory: ", mkdirErr)
33-
}
26+
repo := core.GetRepository(route)
3427

3528
fmt.Printf("Cloning repository from %s\n", url)
36-
gitErr := git.GitCommand("clone", "--mirror", url, repo)
29+
gitErr := git.GitCommand("clone", "--mirror", url, repo.RepoDir)
3730

3831
if gitErr != nil {
39-
return gitErr
32+
return fmt.Errorf("failed to clone repository: %w", gitErr)
4033
}
4134

42-
timestamp := time.Now().UTC().Unix()
43-
bundleFile := web + "/bundle-" + fmt.Sprint(timestamp) + ".bundle"
44-
fmt.Printf("Constructing base bundle file at %s\n", bundleFile)
35+
bundle := bundles.CreateInitialBundle(repo)
36+
fmt.Printf("Constructing base bundle file at %s\n", bundle.Filename)
4537

46-
gitErr = git.GitCommand("-C", repo, "bundle", "create", bundleFile, "--all")
38+
gitErr = git.GitCommand("-C", repo.RepoDir, "bundle", "create", bundle.Filename, "--all")
4739
if gitErr != nil {
48-
return gitErr
40+
return fmt.Errorf("failed to create bundle: %w", gitErr)
41+
}
42+
43+
list := bundles.SingletonList(bundle)
44+
listErr := bundles.WriteBundleList(list, repo)
45+
if listErr != nil {
46+
return fmt.Errorf("failed to write bundle list: %w", listErr)
4947
}
5048

5149
return nil

cmd/git-bundle-server/subcommand.go

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
package main
22

3-
import (
4-
"os"
5-
)
6-
73
type Subcommand interface {
84
subcommand() string
95
run(args []string) error
@@ -14,21 +10,3 @@ func all() []Subcommand {
1410
Init{},
1511
}
1612
}
17-
18-
func bundleroot() string {
19-
dirname, err := os.UserHomeDir()
20-
if err != nil {
21-
// TODO: respond better. For now, try creating in "/var"
22-
dirname = "/var"
23-
}
24-
25-
return dirname + "/git-bundle-server/"
26-
}
27-
28-
func webroot() string {
29-
return bundleroot() + "www/"
30-
}
31-
32-
func reporoot() string {
33-
return bundleroot() + "git/"
34-
}

internal/bundles/bundles.go

Lines changed: 102 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,106 @@
11
package bundles
22

3-
import "fmt"
3+
import (
4+
"bufio"
5+
"encoding/json"
6+
"fmt"
7+
"git-bundle-server/internal/core"
8+
"os"
9+
"time"
10+
)
411

5-
func BundleList() {
6-
fmt.Printf("called bundleList\n")
7-
fmt.Printf("\n");
12+
type Bundle struct {
13+
URI string
14+
Filename string
15+
CreationToken int64
16+
}
17+
18+
type BundleList struct {
19+
Version int
20+
Mode string
21+
Bundles map[int64]Bundle
22+
}
23+
24+
func addBundleToList(bundle Bundle, list BundleList) {
25+
list.Bundles[bundle.CreationToken] = bundle
26+
}
27+
28+
func CreateInitialBundle(repo core.Repository) Bundle {
29+
timestamp := time.Now().UTC().Unix()
30+
bundleName := "bundle-" + fmt.Sprint(timestamp) + ".bundle"
31+
bundleFile := repo.WebDir + "/" + bundleName
32+
bundle := Bundle{
33+
URI: "./" + bundleName,
34+
Filename: bundleFile,
35+
CreationToken: timestamp,
36+
}
37+
38+
return bundle
39+
}
40+
41+
func SingletonList(bundle Bundle) BundleList {
42+
list := BundleList{1, "all", make(map[int64]Bundle)}
43+
44+
addBundleToList(bundle, list)
45+
46+
return list
47+
}
48+
49+
// Given a BundleList
50+
func WriteBundleList(list BundleList, repo core.Repository) error {
51+
listFile := repo.WebDir + "/bundle-list"
52+
jsonFile := repo.RepoDir + "/bundle-list.json"
53+
54+
// TODO: Formalize lockfile concept.
55+
f, err := os.OpenFile(listFile+".lock", os.O_WRONLY|os.O_CREATE, 0600)
56+
if err != nil {
57+
return fmt.Errorf("failure to open file: %w", err)
58+
}
59+
60+
out := bufio.NewWriter(f)
61+
62+
fmt.Fprintf(
63+
out, "[bundle]\n\tversion = %d\n\tmode = %s\n\n",
64+
list.Version, list.Mode)
65+
66+
for token, bundle := range list.Bundles {
67+
fmt.Fprintf(
68+
out, "[bundle \"%d\"]\n\turi = %s\n\tcreationToken = %d\n\n",
69+
token, bundle.URI, token)
70+
}
71+
72+
out.Flush()
73+
err = f.Close()
74+
if err != nil {
75+
return fmt.Errorf("failed to close lock file: %w", err)
76+
}
77+
78+
f, err = os.OpenFile(jsonFile+".lock", os.O_WRONLY|os.O_CREATE, 0600)
79+
if err != nil {
80+
return fmt.Errorf("failed to open JSON file: %w", err)
81+
}
82+
83+
data, jsonErr := json.Marshal(list)
84+
if jsonErr != nil {
85+
return fmt.Errorf("failed to convert list to JSON: %w", err)
86+
}
87+
88+
written := 0
89+
for written < len(data) {
90+
n, writeErr := f.Write(data[written:])
91+
if writeErr != nil {
92+
return fmt.Errorf("failed to write JSON: %w", err)
93+
}
94+
written += n
95+
}
96+
97+
f.Sync()
98+
f.Close()
99+
100+
renameErr := os.Rename(jsonFile+".lock", jsonFile)
101+
if renameErr != nil {
102+
return fmt.Errorf("failed to rename JSON file: %w", renameErr)
103+
}
104+
105+
return os.Rename(listFile+".lock", listFile)
8106
}

internal/core/paths.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package core
2+
3+
import "os"
4+
5+
func bundleroot() string {
6+
dirname, err := os.UserHomeDir()
7+
if err != nil {
8+
// TODO: respond better. For now, try creating in "/var"
9+
dirname = "/var"
10+
}
11+
12+
return dirname + "/git-bundle-server/"
13+
}
14+
15+
func webroot() string {
16+
return bundleroot() + "www/"
17+
}
18+
19+
func reporoot() string {
20+
return bundleroot() + "git/"
21+
}

internal/core/repo.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package core
2+
3+
import (
4+
"log"
5+
"os"
6+
)
7+
8+
type Repository struct {
9+
Route string
10+
RepoDir string
11+
WebDir string
12+
}
13+
14+
func GetRepository(route string) Repository {
15+
repo := reporoot() + route
16+
web := webroot() + route
17+
18+
mkdirErr := os.MkdirAll(web, os.ModePerm)
19+
if mkdirErr != nil {
20+
log.Fatal("failed to create web directory: ", mkdirErr)
21+
}
22+
23+
return Repository{
24+
Route: route,
25+
RepoDir: repo,
26+
WebDir: web,
27+
}
28+
}

0 commit comments

Comments
 (0)