Skip to content

Commit

Permalink
deletion first implementation (#12)
Browse files Browse the repository at this point in the history
* deletion first implementation

* binary

* http.MethodDelete
  • Loading branch information
sjeandeaux committed Jan 4, 2018
1 parent 2e29883 commit 0dfd872
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 37 deletions.
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
language: go
go:
- 1.5
- 1.6
- 1.7
- 1.8
Expand Down
36 changes: 31 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,16 +1,42 @@

os=linux
arch=amd64
GOOS?=$(shell uname -s | tr '[:upper:]' '[:lower:]')
GOARCH?=amd64

test:
go test ./...
go test ./...
nexus:
docker run -d -p 8081:8081 --name nexus sonatype/nexus3

build: test
GOOS=$(os) GOARCH=$(arch) go build -ldflags " \
GOOS=$(GOOS) GOARCH=$(GOARCH) go build -ldflags " \
-X github.com/sjeandeaux/nexus-cli/information.Version=$(shell cat VERSION) \
-X github.com/sjeandeaux/nexus-cli/information.BuildTime=$(shell date +"%Y-%m-%dT%H:%M:%S") \
-X github.com/sjeandeaux/nexus-cli/information.GitCommit=$(shell git rev-parse --short HEAD) \
-X github.com/sjeandeaux/nexus-cli/information.GitDescribe=$(shell git describe --tags --always) \
-X github.com/sjeandeaux/nexus-cli/information.GitDirty=$(shell test -n "`git status --porcelain`" && echo "+CHANGES" || true)" \
-o dist/$(os)_$(arch)_nexus_cli
-o dist/$(GOOS)-$(GOARCH)-nexus-cli

upload:
touch upload.jar
go run main.go -repo=http://localhost:8081/repository/maven-releases \
-user=admin \
-password=admin123 \
-action PUT \
-file=upload.jar \
-groupID=com.jeandeaux \
-artifactID=elyne \
-version=0.1.0 \
-hash md5 \
-hash sha1

delete:
go run main.go -repo=http://localhost:8081/repository/maven-releases \
-user=admin \
-password=admin123 \
-file=upload.jar \
-action DELETE \
-groupID=com.jeandeaux \
-artifactID=elyne \
-version=0.1.0 \
-hash md5 \
-hash sha1
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# nexus-cli [![Build Status](https://travis-ci.org/sjeandeaux/nexus-cli.svg?branch=master)](https://travis-ci.org/sjeandeaux/nexus-cli)

## upload
## TODOs

* 1.0.0 refactoring model because it is the godawful mess

## nexus-cli

I share a volume where i have my upload.jar file.

Expand All @@ -23,6 +27,18 @@ docker run --link nexus:nexus -ti -v $(pwd):$(pwd):ro sjeandeaux/nexus-cli \
nexus-cli -repo=http://nexus:8081/repository/maven-releases \
-user=admin \
-password=admin123 \
-action PUT \
-file=upload.jar \
-groupID=com.jeandeaux \
-artifactID=elyne \
-version=0.1.0 \
-hash md5 \
-hash sha1

nexus-cli -repo=http://nexus:8081/repository/maven-releases \
-user=admin \
-password=admin123 \
-action DELETE \
-file=upload.jar \
-groupID=com.jeandeaux \
-artifactID=elyne \
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.4.0
0.5.0
Binary file removed dist/linux_amd64_nexus_cli
Binary file not shown.
27 changes: 23 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/sjeandeaux/nexus-cli/repositorymanager"

"os"

"github.com/sjeandeaux/nexus-cli/information"
)

