Adding command line options

This commit is contained in:
OLUWADAMILOLA OKUSANYA 2023-06-30 15:06:46 -04:00
parent e3e81130ba
commit cb52ddab05
16 changed files with 751 additions and 274 deletions

26
cmd/gosimplenpm/conf.go Normal file
View File

@ -0,0 +1,26 @@
package gosimplenpm
import (
"fmt"
"gosimplenpm/config"
"os"
"github.com/spf13/cobra"
)
var configCmd = &cobra.Command{
Use: "config",
Aliases: []string{"conf"},
Short: "Display the config file",
Run: func(_ *cobra.Command, _ []string) {
err := config.PrintConfigFile()
if err != nil {
fmt.Printf("Error printing config: %+v\n", err)
os.Exit(1)
}
},
}
func init() {
rootCmd.AddCommand(configCmd)
}

83
cmd/gosimplenpm/root.go Normal file
View File

@ -0,0 +1,83 @@
package gosimplenpm
import (
"fmt"
"gosimplenpm/config"
"gosimplenpm/handler"
"os"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
var rootCmd = &cobra.Command{
Use: "gosimplenpm",
Short: "Gosimplenpm is an implementation of npm registry server",
Long: `Gosimplenpm is an implemenation of npm registry server.
It creates the repository to host all your private npm repos. It can
serve the npm packages offline.
Documentation about the npm private registry:
https://docs.npmjs.com/packages-and-modules
`,
Run: func(_ *cobra.Command, _ []string) {
err := config.VerifyConfig()
if err != nil {
fmt.Printf("Error verifying config: %+v\n", err)
os.Exit(1)
}
var cfg config.Config
err = config.LoadOrCreateConfig(&cfg)
if err != nil {
fmt.Printf("Error loading config: %+v\n", err)
os.Exit(1)
}
lvl, err := logrus.ParseLevel(cfg.LogLevel)
if err != nil {
fmt.Printf("%+v", err)
os.Exit(1)
}
log := &logrus.Logger{
Out: os.Stdout,
Level: lvl,
Formatter: &logrus.TextFormatter{
FullTimestamp: true,
TimestampFormat: "2009-01-02 15:15:15",
},
}
app := &handler.Application{
Conf: cfg,
Logger: log,
}
fmt.Println("\n Server is starting....")
err = app.Start()
fmt.Println("Why!")
if err != nil {
fmt.Printf("Server start up error: %+v\n", err)
os.Exit(1)
}
},
}
func Execute() {
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}
func init() {
rootCmd.CompletionOptions.HiddenDefaultCmd = true
// hide help command
rootCmd.SetHelpCommand(&cobra.Command{Hidden: true})
// hide help flag
rootCmd.PersistentFlags().BoolP("help", "h", false, "This help")
rootCmd.PersistentFlags().Lookup("help").Hidden = true
// TODO: get some variables from flags
rootCmd.Flags().StringVarP(&config.HTTPListen, "listen", "l", config.HTTPListen, "HTTP bind interface and port for server")
_ = rootCmd.MarkFlagRequired("listen")
rootCmd.Flags().BoolVarP(&config.CanLog, "verbose", "v", config.CanLog, "Logging level for server")
rootCmd.Flags().StringVar(&config.NpmRepoDir, "repodir", config.NpmRepoDir, "Repo dir to house published packages")
}

View File

@ -1,36 +0,0 @@
package main
import (
"gosimplenpm/cmd/npmregserver"
"gosimplenpm/config"
"net/http"
"os"
"github.com/sirupsen/logrus"
)
func main() {
log := &logrus.Logger{
Out: os.Stdout,
Level: logrus.DebugLevel,
Formatter: &logrus.TextFormatter{
FullTimestamp: true,
TimestampFormat: "2009-01-02 15:15:15",
},
}
var cfg config.Config
err := config.LoadConfiguration("userdata/config.json", &cfg)
if err != nil {
log.Fatalf("Config is not loaded: %+v\n", err)
}
app := &npmregserver.Application{
Conf: cfg,
Logger: log,
}
log.Infoln("Starting server on port 4000")
err = http.ListenAndServe(":4000", app.Routes())
log.Fatal(err)
}

View File

@ -1,36 +0,0 @@
package npmregserver
import (
"gosimplenpm/config"
"gosimplenpm/handler"
"gosimplenpm/middlewares"
"net/http"
"github.com/gorilla/mux"
"github.com/sirupsen/logrus"
)
type Application struct {
Logger *logrus.Logger
Conf config.Config
}
func (app *Application) Routes() *mux.Router {
// Need to use UseEncodedPath as shown here https://github.com/gorilla/mux/blob/master/mux.go#L269
m := mux.NewRouter().StrictSlash(true).UseEncodedPath()
m.Use(middlewares.LogMiddleware(app.Logger))
// main handler
m.HandleFunc("/{name}", handler.Get).Methods("GET")
m.HandleFunc("/{name}", middlewares.AuthMiddleware(app.Conf)(handler.Publish)).Methods("PUT")
// tar handlers
m.HandleFunc("/{name}/-/{tar}", handler.Tar).Methods("GET")
// tag handlers
m.HandleFunc("/-/package/{name}/dist-tags/{tag}", middlewares.AuthMiddleware(app.Conf)(handler.DistTagDelete(app.Logger))).Methods("DELETE")
m.HandleFunc("/-/package/{name}/dist-tags/{tag}", middlewares.AuthMiddleware(app.Conf)(handler.DistTagPut(app.Logger))).Methods("PUT")
m.HandleFunc("/-/package/{name}/dist-tags", handler.DistTagGet(app.Logger)).Methods("GET")
m.NotFoundHandler = http.HandlerFunc(handler.NotFound)
return m
}

View File

@ -1,36 +1,316 @@
package config package config
import ( import (
"bufio"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io"
"net"
"os" "os"
"path/filepath" "path"
"golang.org/x/crypto/bcrypt"
)
var (
// File to store the app configuration, like username, password, token, repo dir, logging level
ConfigFilePath string
// Repo dir
NpmRepoDir string
// HTTPListen
HTTPListen string
// Set Verbose Logging
CanLog bool
// Logging Level
LoggingLvl string
// Username
RegUser string
// Password
RegPwd string
) )
type Config struct { type Config struct {
Token string `json:"token"` Token string `json:"token"`
RepoDir string `json:"repoDir"`
IpAddress string `json:"ipAddress"`
LogLevel string `json:"logLevel"`
} }
func LoadConfiguration(file string, config *Config) error { func checkIfCorrectIPPort(s string) bool {
filePath, err := filepath.Abs(file) host, port, _ := net.SplitHostPort(s)
if host == "" || port == "" {
return false
}
if net.ParseIP(host) != nil {
return true
}
_, err := net.ResolveIPAddr("ip", host)
return err == nil
}
func VerifyConfig() error {
if !checkIfCorrectIPPort(HTTPListen) {
return errors.New("ip address should be in the format of <ip>:<port>")
}
// Check if config file exists
dirname, err := os.UserHomeDir()
if err != nil { if err != nil {
fmt.Printf("File repo not found: +%v\n", err)
return err return err
} }
configFile, err := os.Open(filePath) configDirPath, err := checkOrCreateConfigDir(dirname, true)
// From https://stackoverflow/a/76287159
defer func() {
err = errors.Join(err, configFile.Close())
if err != nil { if err != nil {
fmt.Printf("File cannot be closed: +%v\n", err)
}
}()
if err != nil {
fmt.Printf("File cannot be opened: +%v\n", err)
return err return err
} }
json.NewDecoder(configFile).Decode(config)
fmt.Println("Json loaded") ConfigFilePath = path.Join(configDirPath, "config.json")
if NpmRepoDir == "" {
NpmRepoDir = path.Join(dirname, ".gosimplenpm", "registry")
err := checkOrCreateRepoDir(NpmRepoDir)
if err != nil {
return err
}
} else if NpmRepoDir != "" {
err := checkOrCreateRepoDir(NpmRepoDir)
if err != nil {
return err
}
}
if CanLog {
LoggingLvl = "DEBUG"
fmt.Println("\n Enabled debug logging")
} else {
LoggingLvl = "INFO"
}
return nil
}
func checkOrCreateConfigDir(fp string, canCreate bool) (string, error) {
configDirPath := path.Join(fp, ".gosimplenpm", "config")
ok := isDir(configDirPath)
if !ok && canCreate {
err := os.MkdirAll(configDirPath, os.ModePerm)
if err != nil {
return "", err
}
}
if !ok && !canCreate {
return "", nil
}
return configDirPath, nil
}
func checkOrCreateRepoDir(repoDirPath string) error {
ok := isDir(repoDirPath)
if !ok {
err := os.MkdirAll(repoDirPath, os.ModePerm)
if err != nil {
return err
}
}
return nil
}
func createConfig(cfg *Config, recreate bool) error {
var scanner *bufio.Scanner
if recreate {
fmt.Println("\nNew config variables. Saving...")
} else {
fmt.Println("\nConfig file is not found. Creating...")
}
configFile, err := os.Create(ConfigFilePath)
if err != nil {
return err
}
defer configFile.Close()
cfg.IpAddress = HTTPListen
cfg.LogLevel = LoggingLvl
// Get username
if cfg.Token == "" {
fmt.Println("Enter your username: ")
scanner = bufio.NewScanner(os.Stdin)
scanner.Scan()
err = scanner.Err()
if err != nil {
return err
}
RegUser = scanner.Text()
fmt.Println("Enter your password: ")
scanner = bufio.NewScanner(os.Stdin)
scanner.Scan()
err = scanner.Err()
if err != nil {
return err
}
RegPwd = scanner.Text()
token, err := generateAuthToken()
if err != nil {
return err
}
cfg.Token = token
}
fmt.Printf("The npm authToken is %s.\n", cfg.Token)
err = json.NewEncoder(configFile).Encode(cfg)
if err != nil {
return err
}
return nil
}
func loadConfig(cfg *Config) error {
configFile, err := os.Open(ConfigFilePath)
if err != nil {
return err
}
defer configFile.Close()
err = json.NewDecoder(configFile).Decode(cfg)
if err != nil {
return err
}
return nil
}
func LoadOrCreateConfig(cfg *Config) error {
var err error
ok := isFile(ConfigFilePath)
// If file is not found
if !ok {
err = createConfig(cfg, false)
if err != nil {
return err
}
}
if ok {
// File is found
err = loadConfig(cfg)
if err != nil {
return err
}
if cfg.Token == "" || cfg.IpAddress != HTTPListen || cfg.LogLevel != LoggingLvl || cfg.RepoDir != NpmRepoDir {
// recreate the config file
err = createConfig(cfg, true)
if err != nil {
return err
}
}
}
return err
}
func isFile(fp string) bool {
info, err := os.Stat(fp)
if os.IsNotExist(err) || !info.Mode().IsRegular() {
return false
}
return true
}
func isDir(fp string) bool {
info, err := os.Stat(fp)
if os.IsNotExist(err) || !info.IsDir() {
return false
}
return true
}
// Hash password
func hashPassword(password string) (string, error) {
// Convert password string to byte slice
var passwordBytes = []byte(password)
// Hash password with Bcrypt's min cost
hashedPasswordBytes, err := bcrypt.GenerateFromPassword(passwordBytes, bcrypt.MinCost)
return string(hashedPasswordBytes), err
}
// Check if two passwords match using Bcrypt's CompareHashAndPassword
// which return nil on success and an error on failure.
// func doPasswordsMatch(hashedPassword, currPassword string) bool {
// err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(currPassword))
// return err == nil
// }
func generateAuthToken() (string, error) {
hashed, err := hashPassword(RegPwd)
if err != nil {
return "", err
}
token := fmt.Sprintf("%s::%s", RegUser, hashed)
return token, nil
}
func PrintConfigFile() error {
// Check if config file exists
dirname, err := os.UserHomeDir()
if err != nil {
return err
}
configDirPath, err := checkOrCreateConfigDir(dirname, false)
if err != nil {
return err
}
if configDirPath == "" {
return errors.New("config dir is not found")
}
ConfigFilePath = path.Join(configDirPath, "config.json")
ok := isFile(ConfigFilePath)
if !ok {
return errors.New("config file is not found")
}
configFile, err := os.Open(ConfigFilePath)
if err != nil {
return err
}
defer configFile.Close()
b, err := io.ReadAll(configFile)
if err != nil {
return err
}
var result map[string]interface{}
err = json.Unmarshal([]byte(b), &result)
if err != nil {
return err
}
// Pretty-print the result
marshaled, err := json.MarshalIndent(result, "", " ")
if err != nil {
return err
}
fmt.Printf("Printing config located at %s: \n %s\n", ConfigFilePath, (marshaled))
return nil return nil
} }

10
go.mod
View File

@ -5,9 +5,13 @@ go 1.20
require ( require (
github.com/gorilla/mux v1.8.0 github.com/gorilla/mux v1.8.0
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.7.0
golang.org/x/crypto v0.10.0
golang.org/x/mod v0.11.0 golang.org/x/mod v0.11.0
) )
require golang.org/x/sys v0.9.0 // indirect require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
// replace gosimplenpm/handler => ./handler github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/sys v0.9.0 // indirect
)

