diff --git a/args.go b/args.go index 83a84fe..5d641d4 100644 --- a/args.go +++ b/args.go @@ -2,37 +2,31 @@ package main import ( "flag" - "log" "os" ) -func getArgs() (*string, *bool, *string, *string, *string) { - cwd, err := os.Getwd() - if err != nil { - log.Fatalf("Failed to get working directory %s", err) - } - - gitdir := flag.String( +func getArgs(workingdir *string) (gitdir *string, doPush *bool, username *string, password *string, remoteUrl *string) { + gitdir = flag.String( "C", - cwd, + *workingdir, "The directory containing the git repository in which to archive the pads.", ) - doPush := flag.Bool( + doPush = flag.Bool( "push", false, "Push the changes to the remote specified by remoteUrl.", ) - username := flag.String( + username = flag.String( "username", "", "The username for authenticating to the remote.", ) - password := flag.String( + password = flag.String( "password", os.Getenv("GIT_PASSWORD"), "The password for authenticating to the remote. Can also be specified via the environment variable GIT_PASSWORD.", ) - remoteUrl := flag.String( + remoteUrl = flag.String( "url", "", "URL to push changes to.", @@ -40,5 +34,5 @@ func getArgs() (*string, *bool, *string, *string, *string) { flag.Parse() - return gitdir, doPush, username, password, remoteUrl + return } diff --git a/commit.go b/commit.go index 7e65c60..84d92c1 100644 --- a/commit.go +++ b/commit.go @@ -1,6 +1,7 @@ package main import ( + "errors" "fmt" "sync" "time" @@ -10,13 +11,16 @@ import ( "github.com/go-git/go-git/v5/plumbing/object" ) -var cm sync.Mutex +var ( + cm sync.Mutex + nothingToDo = errors.New("Nothing to do for unmodified file") +) func commit( tree *git.Worktree, padfile string, url string, -) (plumbing.Hash, error) { +) (commit plumbing.Hash, err error) { cm.Lock() defer cm.Unlock() @@ -34,7 +38,7 @@ func commit( return plumbing.ZeroHash, nothingToDo } - commit, err := tree.Commit( + commit, err = tree.Commit( fmt.Sprintf("Updated %s from %s", padfile, url), &git.CommitOptions{ All: false, @@ -50,5 +54,5 @@ func commit( return plumbing.ZeroHash, fmt.Errorf("Failed to commit %s: %w", padfile, err) } - return commit, nil + return } diff --git a/download.go b/download.go index 6b9709b..4805f87 100644 --- a/download.go +++ b/download.go @@ -12,7 +12,7 @@ import ( func download( gitdir string, url string, -) (string, error) { +) (padfile string, err error) { res, err := http.Get(url + "/export/txt") if err != nil { return "", fmt.Errorf("Failed to get pad at %s: %w", url, err) @@ -20,7 +20,7 @@ func download( defer res.Body.Close() - padfile := path.Base(url) + ".txt" + padfile = path.Base(url) + ".txt" padpath := filepath.Join(gitdir, padfile) out, err := os.Create(padpath) @@ -34,5 +34,5 @@ func download( return "", fmt.Errorf("Skipping update of %s, because pad has likely been removed from %s", padfile, url) } - return padfile, nil + return } diff --git a/main.go b/main.go index 6bf36ce..24bc1b5 100644 --- a/main.go +++ b/main.go @@ -3,77 +3,40 @@ package main import ( "bufio" "crypto/tls" - "errors" "log" "net/http" "os" - "sync" - - "github.com/go-git/go-git/v5" - githttp "github.com/go-git/go-git/v5/plumbing/transport/http" -) - -const ( - defaultRemoteName = "pad-archiver" -) - -var ( - nothingToDo = errors.New("Nothing to do for unmodified file") ) func main() { http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} - gitdir, doPush, username, password, remoteUrl := getArgs() - - repo, err := git.PlainOpen(*gitdir) + workingdir, err := os.Getwd() if err != nil { - log.Fatalf("Failed to open git repo %s: %s", *gitdir, err) + log.Fatalf("Failed to get working directory %s", err) } - tree, err := repo.Worktree() + gitdir, doPush, username, password, remoteUrl := getArgs(&workingdir) + + repo, tree, err := openRepo(gitdir) if err != nil { - log.Fatalf("Failed to open git worktree %s", err) + if repo == nil { + log.Fatalf("Failed to open git repo %s: %s", *gitdir, err) + } + if tree == nil { + log.Fatalf("Failed to open git worktree %s", err) + } } - defer tree.Clean(&git.CleanOptions{Dir: true}) + padstxt := bufio.NewScanner(os.Stdin) - filesystemRoot := tree.Filesystem.Root() - scanner := bufio.NewScanner(os.Stdin) + updatePads(padstxt, tree) - var wg sync.WaitGroup - for scanner.Scan() { - wg.Add(1) - padurl := scanner.Text() - - go func() { - defer wg.Done() - padfile, err := download(filesystemRoot, padurl) - if err != nil { - log.Printf("%s", err) - - return - } - log.Printf("Downloaded %s", padurl) - if _, err := commit(tree, padfile, padurl); err != nil { - if err == nothingToDo { - log.Printf("Nothing to do for %s", padfile) - } else { - log.Printf("%s", err) - } - } else { - log.Printf("Committed %s", padfile) - } - }() - } - wg.Wait() - - auth := &githttp.BasicAuth{ - Username: *username, - Password: *password, - } + auth := auth(username, password) if *doPush == true { - pushRepo(repo, remoteUrl, auth) + if err := pushRepo(repo, remoteUrl, auth); err != nil { + log.Fatalf("Failed to push repo: %s", err) + } } } diff --git a/remote.go b/remote.go index 6f39e25..bb5842c 100644 --- a/remote.go +++ b/remote.go @@ -8,19 +8,31 @@ import ( githttp "github.com/go-git/go-git/v5/plumbing/transport/http" ) -func pushRepo(repo *git.Repository, remoteUrl *string, auth *githttp.BasicAuth) { - if _, err := createRemote(repo, defaultRemoteName, *remoteUrl); err != nil { - log.Fatalf("%s", err) +const ( + defaultRemoteName = "pad-archiver" +) + +func auth(username *string, password *string) (auth *githttp.BasicAuth) { + return &githttp.BasicAuth{ + Username: *username, + Password: *password, } - if err := push(auth, repo, defaultRemoteName); err != nil { +} + +func pushRepo(repo *git.Repository, remoteUrl *string, auth *githttp.BasicAuth) (err error) { + if _, err = createRemote(repo, defaultRemoteName, *remoteUrl); err != nil { + return + } + if err = push(auth, repo, defaultRemoteName); err != nil { if err == git.NoErrAlreadyUpToDate { log.Println("Already up-to-date") } else { - log.Fatalf("%s", err) + return } } else { log.Println("Pushed changes to remote") } + return } func createRemote( diff --git a/repo.go b/repo.go new file mode 100644 index 0000000..5100e91 --- /dev/null +++ b/repo.go @@ -0,0 +1,12 @@ +package main + +import "github.com/go-git/go-git/v5" + +func openRepo(gitdir *string) (repo *git.Repository, tree *git.Worktree, err error) { + repo, err = git.PlainOpen(*gitdir) + if err != nil { + return + } + tree, err = repo.Worktree() + return +} diff --git a/update.go b/update.go new file mode 100644 index 0000000..2fac376 --- /dev/null +++ b/update.go @@ -0,0 +1,43 @@ +package main + +import ( + "bufio" + "log" + "sync" + + "github.com/go-git/go-git/v5" +) + +func updatePads(pads *bufio.Scanner, tree *git.Worktree) { + defer tree.Clean(&git.CleanOptions{Dir: true}) + + filesystemRoot := tree.Filesystem.Root() + + var wg sync.WaitGroup + for pads.Scan() { + wg.Add(1) + padurl := pads.Text() + + go func() { + defer wg.Done() + if _, err := updatePad(filesystemRoot, padurl, tree); err != nil { + log.Printf("%s", err) + } + }() + } + wg.Wait() +} + +func updatePad(filesystemRoot string, padurl string, tree *git.Worktree) (padfile string, err error) { + padfile, err = download(filesystemRoot, padurl) + if err != nil { + return + } + log.Printf("Downloaded %s", padurl) + if _, err = commit(tree, padfile, padurl); err != nil { + return + } else { + log.Printf("Committed %s", padfile) + return + } +}