Skip to content

Commit

Permalink
feat: single module updates
Browse files Browse the repository at this point in the history
  • Loading branch information
mkloubert committed Jan 4, 2025
1 parent aae690c commit b770760
Show file tree
Hide file tree
Showing 9 changed files with 291 additions and 222 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Change Log (go-package-manager)

## 0.30.0

- feat: `gpm update` now supports update of specific modules as well
- fix: using `TidyUp()` method from `AppContext` instead raw `go mod tidy`
- refactor: `gpm doctor` now checks all dependencies for up-to-dateness
- refactor: code cleanups and improvements

## 0.29.10

- feat: self-update by executing `gpm update --self`
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,14 @@ gpm update

is a short version of `go get -u ./... && go mod tidy` and will update all dependencies.

On the other hand, you are able to run something like

```bash
gpm update github.com/alecthomas/chroma yaml
```

to update specific ones. Each argument can be a module URL or [alias](#add-alias-).

## Setup AI [<a href="#table-of-contents">↑</a>]

If you would like to use AI feature, like suggestion of branch names, you can setup one of the following APIs:
Expand Down
10 changes: 3 additions & 7 deletions commands/doctor.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,25 +116,21 @@ func Init_Doctor_Command(parentCmd *cobra.Command, app *types.AppContext) {

// cleanups and extract items as references
allItems := make([]*GoModFileRequireItem, 0)
directItems := make([]*GoModFileRequireItem, 0)
for _, item := range goMod.Require {
refItem := &item

refItem.Path = strings.TrimSpace(refItem.Path)
refItem.Version = strings.TrimSpace(refItem.Version)

allItems = append(allItems, refItem)
if refItem.Indirect == nil || !*refItem.Indirect {
directItems = append(directItems, refItem)
}
}

if len(directItems) > 0 {
if len(allItems) > 0 {
fmt.Println("Checking dependencies for up-to-dateness ...")
for i, item := range directItems {
for i, item := range allItems {
s := spinner.New(spinner.CharSets[24], 100*time.Millisecond)
s.Prefix = "\t["
s.Suffix = fmt.Sprintf("] Checking '%s' (%v/%v) ...", item.Path, i+1, len(directItems))
s.Suffix = fmt.Sprintf("] Checking '%s' (%v/%v) ...", item.Path, i+1, len(allItems))
s.Start()

thisVersion, err := version.NewVersion(strings.TrimSpace(item.Version))
Expand Down
7 changes: 1 addition & 6 deletions commands/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,12 +418,7 @@ require (
}

// cleanup project
p = utils.CreateShellCommandByArgs("go", "mod", "tidy")
p.Dir = outDir
p.Stdout = nil
p.Stderr = nil
app.Debug(fmt.Sprintf("Cleanup project '%s' ...", projectUrl))
utils.RunCommand(p)
app.TidyUp()

// output final summary
out, _ := glamour.Render(lastResponse.FinalSummary, "dark")
Expand Down
232 changes: 26 additions & 206 deletions commands/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,10 @@
package commands

import (
"bufio"
"bytes"
"fmt"
"io"
"net/http"
"os"
"os/exec"
"runtime"
"strings"

browser "github.com/EDDYCJY/fake-useragent"
"github.com/alecthomas/chroma/quick"
"github.com/mkloubert/go-package-manager/types"
"github.com/mkloubert/go-package-manager/utils"
"github.com/spf13/cobra"
)

Expand All @@ -51,215 +41,45 @@ func Init_Update_Command(parentCmd *cobra.Command, app *types.AppContext) {
var userAgent string

var updateCmd = &cobra.Command{
Use: "update",
Use: "update <modules>",
Aliases: []string{"upd"},
Short: "Update dependencies",
Long: `Updates all dependencies in this project.`,
Long: `Updates all or only specific dependencies in this project.`,
Run: func(cmd *cobra.Command, args []string) {
if selfUpdate {
app.Debug("Will start self-update ...")

consoleFormatter := utils.GetBestChromaFormatterName()
consoleStyle := utils.GetBestChromaStyleName()

customUserAgent := strings.TrimSpace(userAgent)
if customUserAgent == "" {
customUserAgent = browser.Chrome()
}

customPowerShellBin := strings.TrimSpace(powerShellBin)
if customPowerShellBin == "" {
customPowerShellBin = "powershell"
}

customUpdateScript := strings.TrimSpace(updateScript)
if customUpdateScript == "" {
customUpdateScript = strings.TrimSpace(os.Getenv("GPM_UPDATE_SCRIPT"))
}

downloadScript := func(url string) ([]byte, error) {
app.Debug(fmt.Sprintf("Download from '%s' ...", url))
app.Debug(fmt.Sprintf("User agent: %s", customUserAgent))

req, err := http.NewRequest("GET", url, bytes.NewBuffer([]byte{}))
if err != nil {
return []byte{}, err
}

req.Header.Set("User-Agent", customUserAgent)

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return []byte{}, err
}
defer resp.Body.Close()

if resp.StatusCode != 200 {
return []byte{}, fmt.Errorf("unexpected response: %v", resp.StatusCode)
}

responseData, err := io.ReadAll(resp.Body)

return responseData, err
}

showNewVersion := func() {
if noVersionPrint {
return
}
run_self_update_command(
app,
force, noVersionPrint, powerShell, powerShellBin, updateScript, userAgent,
)
} else {
modulesToUpdate := make([]string, 0)
for _, moduleNameOrUrl := range args {
// maybe alias => module url(s)
moduleUrls := app.GetModuleUrls(moduleNameOrUrl)

app.RunShellCommandByArgs("gpm", "--version")
modulesToUpdate = append(modulesToUpdate, moduleUrls...)
}

if powerShell || utils.IsWindows() {
// PowerShell
app.Debug(fmt.Sprintf("Will use PowerShell '%s' ...", powerShellBin))

scriptUrl := customUpdateScript
if scriptUrl == "" {
scriptUrl = "https://raw.githubusercontent.com/mkloubert/go-package-manager/main/sh.kloubert.dev/gpm.ps1"
} else {
su, err := utils.ToUrlForOpenHandler(scriptUrl)
utils.CheckForError(err)

scriptUrl = su
}

pwshScript, err := downloadScript(scriptUrl)
utils.CheckForError(err)

executeScript := func() {
p := exec.Command(customPowerShellBin, "-NoProfile", "-Command", "-")
p.Dir = app.Cwd
p.Stderr = os.Stderr
p.Stdout = os.Stdout

stdinPipe, err := p.StdinPipe()
utils.CheckForError(err)

err = p.Start()
utils.CheckForError(err)

go func() {
defer stdinPipe.Close()
stdinPipe.Write([]byte(pwshScript))
}()
additionalShellArgs := make([]string, 0)
additionalShellArgs = append(additionalShellArgs, modulesToUpdate...)
if len(modulesToUpdate) == 0 {
app.Debug("Will update all modules in project ...")

err = p.Wait()
utils.CheckForError(err)

showNewVersion()
os.Exit(0)
}

if force {
executeScript()
} else {
// ask the user first

err = quick.Highlight(os.Stdout, string(pwshScript), "powershell", consoleFormatter, consoleStyle)
if err != nil {
fmt.Print(string(pwshScript))
}

fmt.Println()
fmt.Println()

reader := bufio.NewReader(os.Stdin)

for {
fmt.Print("Do you really want to run this PowerShell script (Y/n)? ")
userInput, _ := reader.ReadString('\n')
userInput = strings.TrimSpace(strings.ToLower(userInput))

switch userInput {
case "", "y", "yes":
executeScript()
case "n", "no":
os.Exit(0)
}
}
}
} else if utils.IsPOSIXLikeOS() {
// if POSIX-like => sh
app.Debug("Will use UNIX shell ...")

scriptUrl := customUpdateScript
if scriptUrl == "" {
scriptUrl = "https://raw.githubusercontent.com/mkloubert/go-package-manager/main/sh.kloubert.dev/gpm.sh"
} else {
su, err := utils.ToUrlForOpenHandler(scriptUrl)
utils.CheckForError(err)

scriptUrl = su
}

bashScript, err := downloadScript(scriptUrl)
utils.CheckForError(err)

executeScript := func() {
p := exec.Command("sh")
p.Dir = app.Cwd
p.Stderr = os.Stderr
p.Stdout = os.Stdout

stdinPipe, err := p.StdinPipe()
utils.CheckForError(err)

err = p.Start()
utils.CheckForError(err)

go func() {
defer stdinPipe.Close()
stdinPipe.Write([]byte(bashScript))
}()

err = p.Wait()
utils.CheckForError(err)

showNewVersion()
os.Exit(0)
}

if force {
executeScript()
} else {
// ask the user first

err = quick.Highlight(os.Stdout, string(bashScript), "shell", consoleFormatter, consoleStyle)
if err != nil {
fmt.Print(string(bashScript))
}

fmt.Println()
fmt.Println()

reader := bufio.NewReader(os.Stdin)

for {
fmt.Print("Do you really want to run this bash script (Y/n)? ")
userInput, _ := reader.ReadString('\n')
userInput = strings.TrimSpace(strings.ToLower(userInput))

switch userInput {
case "", "y", "yes":
executeScript()
case "n", "no":
os.Exit(0)
}
}
}
// update all in this project instead specific onces
additionalShellArgs = append(additionalShellArgs, "./...")
} else {
utils.CheckForError(fmt.Errorf("self-update for %s/%s is not supported yet", runtime.GOOS, runtime.GOARCH))
// update specific ones
app.Debug(fmt.Sprintf("Will update following modules in project: %s", strings.Join(modulesToUpdate, ",")))
}
} else {
app.Debug("Will start project dependencies ...")

app.RunShellCommandByArgs("go", "get", "-u", "./...")
allShellArgs := make([]string, 0)
allShellArgs = append(allShellArgs, "get", "-u")
allShellArgs = append(allShellArgs, additionalShellArgs...)

app.RunShellCommandByArgs("go", allShellArgs...)

if !noCleanup {
app.RunShellCommandByArgs("go", "mod", "tidy")
app.TidyUp()
}
}
},
Expand Down
Loading

0 comments on commit b770760

Please sign in to comment.