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

Commit

Permalink
Merge branch 'release/1.0.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
NatoBoram committed Aug 1, 2019
2 parents d24cef6 + 5e24977 commit 8135ab9
Show file tree
Hide file tree
Showing 36 changed files with 826 additions and 192 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
web/templates
rice-box.go
build/

# Created by https://www.gitignore.io/api/go,linux,macos,windows,visualstudiocode
# Edit at https://www.gitignore.io/?templates=go,linux,macos,windows,visualstudiocode
Expand Down
8 changes: 4 additions & 4 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
image: golang:1.12.7

before_script:
- go get -u -v gitlab.com/NatoBoram/git-to-ipns
- go get -u -v github.com/GeertJohan/go.rice/rice
- go get -u -v gitlab.com/NatoBoram/git-to-ipfs
- rice embed-go
- go clean

build:
stage: build
script:
- rice embed-go
- go build ./...
- go build

test:
stage: test
script:
- go test ./...
- go test -v -cover -race ./...

after_script:
- go clean
36 changes: 36 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,42 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/) and this

### Security

## [1.0.1] - 2019-08-01

Patches from [github.com/Permaweb/Host/](https://github.com/Permaweb/Host/).

### Added

* Added the following API endpoints :

| Endpoint | Method | Description |
| ------------------ | -------- | ------------------------ |
| `/api/repos` | `GET` | List of all repositories |
| `/api/repos` | `POST` | Create a repository |
| `/api/repos/{url}` | `GET` | Get this repository |
| `/api/repos/{url}` | `DELETE` | Delete this repository |

* Added a list of repositories.
* Added **Delete** buttons on the list of repositories.
* Adds a few selected peers to its swarm on startup for faster discovery.
* Added a few unit tests.
* Cross-compile script with lots of obscure operating systems and architectures.

### Changed

* Spinners are now blue when they're actually doing something and black when they're not.
* Changed name from [Git to IPFS](https://gitlab.com/NatoBoram/git-to-ipfs) to [Git to IPNS](https://gitlab.com/NatoBoram/git-to-ipns).
* Change config directory to `~/.config/gipns`.

### Removed

* Removed the following API endpoint :
* `/api/add`

### Fixed

* Fixed some potential issues when refreshing old repositories that contain errors.

## [1.0.0] - 2019-07-25

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.
Expand Down
28 changes: 19 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Git to IPNS

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

Takes a Git repository and throws it on IPNS.

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

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

```bash
./tools/dependencies.sh
./scripts/dependencies.sh
```

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

### Installation

To install this project, run [tools/install.sh](tools/install.sh).
To install this project, run [scripts/install.sh](scripts/install.sh).

```bash
./tools/install.sh
./scripts/install.sh
```

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

### Running

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

```bash
./tools/run.sh
./scripts/run.sh
```

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

### Building

To build this project, run [scripts/cross-compile.sh](scripts/cross-compile.sh).

```bash
./scripts/cross-compile.sh
```

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.
125 changes: 43 additions & 82 deletions badger.go
Original file line number Diff line number Diff line change
@@ -1,121 +1,82 @@
// Low-level operations on the database.

package main

import (
"fmt"

badger "github.com/dgraph-io/badger"
"golang.org/x/xerrors"
)

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) {
err = db.View(func(txn *badger.Txn) (err error) {

// Select from URL
item, err := txn.Get([]byte(link))
if err == badger.ErrKeyNotFound {
repo, err := newRepo(db, link)
if err != nil {
return xerrors.Errorf("Couldn't add a new repo : %w", err)
}
ch <- repo
} else if err != nil {
return xerrors.Errorf("Couldn't select an URL : %w", err)
}

// Get value
err = item.Value(func(bytes []byte) (err error) {

// Decode
repo, err := decodeRepo(bytes)
if err != nil {
return xerrors.Errorf("Couldn't decode a repo : %w", err)
}

// Execute the callback only if there's no error.
repo, err = oldRepo(db, repo)
if err != nil {
return xerrors.Errorf("Couldn't refresh an old repo : %w", err)
}
ch <- repo

// Unreachable code
return nil
})

if err != nil {
return xerrors.Errorf("Couldn't get an URL's value : %w", err)
}

return nil
})

if err != nil {
return xerrors.Errorf("Couldn't create a view from an URL : %w", err)
}

return nil
}

func (repo Repo) save(db *badger.DB) (err error) {
err = db.Update(func(txn *badger.Txn) error {
func badgerSet(db *badger.DB, repo Repo) error {
return db.Update(func(txn *badger.Txn) error {

// Encode
bytes, err := repo.encode()
if err != nil {
return xerrors.Errorf("Couldn't encode a repo : %w", err)
return err
}

// Save
err = txn.Set([]byte(repo.URL), bytes)
if err != nil {
return xerrors.Errorf("Couldn't save a repo : %w", err)
}

return nil
return err
})

if err != nil {
return xerrors.Errorf("Couldn't create an update transaction : %w", err)
}

return nil
}

func getRepos(db *badger.DB, ch chan Repo) error {

// Create a view
// badgerList populates a channel with every single keys inside the Badger database.
func badgerList(db *badger.DB, ch chan repoerr) error {
err := db.View(func(txn *badger.Txn) error {

it := txn.NewIterator(badger.DefaultIteratorOptions)
defer it.Close()
defer close(ch)

for it.Rewind(); it.Valid(); it.Next() {
item := it.Item()

err := item.Value(func(v []byte) error {

repo, err := decodeRepo(v)
if err != nil {
return xerrors.Errorf("Couldn't decode a repo : %w", err)
ch <- repoerr{
repo: repo,
err: err,
}

ch <- repo

return nil
return err
})

// Continue even if there's an error
if err != nil {
fmt.Println("Couldn't get a value.")
fmt.Println("Couldn't get the value of an item.")
fmt.Println(err.Error())
}
}

return nil
})
if err != nil {
return xerrors.Errorf("Couldn't create a view : %w", err)
}

return nil
close(ch)
return err
}

// Get a repository from its URL.
//
// Can return `badger.ErrKeyNotFound`.
func badgerGet(db *badger.DB, link string, ch chan Repo) error {
err := db.View(func(txn *badger.Txn) error {
item, err := txn.Get([]byte(link))
if err != nil {
return err
}

return item.Value(func(bytes []byte) error {
repo, err := decodeRepo(bytes)
ch <- repo
return err
})
})

close(ch)
return err
}

func badgerDelete(db *badger.DB, link string) error {
return db.Update(func(txn *badger.Txn) error {
return txn.Delete([]byte(link))
})
}
33 changes: 33 additions & 0 deletions commands.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Bash commands to be executed by the application.

package main

import (
Expand Down Expand Up @@ -51,6 +53,19 @@ func ipfsKeyGen(link string) (out []byte, err error) {
)
}

func ipfsKeyRm(key string) (out []byte, err error) {
return run(
exec.Command("ipfs", "key", "rm", key),
".",
"Couldn't remove a key.",
aurora.Bold("Command :"), "ipfs", "key", "rm", key,
)
}

func ipfsKeyRmName(name string) (out []byte, err error) {
return ipfsKeyRm(url.PathEscape(name))
}

func ipfsNamePublish(key string, ipfs string) (out []byte, err error) {
return run(
exec.Command("ipfs", "name", "publish", "--key", key, "--quieter", "/ipfs/"+ipfs),
Expand Down Expand Up @@ -86,3 +101,21 @@ func ipfsClusterRm(ipfs string) (out []byte, err error) {
aurora.Bold("Command :"), "ipfs-cluster-ctl", "pin", "rm", aurora.Cyan(ipfs),
)
}

func rm(uuid string) (out []byte, err error) {
return run(
exec.Command("rm", "--force", "--recursive", uuid),
dirHome+dirGit,
"Couldn't delete the repository.",
aurora.Bold("Command :"), "rm", "--force", "--recursive", uuid,
)
}

func ipfsSwarmConnect(address string) (out []byte, err error) {
return run(
exec.Command("ipfs", "swarm", "connect", address),
".",
"Couldn't connect to "+address+".",
aurora.Bold("Command :"), "ipfs", "swarm", "connect", aurora.Cyan(address),
)
}
20 changes: 20 additions & 0 deletions commands_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package main

import (
"os/exec"
"testing"

"github.com/logrusorgru/aurora"
)

func TestRun(t *testing.T) {
_, err := run(
exec.Command("go", "help"),
".",
"Couldn't run the Go command.",
aurora.Bold("Command :"), "go", "help",
)
if err != nil {
t.Errorf("Failed to run a command: %s.", err.Error())
}
}
10 changes: 9 additions & 1 deletion consts.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// Constants.

package main

import "os"

// Relative paths for the whole application.
// Use them with `dirHome`.
const (
dirConfig = "/.config/gi"
dirConfig = "/.config/gipns"
dirBadger = dirConfig + "/badger"
dirGit = dirConfig + "/git"
)
Expand All @@ -21,3 +23,9 @@ const (
speed = 10 * 1024 * 1024
seconds = 60
)

// Public Gateways
const (
pgPermaweb = "/dnsaddr/permaweb.io"
pgLibp2p = "/dnsaddr/bootstrap.libp2p.io"
)
Loading

0 comments on commit 8135ab9

Please sign in to comment.