13
go.sum
View File

@ -1,20 +1,31 @@
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

48
handler/app.go Normal file
View File

@ -0,0 +1,48 @@
package handler
import (
"gosimplenpm/config"
"gosimplenpm/middlewares"
"net/http"
"time"
"github.com/gorilla/mux"
"github.com/sirupsen/logrus"
)
type Application struct {
Logger *logrus.Logger
Conf config.Config
Mux *mux.Router
}
func (app *Application) Routes() {
// Need to use UseEncodedPath as shown here https://github.com/gorilla/mux/blob/master/mux.go#L269
m := mux.NewRouter().StrictSlash(true).UseEncodedPath()
m.Use(middlewares.LogMiddleware(app.Logger))
// main handler
m.HandleFunc("/{name}", GetPackage(app.Logger, app.Conf)).Methods("GET")
m.HandleFunc("/{name}", middlewares.AuthMiddleware(app.Conf)(Publish(app.Logger, app.Conf))).Methods("PUT")
// tar handlers
m.HandleFunc("/{name}/-/{tar}", PackageTarGet(app.Logger, app.Conf)).Methods("GET")
// tag handlers
m.HandleFunc("/-/package/{name}/dist-tags/{tag}", middlewares.AuthMiddleware(app.Conf)(DistTagDelete(app.Logger, app.Conf))).Methods("DELETE")
m.HandleFunc("/-/package/{name}/dist-tags/{tag}", middlewares.AuthMiddleware(app.Conf)(DistTagPut(app.Logger, app.Conf))).Methods("PUT")
m.HandleFunc("/-/package/{name}/dist-tags", DistTagGet(app.Logger, app.Conf)).Methods("GET")
m.NotFoundHandler = http.HandlerFunc(NotFound)
app.Mux = m
}
func (app *Application) Start() error {
app.Routes()
server := &http.Server{
Addr: app.Conf.IpAddress,
Handler: app.Mux,
ReadTimeout: 4 * time.Second,
WriteTimeout: 4 * time.Second,
}
return server.ListenAndServe()
}

