Skip to content

Commit

Permalink
fetch files from given url (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
notJoon committed Sep 5, 2024
1 parent cdca53a commit b4b93c5
Show file tree
Hide file tree
Showing 8 changed files with 590 additions and 0 deletions.
37 changes: 37 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Go parameters
GOCMD=go
GOBUILD=$(GOCMD) build
GOTEST=$(GOCMD) test
GOCLEAN=$(GOCMD) clean
GOGET=$(GOCMD) get
BINARY_NAME=gnock

# Main package path
MAIN_PACKAGE=./cmd/gnock

install:
go install $(MAIN_PACKAGE)

# Build the project
all: test build

build:
$(GOBUILD) -o $(BINARY_NAME) -v $(MAIN_PACKAGE)

# Run tests
test:
$(GOTEST) -race -v ./...

# Dependencies
deps:
$(GOGET) -v ./...

# Run golangci-lint
lint:
golangci-lint run

# Format the code
fmt:
go fmt ./...

.PHONY: install build test deps lint fmt
28 changes: 28 additions & 0 deletions cmd/gnock/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package main

import (
"fmt"
"os"

"github.com/spf13/cobra"
)

func main() {
var rootCmd = &cobra.Command{Use: "gnock"}

var getCmd = &cobra.Command{
Use: "gnock get [url]",
Short: "Get a package from an given URL (example: gnock get http://github.com/...)",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {

},
}

rootCmd.AddCommand(getCmd)

if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
9 changes: 9 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module github.com/gnoswap-labs/gnock

go 1.22.2

require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/spf13/cobra v1.8.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
)
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
120 changes: 120 additions & 0 deletions internal/fetch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package internal

import (
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"

"github.com/gnoswap-labs/gnock/internal/modfile"
)

const gnoModFilename = "gno.mod"

var (
ErrInvalidURL = errors.New("invalid URL")
)

var execCommand = executeGitCommand

func executeGitCommand(clone, url, dir string) error {
cmd := exec.Command("git", clone, url, dir)
if err := cmd.Run(); err != nil {
return fmt.Errorf("failed to clone repository: %v", err)
}
return nil
}

// GetPackage fetches a package from the given URL (e.g. github.com/username/repo)
// and copies it to the target directory which declared in the gno.mod file.
func GetPackage(url string) error {
// TODO: check valid URL
parts := strings.Split(url, "/")

// pats are contains at least 3 parts
// ex: github.com/username/repo/...
// |---------|--------|-----|
// initial owner repo
if len(parts) < 3 {
return ErrInvalidURL
}

tempDir, err := os.MkdirTemp("", "gnock-*")
if err != nil {
return fmt.Errorf("failed to create temp directory: %v", err)
}
defer os.RemoveAll(tempDir)

// TODO: use universal method to clone repository
err = execCommand("clone", url, tempDir)
if err != nil {
return fmt.Errorf("failed to clone repository: %v", err)
}

return processDirectory(tempDir, "")
}

func processDirectory(dir, relpath string) error {
entries, err := os.ReadDir(dir)
if err != nil {
return fmt.Errorf("failed to rea directory %s: %v", dir, err)
}

for _, entry := range entries {
if entry.IsDir() {
err := processDirectory(filepath.Join(dir, entry.Name()), filepath.Join(relpath, entry.Name()))
if err != nil {
return err
}
} else if entry.Name() == gnoModFilename {
gnoModPath := filepath.Join(dir, gnoModFilename)
module, err := modfile.Parse(gnoModPath)
if err != nil {
return fmt.Errorf("failed to parse gno.mod file in %s: %v", relpath, err)
}

// TODO: the name of the `gno` directory can be different for each user.
// so need to set it as a variable and update via the CLI or find it automatically
destDir := filepath.Join("gno", "examples", module.Path)
if err := os.MkdirAll(destDir, 0755); err != nil {
return fmt.Errorf("failed to create destination directory %s: %v", destDir, err)
}

if err := copyDir(dir, destDir); err != nil {
return fmt.Errorf("failed to copy directory %s to %s: %v", dir, destDir, err)
}

fmt.Printf("Package %s installed successfully to %s\n", module.Path, destDir)
}
}

return nil
}

func copyDir(src string, dst string) error {
return filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}

relPath, err := filepath.Rel(src, path)
if err != nil {
return err
}

dstPath := filepath.Join(dst, relPath)

if info.IsDir() {
return os.MkdirAll(dstPath, info.Mode())
}

data, err := os.ReadFile(path)
if err != nil {
return err
}

return os.WriteFile(dstPath, data, info.Mode())
})
}
Loading

0 comments on commit b4b93c5

Please sign in to comment.