Skip to content
This repository was archived by the owner on Apr 21, 2024. It is now read-only.

Commit 8135ab9

Browse files
committed
Merge branch 'release/1.0.1'
2 parents d24cef6 + 5e24977 commit 8135ab9

36 files changed

+826
-192
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
web/templates
22
rice-box.go
3+
build/
34

45
# Created by https://www.gitignore.io/api/go,linux,macos,windows,visualstudiocode
56
# Edit at https://www.gitignore.io/?templates=go,linux,macos,windows,visualstudiocode

.gitlab-ci.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
image: golang:1.12.7
22

33
before_script:
4+
- go get -u -v gitlab.com/NatoBoram/git-to-ipns
45
- go get -u -v github.com/GeertJohan/go.rice/rice
5-
- go get -u -v gitlab.com/NatoBoram/git-to-ipfs
6+
- rice embed-go
67
- go clean
78

89
build:
910
stage: build
1011
script:
11-
- rice embed-go
12-
- go build ./...
12+
- go build
1313

1414
test:
1515
stage: test
1616
script:
17-
- go test ./...
17+
- go test -v -cover -race ./...
1818

1919
after_script:
2020
- go clean

CHANGELOG.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,42 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/) and this
1818

1919
### Security
2020

21+
## [1.0.1] - 2019-08-01
22+
23+
Patches from [github.com/Permaweb/Host/](https://github.com/Permaweb/Host/).
24+
25+
### Added
26+
27+
* Added the following API endpoints :
28+
29+
| Endpoint | Method | Description |
30+
| ------------------ | -------- | ------------------------ |
31+
| `/api/repos` | `GET` | List of all repositories |
32+
| `/api/repos` | `POST` | Create a repository |
33+
| `/api/repos/{url}` | `GET` | Get this repository |
34+
| `/api/repos/{url}` | `DELETE` | Delete this repository |
35+
36+
* Added a list of repositories.
37+
* Added **Delete** buttons on the list of repositories.
38+
* Adds a few selected peers to its swarm on startup for faster discovery.
39+
* Added a few unit tests.
40+
* Cross-compile script with lots of obscure operating systems and architectures.
41+
42+
### Changed
43+
44+
* Spinners are now blue when they're actually doing something and black when they're not.
45+
* Changed name from [Git to IPFS](https://gitlab.com/NatoBoram/git-to-ipfs) to [Git to IPNS](https://gitlab.com/NatoBoram/git-to-ipns).
46+
* Change config directory to `~/.config/gipns`.
47+
48+
### Removed
49+
50+
* Removed the following API endpoint :
51+
* `/api/add`
52+
53+
### Fixed
54+
55+
* Fixed some potential issues when refreshing old repositories that contain errors.
56+
2157
## [1.0.0] - 2019-07-25
2258

2359
Initial release. It has a web interface, can `git clone` repositories, add them to IPFS Cluster, create IPFS keys, then add the repo to IPNS.

README.md

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Git to IPNS
22

3-
[![Pipeline Status](https://gitlab.com/NatoBoram/git-to-ipfs/badges/master/pipeline.svg)](https://gitlab.com/NatoBoram/git-to-ipfs/commits/master)
4-
[![Go Report Card](https://goreportcard.com/badge/gitlab.com/NatoBoram/git-to-ipfs)](https://goreportcard.com/report/gitlab.com/NatoBoram/git-to-ipfs)
5-
[![GoDoc](https://godoc.org/gitlab.com/NatoBoram/git-to-ipfs?status.svg)](https://godoc.org/gitlab.com/NatoBoram/git-to-ipfs)
3+
[![Pipeline Status](https://gitlab.com/NatoBoram/git-to-ipns/badges/master/pipeline.svg)](https://gitlab.com/NatoBoram/git-to-ipns/commits/master)
4+
[![Go Report Card](https://goreportcard.com/badge/gitlab.com/NatoBoram/git-to-ipns)](https://goreportcard.com/report/gitlab.com/NatoBoram/git-to-ipns)
5+
[![GoDoc](https://godoc.org/gitlab.com/NatoBoram/git-to-ipns?status.svg)](https://godoc.org/gitlab.com/NatoBoram/git-to-ipns)
66

77
Takes a Git repository and throws it on IPNS.
88

@@ -13,10 +13,10 @@ Takes a Git repository and throws it on IPNS.
1313
Building the program requires `go`, `npm` and `ipfs`. Don't forget to add `~/go/bin` to your `$PATH`.
1414

1515
This project uses [Hogan.js](https://twitter.github.io/hogan.js/) and [go.rice](https://github.com/GeertJohan/go.rice).
16-
Their installation is scripted in [tools/dependencies.sh](tools/dependencies.sh).
16+
Their installation is scripted in [scripts/dependencies.sh](scripts/dependencies.sh).
1717

1818
```bash
19-
./tools/dependencies.sh
19+
./scripts/dependencies.sh
2020
```
2121

2222
Please note that `npm` requires root to install packages globally.
@@ -25,20 +25,30 @@ Running the program requires `ipfs-cluster-ctl`. Make sure `ipfs-cluster-service
2525

2626
### Installation
2727

28-
To install this project, run [tools/install.sh](tools/install.sh).
28+
To install this project, run [scripts/install.sh](scripts/install.sh).
2929

3030
```bash
31-
./tools/install.sh
31+
./scripts/install.sh
3232
```
3333

3434
It will publish the necessary files to IPFS, generate the templates and embed the web interface inside the binary.
3535

3636
### Running
3737

38-
To run this project without installing it, run [tools/run.sh](tools/run.sh).
38+
To run this project without installing it, run [scripts/run.sh](scripts/run.sh).
3939

4040
```bash
41-
./tools/run.sh
41+
./scripts/run.sh
4242
```
4343

4444
It will publish the necessary files to IPFS, generate the templates and embed the web interface inside the binary.
45+
46+
### Building
47+
48+
To build this project, run [scripts/cross-compile.sh](scripts/cross-compile.sh).
49+
50+
```bash
51+
./scripts/cross-compile.sh
52+
```
53+
54+
It will publish the necessary files to IPFS, generate the templates, embed the web interface inside the binary, then compile the program for every single operating system and architecture supported by Go. Lots of them will fail, but the result is ready to be published.

badger.go

Lines changed: 43 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,121 +1,82 @@
1+
// Low-level operations on the database.
2+
13
package main
24

35
import (
46
"fmt"
57

68
badger "github.com/dgraph-io/badger"
7-
"golang.org/x/xerrors"
89
)
910

10-
func getFromURL(db *badger.DB, link string, ch chan Repo, oldRepo func(*badger.DB, Repo) (Repo, error), newRepo func(*badger.DB, string) (Repo, error)) (err error) {
11-
err = db.View(func(txn *badger.Txn) (err error) {
12-
13-
// Select from URL
14-
item, err := txn.Get([]byte(link))
15-
if err == badger.ErrKeyNotFound {
16-
repo, err := newRepo(db, link)
17-
if err != nil {
18-
return xerrors.Errorf("Couldn't add a new repo : %w", err)
19-
}
20-
ch <- repo
21-
} else if err != nil {
22-
return xerrors.Errorf("Couldn't select an URL : %w", err)
23-
}
24-
25-
// Get value
26-
err = item.Value(func(bytes []byte) (err error) {
27-
28-
// Decode
29-
repo, err := decodeRepo(bytes)
30-
if err != nil {
31-
return xerrors.Errorf("Couldn't decode a repo : %w", err)
32-
}
33-
34-
// Execute the callback only if there's no error.
35-
repo, err = oldRepo(db, repo)
36-
if err != nil {
37-
return xerrors.Errorf("Couldn't refresh an old repo : %w", err)
38-
}
39-
ch <- repo
40-
41-
// Unreachable code
42-
return nil
43-
})
44-
45-
if err != nil {
46-
return xerrors.Errorf("Couldn't get an URL's value : %w", err)
47-
}
48-
49-
return nil
50-
})
51-
52-
if err != nil {
53-
return xerrors.Errorf("Couldn't create a view from an URL : %w", err)
54-
}
55-
56-
return nil
57-
}
58-
59-
func (repo Repo) save(db *badger.DB) (err error) {
60-
err = db.Update(func(txn *badger.Txn) error {
11+
func badgerSet(db *badger.DB, repo Repo) error {
12+
return db.Update(func(txn *badger.Txn) error {
6113

6214
// Encode
6315
bytes, err := repo.encode()
6416
if err != nil {
65-
return xerrors.Errorf("Couldn't encode a repo : %w", err)
17+
return err
6618
}
6719

6820
// Save
6921
err = txn.Set([]byte(repo.URL), bytes)
70-
if err != nil {
71-
return xerrors.Errorf("Couldn't save a repo : %w", err)
72-
}
73-
74-
return nil
22+
return err
7523
})
76-
77-
if err != nil {
78-
return xerrors.Errorf("Couldn't create an update transaction : %w", err)
79-
}
80-
81-
return nil
8224
}
8325

84-
func getRepos(db *badger.DB, ch chan Repo) error {
85-
86-
// Create a view
26+
// badgerList populates a channel with every single keys inside the Badger database.
27+
func badgerList(db *badger.DB, ch chan repoerr) error {
8728
err := db.View(func(txn *badger.Txn) error {
88-
8929
it := txn.NewIterator(badger.DefaultIteratorOptions)
9030
defer it.Close()
91-
defer close(ch)
92-
9331
for it.Rewind(); it.Valid(); it.Next() {
9432
item := it.Item()
95-
9633
err := item.Value(func(v []byte) error {
97-
9834
repo, err := decodeRepo(v)
99-
if err != nil {
100-
return xerrors.Errorf("Couldn't decode a repo : %w", err)
35+
ch <- repoerr{
36+
repo: repo,
37+
err: err,
10138
}
10239

103-
ch <- repo
104-
105-
return nil
40+
return err
10641
})
10742

43+
// Continue even if there's an error
10844
if err != nil {
109-
fmt.Println("Couldn't get a value.")
45+
fmt.Println("Couldn't get the value of an item.")
11046
fmt.Println(err.Error())
11147
}
11248
}
11349

11450
return nil
11551
})
116-
if err != nil {
117-
return xerrors.Errorf("Couldn't create a view : %w", err)
118-
}
11952

120-
return nil
53+
close(ch)
54+
return err
55+
}
56+
57+
// Get a repository from its URL.
58+
//
59+
// Can return `badger.ErrKeyNotFound`.
60+
func badgerGet(db *badger.DB, link string, ch chan Repo) error {
61+
err := db.View(func(txn *badger.Txn) error {
62+
item, err := txn.Get([]byte(link))
63+
if err != nil {
64+
return err
65+
}
66+
67+
return item.Value(func(bytes []byte) error {
68+
repo, err := decodeRepo(bytes)
69+
ch <- repo
70+
return err
71+
})
72+
})
73+
74+
close(ch)
75+
return err
76+
}
77+
78+
func badgerDelete(db *badger.DB, link string) error {
79+
return db.Update(func(txn *badger.Txn) error {
80+
return txn.Delete([]byte(link))
81+
})
12182
}

commands.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// Bash commands to be executed by the application.
2+
13
package main
24

35
import (
@@ -51,6 +53,19 @@ func ipfsKeyGen(link string) (out []byte, err error) {
5153
)
5254
}
5355

56+
func ipfsKeyRm(key string) (out []byte, err error) {
57+
return run(
58+
exec.Command("ipfs", "key", "rm", key),
59+
".",
60+
"Couldn't remove a key.",
61+
aurora.Bold("Command :"), "ipfs", "key", "rm", key,
62+
)
63+
}
64+
65+
func ipfsKeyRmName(name string) (out []byte, err error) {
66+
return ipfsKeyRm(url.PathEscape(name))
67+
}
68+
5469
func ipfsNamePublish(key string, ipfs string) (out []byte, err error) {
5570
return run(
5671
exec.Command("ipfs", "name", "publish", "--key", key, "--quieter", "/ipfs/"+ipfs),
@@ -86,3 +101,21 @@ func ipfsClusterRm(ipfs string) (out []byte, err error) {
86101
aurora.Bold("Command :"), "ipfs-cluster-ctl", "pin", "rm", aurora.Cyan(ipfs),
87102
)
88103
}
104+
105+
func rm(uuid string) (out []byte, err error) {
106+
return run(
107+
exec.Command("rm", "--force", "--recursive", uuid),
108+
dirHome+dirGit,
109+
"Couldn't delete the repository.",
110+
aurora.Bold("Command :"), "rm", "--force", "--recursive", uuid,
111+
)
112+
}
113+
114+
func ipfsSwarmConnect(address string) (out []byte, err error) {
115+
return run(
116+
exec.Command("ipfs", "swarm", "connect", address),
117+
".",
118+
"Couldn't connect to "+address+".",
119+
aurora.Bold("Command :"), "ipfs", "swarm", "connect", aurora.Cyan(address),
120+
)
121+
}

commands_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package main
2+
3+
import (
4+
"os/exec"
5+
"testing"
6+
7+
"github.com/logrusorgru/aurora"
8+
)
9+
10+
func TestRun(t *testing.T) {
11+
_, err := run(
12+
exec.Command("go", "help"),
13+
".",
14+
"Couldn't run the Go command.",
15+
aurora.Bold("Command :"), "go", "help",
16+
)
17+
if err != nil {
18+
t.Errorf("Failed to run a command: %s.", err.Error())
19+
}
20+
}

consts.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1+
// Constants.
2+
13
package main
24

35
import "os"
46

57
// Relative paths for the whole application.
68
// Use them with `dirHome`.
79
const (
8-
dirConfig = "/.config/gi"
10+
dirConfig = "/.config/gipns"
911
dirBadger = dirConfig + "/badger"
1012
dirGit = dirConfig + "/git"
1113
)
@@ -21,3 +23,9 @@ const (
2123
speed = 10 * 1024 * 1024
2224
seconds = 60
2325
)
26+
27+
// Public Gateways
28+
const (
29+
pgPermaweb = "/dnsaddr/permaweb.io"
30+
pgLibp2p = "/dnsaddr/bootstrap.libp2p.io"
31+
)

0 commit comments

Comments
 (0)