Expand All @@ -29,7 +30,9 @@ type commandLineArgs struct {
urlOfRepository string
user string
password string
//file to upload
//action PUT or DELETE
action string
//file to upload or if we delete we get the extension.
file string
//groupID of artifact
groupID string
Expand All @@ -49,7 +52,8 @@ func init() {
flag.StringVar(&commandLine.urlOfRepository, "repo", "http://localhost/repository/third-party", "url of repository")
flag.StringVar(&commandLine.user, "user", "", "user for repository")
flag.StringVar(&commandLine.password, "password", "", "password for repository")
flag.StringVar(&commandLine.file, "file", "", "your file to upload on repository")
flag.StringVar(&commandLine.action, "action", "", "action PUT or DELETE")
flag.StringVar(&commandLine.file, "file", "", "your file to upload on repository or if we delete we get the extension.")
flag.StringVar(&commandLine.groupID, "groupID", "com.jeandeaux", "groupid of artifact")
flag.StringVar(&commandLine.artifactID, "artifactID", "elyne", "artifactID of artifact")
flag.StringVar(&commandLine.version, "version", "0.1.0-SNAPSHOT", "version of artifact")
Expand All @@ -59,6 +63,10 @@ func init() {

//main upload artifact
func main() {
const (
DELETE = "DELETE"
PUT = "PUT"
)
log.Logger.Println(information.Print())
repo := repositorymanager.NewRepository(commandLine.urlOfRepository, commandLine.user, commandLine.password)

Expand All @@ -67,7 +75,18 @@ func main() {
log.Logger.Fatal(err)
}

if err := repo.UploadArtifact(artifact, commandLine.hash...); err != nil {
log.Logger.Fatal(err)
switch commandLine.action {
case PUT:
if err := repo.UploadArtifact(artifact, commandLine.hash...); err != nil {
log.Logger.Fatal(err)
}

case DELETE:
if err := repo.DeleteArtifact(artifact, commandLine.hash...); err != nil {
log.Logger.Fatal(err)
}
default:
log.Logger.Fatal(fmt.Errorf("what do you want to do with %q ", commandLine.action))
}

}
80 changes: 65 additions & 15 deletions repositorymanager/repositorymanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"crypto/md5"
"crypto/sha1"
"encoding/hex"
"errors"
"fmt"
"hash"
"io"
Expand All @@ -19,13 +20,15 @@ import (

"github.com/sjeandeaux/nexus-cli/log"

"errors"
"github.com/sjeandeaux/nexus-cli/information"
)

const (
dot = "."
suffixPom = "pom"
dot = "."
suffixPom = "pom"
allReplacement = -1
slash = "/"
dash = "-"
)

//Repository where we want put the file
Expand Down Expand Up @@ -72,6 +75,27 @@ func NewRepository(url, user, password string) *Repository {

}

//DeleteArtifact deletes the artifact
//ar the artifact to delete
//hashs list of hash to delete
func (n *Repository) DeleteArtifact(ar *Artifact, hashs ...string) error {
pomURL := n.generateURL(ar, suffixPom)
if err := n.delete(pomURL); err != nil {
return err
}

fileURL := n.generateURL(ar, ar.extension())
if err := n.delete(fileURL); err != nil {
return err
}

for _, h := range hashs {
//if we can't delete hash we continue
n.deleteHash(ar, h)
}
return nil
}

//UploadArtifact upload ar on repository TODO goroutine to upload
//ar the artifact to upload
//hashs list of hash to send
Expand Down Expand Up @@ -120,12 +144,6 @@ func generateURLIssue(h string) string {
//generateURL generate the url of ar
// <url>/<groupID/<arID>/<version>/<arID>-<version>.<endOfFile>
func (n *Repository) generateURL(ar *Artifact, endOfFile string) string {
const (
allReplacement = -1
slash = "/"
dash = "-"
)

g := strings.Replace(ar.GroupID, dot, slash, allReplacement)
nameOfFile := fmt.Sprint(slash, ar.ArtifactID, dash, ar.Version, dot, endOfFile)
return fmt.Sprint(n.url, slash, g, slash, ar.ArtifactID, slash, ar.Version, nameOfFile)
Expand All @@ -147,8 +165,23 @@ func (n *Repository) uploadHash(ar *Artifact, h *repositoryHash) error {
return n.upload(hashedFile, f)
}

//deleteHash delete the hash
func (n *Repository) deleteHash(ar *Artifact, h string) error {
hashedPom := n.generateURL(ar, fmt.Sprint(suffixPom, dot, h))
if err := n.delete(hashedPom); err != nil {
return err
}

hashedFile := n.generateURL(ar, fmt.Sprint(ar.extension(), dot, h))
return n.delete(hashedFile)
}

func (n *Repository) upload(url string, data io.Reader) error {
const PUT = "PUT"
const (
PUT = "PUT"
httpSuccess = 201
)

log.Logger.Print(url)
req, _ := http.NewRequest(PUT, url, data)
if n.user != "" && n.password != "" {
Expand All @@ -161,7 +194,27 @@ func (n *Repository) upload(url string, data io.Reader) error {
}
defer res.Body.Close()

if res.StatusCode != 201 {
if res.StatusCode != httpSuccess {
return fmt.Errorf(res.Status)
}
return nil
}

func (n *Repository) delete(url string) error {
const httpSuccess = 204
log.Logger.Print(url)
req, _ := http.NewRequest(http.MethodDelete, url, nil)
if n.user != "" && n.password != "" {
req.SetBasicAuth(n.user, n.password)
}

res, err := n.client.Do(req)
if err != nil {
return err
}
defer res.Body.Close()

if res.StatusCode != httpSuccess {
return fmt.Errorf(res.Status)
}
return nil
Expand Down Expand Up @@ -212,15 +265,12 @@ type Artifact struct {

//NewArtifact create a artifact with this own pom
func NewArtifact(groupID, artifactID, version, file string) (*Artifact, error) {

if file == "" {
return nil, errors.New("You must specify a file")

}

if _, err := os.Stat(file); os.IsNotExist(err) {
return nil, err
}

a := &Artifact{
GroupID: groupID,
ArtifactID: artifactID,
Expand Down
70 changes: 60 additions & 10 deletions repositorymanager/repositorymanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func TestRepository_UploadArtifact(t *testing.T) {
file.WriteString(forFile.expected)
extension := filepath.Ext(file.Name())

ts := repositoryManagerImplementation(t, extension, &forPom, &forFile)
ts := repositoryManagerUpload(t, extension, &forPom, &forFile)
defer ts.Close()
repo := NewRepository(ts.URL, "bob", "thesponge")

Expand All @@ -92,8 +92,41 @@ func TestRepository_UploadArtifact(t *testing.T) {

}

//repositoryManagerImplementation TODO too big for what is it
func repositoryManagerImplementation(t *testing.T, extension string, forPom *call, forFile *call) *httptest.Server {
func TestRepository_DeleteArtifact(t *testing.T) {
forPom := call{
called: false,
calledSha1: false,
calledMd5: false,
}

forFile := call{
called: false,
calledSha1: false,
calledMd5: false,
}

ts := repositoryManagerDelete(t, ".jar", &forPom, &forFile)
defer ts.Close()
repo := NewRepository(ts.URL, "bob", "thesponge")

a, _ := NewArtifact(groupID, artifactID, version, "bob.jar")
err := repo.DeleteArtifact(a, "sha1", "md5", "not-found")
if err != nil {
t.Fatal(err)
}

if !forFile.allIsCalled() {
t.Errorf("Problem we are waiting more calls %v", forFile)
}

if !forPom.allIsCalled() {
t.Errorf("Problem we are waiting more calls %v", forPom)
}

}

//repositoryManagerUpload TODO too big for what is it
func repositoryManagerUpload(t *testing.T, extension string, forPom *call, forFile *call) *httptest.Server {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(201)
bodyBytes, err := ioutil.ReadAll(r.Body)
Expand Down Expand Up @@ -154,6 +187,30 @@ func repositoryManagerImplementation(t *testing.T, extension string, forPom *cal
return ts
}

//repositoryManagerDelete TODO too big for what is it
func repositoryManagerDelete(t *testing.T, extension string, forPom *call, forFile *call) *httptest.Server {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(204)
path := "/com/jeandeaux/elyne/0.1.0-SNAPSHOT/elyne-0.1.0-SNAPSHOT"
switch r.URL.Path {
case fmt.Sprint(path, ".pom"):
forPom.called = true
case fmt.Sprint(path, ".pom.sha1"):
forPom.calledSha1 = true
case fmt.Sprint(path, ".pom.md5"):
forPom.calledMd5 = true
case fmt.Sprint(path, extension):
forFile.called = true
case fmt.Sprint(path, extension, ".sha1"):
forFile.calledSha1 = true
case fmt.Sprint(path, extension, ".md5"):
forFile.calledMd5 = true
}

}))
return ts
}

func TestArtifact_writePom(t *testing.T) {
a := &Artifact{GroupID: groupID, ArtifactID: artifactID, Version: version}
actualBytes, err := a.writePom()
Expand Down Expand Up @@ -193,13 +250,6 @@ func TestNewArtifact_Ok(t *testing.T) {
}
}

func TestNewArtifact_Ko_Because_Not_Found(t *testing.T) {
_, err := NewArtifact(groupID, artifactID, version, "<not found>")
if err == nil {
t.Fatal("I want a error")
}
}

func TestNewArtifact_Ko_Because_Name_Empty(t *testing.T) {
_, err := NewArtifact(groupID, artifactID, version, "")
if err == nil {
Expand Down

0 comments on commit 0dfd872

Please sign in to comment.