View File

@ -6,16 +6,21 @@ import (
"net/url" "net/url"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/sirupsen/logrus"
"gosimplenpm/config"
"gosimplenpm/storage" "gosimplenpm/storage"
) )
func Get(w http.ResponseWriter, r *http.Request) { func GetPackage(lg *logrus.Logger, cfg config.Config) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
escapedName := mux.Vars(r)["name"] escapedName := mux.Vars(r)["name"]
packageName, _ := url.PathUnescape(escapedName) packageName, _ := url.PathUnescape(escapedName)
fmt.Printf("Package name => %s\n", packageName) lg.WithFields(logrus.Fields{
"function": "get-package",
}).Debugf("Package name => %s\n", packageName)
fileToServe, found, err := storage.GetIndexJsonFromStore(packageName) fileToServe, found, err := storage.GetIndexJsonFromStore(packageName, cfg.RepoDir, lg)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
@ -30,3 +35,4 @@ func Get(w http.ResponseWriter, r *http.Request) {
// serve file // serve file
http.ServeFile(w, r, fileToServe) http.ServeFile(w, r, fileToServe)
} }
}

View File

@ -3,6 +3,7 @@ package handler
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"gosimplenpm/config"
"gosimplenpm/serviceidos" "gosimplenpm/serviceidos"
"gosimplenpm/storage" "gosimplenpm/storage"
"net/http" "net/http"
@ -11,13 +12,15 @@ import (
"strings" "strings"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/sirupsen/logrus"
) )
type NPMClientPutRequest struct { type NPMClientPutRequest struct {
Request serviceidos.IndexJson Request serviceidos.IndexJson
} }
func Publish(w http.ResponseWriter, r *http.Request) { func Publish(lg *logrus.Logger, cfg config.Config) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// (1) Parse Json Body // (1) Parse Json Body
// (2) Check if package exists in the folder. // (2) Check if package exists in the folder.
// (a) if it does, ckeck if it is the same version. If it is, return error. Else modify index.json from (2) // (a) if it does, ckeck if it is the same version. If it is, return error. Else modify index.json from (2)
@ -25,14 +28,18 @@ func Publish(w http.ResponseWriter, r *http.Request) {
escapedName := mux.Vars(r)["name"] escapedName := mux.Vars(r)["name"]
packageName, _ := url.PathUnescape(escapedName) packageName, _ := url.PathUnescape(escapedName)
fmt.Printf("Package name => %s\n", packageName) lg.WithFields(logrus.Fields{
"function": "publish",
}).Debugf("Package name => %s\n", packageName)
var cr NPMClientPutRequest var cr NPMClientPutRequest
// Parse json body // Parse json body
err := json.NewDecoder(r.Body).Decode(&cr.Request) err := json.NewDecoder(r.Body).Decode(&cr.Request)
if err != nil { if err != nil {
fmt.Printf("Error unmarshaling put request: %+v\n", err) lg.WithFields(logrus.Fields{
"function": "publish",
}).Debugf("Error unmarshaling put request: %+v\n", err)
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
@ -52,20 +59,26 @@ func Publish(w http.ResponseWriter, r *http.Request) {
index++ index++
} }
versionData = cr.Request.Versions[version] versionData = cr.Request.Versions[version]
fmt.Printf("For version(%s) with tag(%s), versionData => %+v\n", version, tag, versionData) lg.WithFields(logrus.Fields{
"function": "publish",
}).Debugf("For version(%s) with tag(%s), versionData => %+v\n", version, tag, versionData)
// Rewrite the tarball path // Rewrite the tarball path
tarballFileName := strings.Split(versionData.Dist.Tarball, "/-/")[1] tarballFileName := strings.Split(versionData.Dist.Tarball, "/-/")[1]
fmt.Printf("TarballName => %s\n", tarballFileName) lg.WithFields(logrus.Fields{
"function": "publish",
}).Debugf("TarballName => %s\n", tarballFileName)
// versionData.Dist.Tarball = fmt.Sprintf("file://%s", packageFilePath) // versionData.Dist.Tarball = fmt.Sprintf("file://%s", packageFilePath)
versionData.Dist.Tarball = fmt.Sprintf("http://%s/%s/-/%s", r.Host, url.PathEscape(packageName), url.PathEscape(tarballFileName)) versionData.Dist.Tarball = fmt.Sprintf("http://%s/%s/-/%s", r.Host, url.PathEscape(packageName), url.PathEscape(tarballFileName))
fmt.Printf("versionData.Dist.Tarball => %s\n", versionData.Dist.Tarball) lg.WithFields(logrus.Fields{
registryPath, _ := storage.GetRegistryPath() "function": "publish",
}).Debugf("versionData.Dist.Tarball => %s\n", versionData.Dist.Tarball)
tarBallFile := strings.Split(tarballFileName, "/")[1] tarBallFile := strings.Split(tarballFileName, "/")[1]
packageFilePath := path.Join(registryPath, packageName, tarBallFile) packageFilePath := path.Join(cfg.RepoDir, packageName, tarBallFile)
// Try to get the index.json from the store // Try to get the index.json from the store
fileToServe, found, err := storage.GetIndexJsonFromStore(packageName) fileToServe, found, err := storage.GetIndexJsonFromStore(packageName, cfg.RepoDir, lg)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
@ -78,7 +91,7 @@ func Publish(w http.ResponseWriter, r *http.Request) {
jsonFile.DistTags["latest"] = version jsonFile.DistTags["latest"] = version
} else { } else {
// old package // old package
err = storage.ReadIndexJson(fileToServe, &jsonFile) err = storage.ReadIndexJson(fileToServe, &jsonFile, lg)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
@ -86,7 +99,9 @@ func Publish(w http.ResponseWriter, r *http.Request) {
// Checking that you are not publishing over a pervious published version // Checking that you are not publishing over a pervious published version
if jsonFile.Versions[version].Version == version { if jsonFile.Versions[version].Version == version {
fmt.Printf("Version %s of package %s already exists!!\n", version, packageName) lg.WithFields(logrus.Fields{
"function": "publish",
}).Debugf("Version %s of package %s already exists!!\n", version, packageName)
http.Error(w, err.Error(), http.StatusBadRequest) http.Error(w, err.Error(), http.StatusBadRequest)
return return
} }
@ -101,21 +116,27 @@ func Publish(w http.ResponseWriter, r *http.Request) {
jsonFile.Versions[version] = versionData jsonFile.Versions[version] = versionData
} }
fmt.Println("FiletoServe ==> ", fileToServe) lg.WithFields(logrus.Fields{
"function": "publish",
}).Debugln("FiletoServe ==> ", fileToServe)
// Write index.json // Write index.json
err = storage.WriteIndexJson(fileToServe, &jsonFile) err = storage.WriteIndexJson(fileToServe, &jsonFile, lg)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
fmt.Println("Package path => ", packageFilePath) lg.WithFields(logrus.Fields{
"function": "publish",
}).Debugln("Package path => ", packageFilePath)
// Write bundled package // Write bundled package
packageData := jsonFile.Attachments[fmt.Sprintf("%s-%s.tgz", packageName, version)].Data packageData := jsonFile.Attachments[fmt.Sprintf("%s-%s.tgz", packageName, version)].Data
err = storage.WritePackageToStore(packageFilePath, packageData) err = storage.WritePackageToStore(packageFilePath, packageData, lg)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
} }
}

View File

@ -3,6 +3,7 @@ package handler
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"gosimplenpm/config"
"gosimplenpm/serviceidos" "gosimplenpm/serviceidos"
"gosimplenpm/storage" "gosimplenpm/storage"
"net/http" "net/http"
@ -14,15 +15,19 @@ import (
"golang.org/x/mod/semver" "golang.org/x/mod/semver"
) )
func DistTagDelete(lg *logrus.Logger) http.HandlerFunc { func DistTagDelete(lg *logrus.Logger, cfg config.Config) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
escapedName := mux.Vars(r)["name"] escapedName := mux.Vars(r)["name"]
packageName, _ := url.PathUnescape(escapedName) packageName, _ := url.PathUnescape(escapedName)
lg.Printf("Package name => %s\n", packageName) lg.WithFields(logrus.Fields{
"function": "dist-tags-delete",
}).Debugf("Package name => %s\n", packageName)
escapedName = mux.Vars(r)["tag"] escapedName = mux.Vars(r)["tag"]
tag, _ := url.PathUnescape(escapedName) tag, _ := url.PathUnescape(escapedName)
lg.Printf("Tag => %s\n", tag) lg.WithFields(logrus.Fields{
"function": "dist-tags-delete",
}).Debugf("Tag => %s\n", tag)
if semver.IsValid(tag) { if semver.IsValid(tag) {
http.Error(w, "Tag cannot be a semver version", http.StatusBadRequest) http.Error(w, "Tag cannot be a semver version", http.StatusBadRequest)
@ -34,7 +39,7 @@ func DistTagDelete(lg *logrus.Logger) http.HandlerFunc {
return return
} }
fileToServe, found, err := storage.GetIndexJsonFromStore(packageName) fileToServe, found, err := storage.GetIndexJsonFromStore(packageName, cfg.RepoDir, lg)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
@ -47,7 +52,7 @@ func DistTagDelete(lg *logrus.Logger) http.HandlerFunc {
} }
var jsonFile serviceidos.IndexJson var jsonFile serviceidos.IndexJson
err = storage.ReadIndexJson(fileToServe, &jsonFile) err = storage.ReadIndexJson(fileToServe, &jsonFile, lg)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
@ -56,7 +61,7 @@ func DistTagDelete(lg *logrus.Logger) http.HandlerFunc {
delete(jsonFile.DistTags, tag) delete(jsonFile.DistTags, tag)
// Write index.json // Write index.json
err = storage.WriteIndexJson(fileToServe, &jsonFile) err = storage.WriteIndexJson(fileToServe, &jsonFile, lg)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return

View File

@ -3,6 +3,7 @@ package handler
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"gosimplenpm/config"
"gosimplenpm/serviceidos" "gosimplenpm/serviceidos"
"gosimplenpm/storage" "gosimplenpm/storage"
"net/http" "net/http"
@ -13,13 +14,15 @@ import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
func DistTagGet(lg *logrus.Logger) http.HandlerFunc { func DistTagGet(lg *logrus.Logger, cfg config.Config) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
escapedName := mux.Vars(r)["name"] escapedName := mux.Vars(r)["name"]
packageName, _ := url.PathUnescape(escapedName) packageName, _ := url.PathUnescape(escapedName)
lg.Debugf("Package name => %s\n", packageName) lg.WithFields(logrus.Fields{
"function": "dist-tags-get",
}).Debugf("Package name => %s\n", packageName)
fileToServe, found, err := storage.GetIndexJsonFromStore(packageName) fileToServe, found, err := storage.GetIndexJsonFromStore(packageName, cfg.RepoDir, lg)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
@ -32,7 +35,7 @@ func DistTagGet(lg *logrus.Logger) http.HandlerFunc {
} }
var jsonFile serviceidos.IndexJson var jsonFile serviceidos.IndexJson
err = storage.ReadIndexJson(fileToServe, &jsonFile) err = storage.ReadIndexJson(fileToServe, &jsonFile, lg)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return

View File

@ -3,6 +3,7 @@ package handler
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"gosimplenpm/config"
"gosimplenpm/serviceidos" "gosimplenpm/serviceidos"
"gosimplenpm/storage" "gosimplenpm/storage"
"io" "io"
@ -15,15 +16,19 @@ import (
"golang.org/x/mod/semver" "golang.org/x/mod/semver"
) )
func DistTagPut(lg *logrus.Logger) http.HandlerFunc { func DistTagPut(lg *logrus.Logger, cfg config.Config) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
escapedName := mux.Vars(r)["name"] escapedName := mux.Vars(r)["name"]
packageName, _ := url.PathUnescape(escapedName) packageName, _ := url.PathUnescape(escapedName)
lg.Printf("Package name => %s\n", packageName) lg.WithFields(logrus.Fields{
"function": "dist-tags-put",
}).Debugf("Package name => %s\n", packageName)
escapedName = mux.Vars(r)["tag"] escapedName = mux.Vars(r)["tag"]
tag, _ := url.PathUnescape(escapedName) tag, _ := url.PathUnescape(escapedName)
lg.Printf("Tag => %s\n", tag) lg.WithFields(logrus.Fields{
"function": "dist-tags-put",
}).Debugf("Tag => %s\n", tag)
if semver.IsValid(tag) { if semver.IsValid(tag) {
http.Error(w, "Tag cannot be a semver version", http.StatusBadRequest) http.Error(w, "Tag cannot be a semver version", http.StatusBadRequest)
@ -38,9 +43,11 @@ func DistTagPut(lg *logrus.Logger) http.HandlerFunc {
body, _ := io.ReadAll(r.Body) body, _ := io.ReadAll(r.Body)
var version string var version string
_ = json.Unmarshal(body, &version) _ = json.Unmarshal(body, &version)
lg.Printf("Body => %s", version) lg.WithFields(logrus.Fields{
"function": "dist-tags-put",
}).Debugf("Body => %s", version)
fileToServe, found, err := storage.GetIndexJsonFromStore(packageName) fileToServe, found, err := storage.GetIndexJsonFromStore(packageName, cfg.RepoDir, lg)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
@ -53,7 +60,7 @@ func DistTagPut(lg *logrus.Logger) http.HandlerFunc {
} }
var jsonFile serviceidos.IndexJson var jsonFile serviceidos.IndexJson
err = storage.ReadIndexJson(fileToServe, &jsonFile) err = storage.ReadIndexJson(fileToServe, &jsonFile, lg)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
@ -62,7 +69,7 @@ func DistTagPut(lg *logrus.Logger) http.HandlerFunc {
jsonFile.DistTags[tag] = version jsonFile.DistTags[tag] = version
// Write index.json // Write index.json
err = storage.WriteIndexJson(fileToServe, &jsonFile) err = storage.WriteIndexJson(fileToServe, &jsonFile, lg)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return

View File

@ -2,7 +2,7 @@ package handler
import ( import (
"bytes" "bytes"
"fmt" "gosimplenpm/config"
"gosimplenpm/storage" "gosimplenpm/storage"
"io" "io"
"net/http" "net/http"
@ -11,9 +11,11 @@ import (
"strings" "strings"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/sirupsen/logrus"
) )
func Tar(w http.ResponseWriter, r *http.Request) { func PackageTarGet(lg *logrus.Logger, cfg config.Config) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// Sample output of npm view // Sample output of npm view
// Public // Public
// dist // dist
@ -24,13 +26,17 @@ func Tar(w http.ResponseWriter, r *http.Request) {
escapedName := mux.Vars(r)["name"] escapedName := mux.Vars(r)["name"]
packageName, _ := url.PathUnescape(escapedName) packageName, _ := url.PathUnescape(escapedName)
fmt.Printf("Package name => %s\n", packageName) lg.WithFields(logrus.Fields{
"function": "get-tar",
}).Debugf("Package name => %s\n", packageName)
escapedName = mux.Vars(r)["tar"] escapedName = mux.Vars(r)["tar"]
tarFileName, _ := url.PathUnescape(escapedName) tarFileName, _ := url.PathUnescape(escapedName)
fmt.Printf("Tarfile name => %s\n", tarFileName) lg.WithFields(logrus.Fields{
"function": "get-tar",
}).Debugf("Tarfile name => %s\n", tarFileName)
versionName := strings.Split(strings.Split(tarFileName, "-")[1], ".tgz")[0] versionName := strings.Split(strings.Split(tarFileName, "-")[1], ".tgz")[0]
fileAsString, err := storage.GetTarFromStore(packageName, versionName) fileAsString, err := storage.GetTarFromStore(packageName, versionName, cfg.RepoDir, lg)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
@ -41,3 +47,4 @@ func Tar(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Length", strconv.Itoa(len([]byte(fileAsString)))) w.Header().Set("Content-Length", strconv.Itoa(len([]byte(fileAsString))))
io.Copy(w, bytes.NewReader([]byte(fileAsString))) io.Copy(w, bytes.NewReader([]byte(fileAsString)))
} }
}

35
main.go Normal file
View File

@ -0,0 +1,35 @@
package main
import (
"gosimplenpm/cmd/gosimplenpm"
)
func main() {
gosimplenpm.Execute()
}
// func main() {
// log := &logrus.Logger{
// Out: os.Stdout,
// Level: logrus.DebugLevel,
// Formatter: &logrus.TextFormatter{
// FullTimestamp: true,
// TimestampFormat: "2009-01-02 15:15:15",
// },
// }
// var cfg config.Config
// err := config.LoadConfiguration("userdata/config.json", &cfg)
// if err != nil {
// log.Fatalf("Config is not loaded: %+v\n", err)
// }
// app := &gosimplenpm.Application{
// Conf: cfg,
// Logger: log,
// }
// log.Infoln("Starting server on port 4000")
// err = http.ListenAndServe(":4000", app.Routes())
// log.Fatal(err)
// }

View File

@ -14,26 +14,15 @@ import (
"gosimplenpm/serviceidos" "gosimplenpm/serviceidos"
"path/filepath" "path/filepath"
"github.com/sirupsen/logrus"
) )
func GetRegistryPath() (string, error) { func GetIndexJsonFromStore(packageName string, registryPath string, log *logrus.Logger) (string, bool, error) {
registryPath, err := filepath.Abs("./examples")
if err != nil {
fmt.Printf("File repo not found: +%v\n", err)
return "", err
}
return registryPath, err
}
func GetIndexJsonFromStore(packageName string) (string, bool, error) {
fileToServe := "" fileToServe := ""
found := false found := false
searchDir, err := GetRegistryPath()
if err != nil {
return searchDir, found, err
}
err = filepath.WalkDir(searchDir, func(fp string, info fs.DirEntry, e error) error { err := filepath.WalkDir(registryPath, func(fp string, info fs.DirEntry, e error) error {
if strings.Contains(fp, path.Join(packageName, "index.json")) { if strings.Contains(fp, path.Join(packageName, "index.json")) {
fileToServe = fp fileToServe = fp
found = true found = true
@ -42,25 +31,23 @@ func GetIndexJsonFromStore(packageName string) (string, bool, error) {
}) })
if err != nil { if err != nil {
fmt.Printf("List files error: +%v\n", err) log.WithFields(logrus.Fields{
"function": "get-index-json-from-store",
}).Debugf("List files error: +%v\n", err)
return fileToServe, found, err return fileToServe, found, err
} }
if fileToServe == "" && !found { if fileToServe == "" && !found {
fileToServe = path.Join(searchDir, packageName, "index.json") fileToServe = path.Join(registryPath, packageName, "index.json")
} }
return fileToServe, found, nil return fileToServe, found, nil
} }
func GetTarFromStore(packageName string, tarFileName string) (string, error) { func GetTarFromStore(packageName string, tarFileName string, registryPath string, log *logrus.Logger) (string, error) {
fileToServe := "" fileToServe := ""
searchDir, err := GetRegistryPath()
if err != nil {
return searchDir, err
}
err = filepath.WalkDir(searchDir, func(fp string, info fs.DirEntry, e error) error { err := filepath.WalkDir(registryPath, func(fp string, info fs.DirEntry, e error) error {
if strings.Contains(fp, path.Join(packageName, tarFileName)) { if strings.Contains(fp, path.Join(packageName, tarFileName)) {
fileToServe = fp fileToServe = fp
} }
@ -68,7 +55,9 @@ func GetTarFromStore(packageName string, tarFileName string) (string, error) {
}) })
if err != nil { if err != nil {
fmt.Printf("List files error: +%v\n", err) log.WithFields(logrus.Fields{
"function": "get-tar-from-store",
}).Debugf("List files error: +%v\n", err)
return fileToServe, err return fileToServe, err
} }
@ -78,29 +67,37 @@ func GetTarFromStore(packageName string, tarFileName string) (string, error) {
file, err := os.Open(fileToServe) file, err := os.Open(fileToServe)
if err != nil { if err != nil {
fmt.Printf("Open error: %s\n", fileToServe) log.WithFields(logrus.Fields{
"function": "get-tar-from-store",
}).Debugf("Open error: %s\n", fileToServe)
return "", err return "", err
} }
archive, err := gzip.NewReader(file) archive, err := gzip.NewReader(file)
if err != nil { if err != nil {
fmt.Printf("Archive Open error: %s\n", fileToServe) log.WithFields(logrus.Fields{
"function": "get-tar-from-store",
}).Debugf("Archive Open error: %s\n", fileToServe)
return "", err return "", err
} }
tr := tar.NewReader(archive) tr := tar.NewReader(archive)
bs, err := io.ReadAll(tr) bs, err := io.ReadAll(tr)
if err != nil { if err != nil {
fmt.Printf("Archive Read error: %s\n", fileToServe) log.WithFields(logrus.Fields{
"function": "get-tar-from-store",
}).Debugf("Archive Read error: %s\n", fileToServe)
return "", err return "", err
} }
return base64.StdEncoding.EncodeToString(bs), err return base64.StdEncoding.EncodeToString(bs), err
} }
func ReadIndexJson(fPath string, res *serviceidos.IndexJson) error { func ReadIndexJson(fPath string, res *serviceidos.IndexJson, log *logrus.Logger) error {
jsonFile, err := os.Open(fPath) jsonFile, err := os.Open(fPath)
if err != nil { if err != nil {
fmt.Printf("File Not found: %s\n", fPath) log.WithFields(logrus.Fields{
"function": "read-index-json",
}).Debugf("File Not found: %s\n", fPath)
return err return err
} }
@ -108,19 +105,23 @@ func ReadIndexJson(fPath string, res *serviceidos.IndexJson) error {
err = json.NewDecoder(jsonFile).Decode(res) err = json.NewDecoder(jsonFile).Decode(res)
if err != nil { if err != nil {
fmt.Printf("Unmarshalerror: %+v\n", err) log.WithFields(logrus.Fields{
"function": "read-index-json",
}).Debugf("Unmarshalerror: %+v\n", err)
return err return err
} }
return nil return nil
} }
func WriteIndexJson(fPath string, res *serviceidos.IndexJson) error { func WriteIndexJson(fPath string, res *serviceidos.IndexJson, log *logrus.Logger) error {
// Need to create the directory first // Need to create the directory first
parent := path.Dir(fPath) parent := path.Dir(fPath)
err := os.MkdirAll(parent, os.ModePerm) err := os.MkdirAll(parent, os.ModePerm)
if err != nil { if err != nil {
fmt.Printf("Folder (%s) creation failed.\n", fPath) log.WithFields(logrus.Fields{
"function": "write-index-json",
}).Debugf("Folder (%s) creation failed.\n", fPath)
return err return err
} }
@ -128,7 +129,9 @@ func WriteIndexJson(fPath string, res *serviceidos.IndexJson) error {
jsonFile, err := os.Create(fPath) jsonFile, err := os.Create(fPath)
if err != nil { if err != nil {
fmt.Printf("Creation error for path(%s): %+v\n ", fPath, err) log.WithFields(logrus.Fields{
"function": "write-index-json",
}).Debugf("Creation error for path(%s): %+v\n ", fPath, err)
return err return err
} }
@ -136,23 +139,29 @@ func WriteIndexJson(fPath string, res *serviceidos.IndexJson) error {
err = json.NewEncoder(jsonFile).Encode(res) err = json.NewEncoder(jsonFile).Encode(res)
if err != nil { if err != nil {
fmt.Printf("Marshalerror: %+v\n", err) log.WithFields(logrus.Fields{
"function": "write-index-json",
}).Debugf("Marshalerror: %+v\n", err)
return err return err
} }
return nil return nil
} }
func WritePackageToStore(fPath string, data string) error { func WritePackageToStore(fPath string, data string, log *logrus.Logger) error {
dec, err := base64.StdEncoding.DecodeString(data) dec, err := base64.StdEncoding.DecodeString(data)
if err != nil { if err != nil {
fmt.Printf("Base64 Decode error: %+v\n", err) log.WithFields(logrus.Fields{
"function": "write-package-to-store",
}).Debugf("Base64 Decode error: %+v\n", err)
return err return err
} }
dataFile, err := os.Create(fPath) dataFile, err := os.Create(fPath)
if err != nil { if err != nil {
fmt.Printf("Creation error: %s\n", fPath) log.WithFields(logrus.Fields{
"function": "write-package-to-store",
}).Debugf("Creation error: %s\n", fPath)
return err return err
} }
@ -160,13 +169,17 @@ func WritePackageToStore(fPath string, data string) error {
_, err = dataFile.Write(dec) _, err = dataFile.Write(dec)
if err != nil { if err != nil {
fmt.Printf("Write error: %s\n", fPath) log.WithFields(logrus.Fields{
"function": "write-package-to-store",
}).Debugf("Write error: %s\n", fPath)
return err return err
} }
err = dataFile.Sync() err = dataFile.Sync()
if err != nil { if err != nil {
fmt.Printf("Sync error: %s\n", fPath) log.WithFields(logrus.Fields{
"function": "write-package-to-store",
}).Debugf("Sync error: %s\n", fPath)
return err return err
} }