Merge branch 'main' into pr/unilock/230

This commit is contained in:
comp500 2024-08-28 18:25:44 +01:00
commit a0c4aadba0
13 changed files with 95 additions and 25 deletions

1
,gitattributes Normal file
View File

@ -0,0 +1 @@
*.go text eol=lf

3
.gitignore vendored
View File

@ -15,6 +15,9 @@
# I use GoLand now # I use GoLand now
.idea/ .idea/
# I no longer have student GoLand
.vscode/
# Nix build output # Nix build output
result result

View File

@ -24,7 +24,11 @@ Join my Discord server if you need help [here](https://discord.gg/Csh8zbbhCt)!
- Creation of remote file metadata from JAR files for CurseForge mods - Creation of remote file metadata from JAR files for CurseForge mods
## Installation ## Installation
Prebuilt binaries are available from [GitHub Actions](https://github.com/packwiz/packwiz/actions) - the UI is a bit terrible, but essentially select the top build, then download the artifact ZIP for your system at the bottom of the page. To run the executable, add the folder where you downloaded it to your PATH environment variable ([see tutorial for Windows here](https://www.howtogeek.com/118594/how-to-edit-your-system-path-for-easy-command-line-access/)) or move it to where you want to use it. Prebuilt binaries are available from [GitHub Actions](https://github.com/packwiz/packwiz/actions) - the UI is a bit terrible, but essentially select the top build, then download the artifact ZIP for your system at the bottom of the page.
Another option is to use [nightly.link](https://nightly.link/packwiz/packwiz/workflows/go/main). Just go to the page, and download the artifact for your system.
To run the executable, first extract it, then add the folder where you extracted it to your PATH environment variable ([see tutorial for Windows here](https://www.howtogeek.com/118594/how-to-edit-your-system-path-for-easy-command-line-access/)) or move it to where you want to use it.
In future I will have a lot more installation options, but you can also compile from source: In future I will have a lot more installation options, but you can also compile from source:

View File

@ -222,6 +222,10 @@ func init() {
func initReadValue(prompt string, def string) string { func initReadValue(prompt string, def string) string {
fmt.Print(prompt) fmt.Print(prompt)
if viper.GetBool("non-interactive") {
fmt.Printf("%s\n", def)
return def
}
value, err := bufio.NewReader(os.Stdin).ReadString('\n') value, err := bufio.NewReader(os.Stdin).ReadString('\n')
if err != nil { if err != nil {
fmt.Printf("Error reading input: %s\n", err) fmt.Printf("Error reading input: %s\n", err)

View File

@ -123,6 +123,7 @@ func reuseExistingFile(cacheHandle *CacheIndexHandle, hashesToObtain []string, m
file, err := cacheHandle.Open() file, err := cacheHandle.Open()
if err == nil { if err == nil {
remainingHashes := cacheHandle.GetRemainingHashes(hashesToObtain) remainingHashes := cacheHandle.GetRemainingHashes(hashesToObtain)
var warnings []error
if len(remainingHashes) > 0 { if len(remainingHashes) > 0 {
err = teeHashes(remainingHashes, cacheHandle.Hashes, io.Discard, file) err = teeHashes(remainingHashes, cacheHandle.Hashes, io.Discard, file)
if err != nil { if err != nil {
@ -134,13 +135,14 @@ func reuseExistingFile(cacheHandle *CacheIndexHandle, hashesToObtain []string, m
_ = file.Close() _ = file.Close()
return CompletedDownload{}, fmt.Errorf("failed to seek file %s in cache: %w", cacheHandle.Path(), err) return CompletedDownload{}, fmt.Errorf("failed to seek file %s in cache: %w", cacheHandle.Path(), err)
} }
cacheHandle.UpdateIndex() warnings = cacheHandle.UpdateIndex()
} }
return CompletedDownload{ return CompletedDownload{
File: file, File: file,
Mod: mod, Mod: mod,
Hashes: cacheHandle.Hashes, Hashes: cacheHandle.Hashes,
Warnings: warnings,
}, nil }, nil
} else { } else {
return CompletedDownload{}, fmt.Errorf("failed to read file %s from cache: %w", cacheHandle.Path(), err) return CompletedDownload{}, fmt.Errorf("failed to read file %s from cache: %w", cacheHandle.Path(), err)
@ -229,7 +231,10 @@ func getHashListsForDownload(hashesToObtain []string, validateHashFormat string,
hashes := make(map[string]string) hashes := make(map[string]string)
hashes[validateHashFormat] = validateHash hashes[validateHashFormat] = validateHash
cl := []string{cacheHashFormat} var cl []string
if cacheHashFormat != validateHashFormat {
cl = append(cl, cacheHashFormat)
}
for _, v := range hashesToObtain { for _, v := range hashesToObtain {
if v != validateHashFormat && v != cacheHashFormat { if v != validateHashFormat && v != cacheHashFormat {
cl = append(cl, v) cl = append(cl, v)
@ -552,6 +557,33 @@ func (h *CacheIndexHandle) Remove() {
return return
} }
func removeIndices(hashList []string, indices []int) []string {
i := 0
for _, v := range hashList {
if len(indices) > 0 && i == indices[0] {
indices = indices[1:]
} else {
hashList[i] = v
i++
}
}
return hashList[:i]
}
func removeEmpty(hashList []string) ([]string, []int) {
var indices []int
i := 0
for oldIdx, v := range hashList {
if v == "" {
indices = append(indices, oldIdx)
} else {
hashList[i] = v
i++
}
}
return hashList[:i], indices
}
func CreateDownloadSession(mods []*Mod, hashesToObtain []string) (DownloadSession, error) { func CreateDownloadSession(mods []*Mod, hashesToObtain []string) (DownloadSession, error) {
// Load cache index // Load cache index
cacheIndex := CacheIndex{Version: 1, Hashes: make(map[string][]string)} cacheIndex := CacheIndex{Version: 1, Hashes: make(map[string][]string)}
@ -588,6 +620,18 @@ func CreateDownloadSession(mods []*Mod, hashesToObtain []string) (DownloadSessio
cacheIndex.Hashes[cacheHashFormat] = make([]string, 0) cacheIndex.Hashes[cacheHashFormat] = make([]string, 0)
} }
cacheIndex.cachePath = cachePath cacheIndex.cachePath = cachePath
// Clean up empty entries in index
var removedEntries []int
cacheIndex.Hashes[cacheHashFormat], removedEntries = removeEmpty(cacheIndex.Hashes[cacheHashFormat])
if len(removedEntries) > 0 {
for hashFormat, v := range cacheIndex.Hashes {
if hashFormat != cacheHashFormat {
cacheIndex.Hashes[hashFormat] = removeIndices(v, removedEntries)
}
}
}
cacheIndex.nextHashIdx = len(cacheIndex.Hashes[cacheHashFormat]) cacheIndex.nextHashIdx = len(cacheIndex.Hashes[cacheHashFormat])
// Create import folder // Create import folder

View File

@ -1,4 +1,4 @@
// +build !windows //go:build !windows
package curseforge package curseforge

6
flake.lock generated
View File

@ -2,11 +2,11 @@
"nodes": { "nodes": {
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1689444953, "lastModified": 1703013332,
"narHash": "sha256-0o56bfb2LC38wrinPdCGLDScd77LVcr7CrH1zK7qvDg=", "narHash": "sha256-+tFNwMvlXLbJZXiMHqYq77z/RfmpfpiI3yjL6o/Zo9M=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "8acef304efe70152463a6399f73e636bcc363813", "rev": "54aac082a4d9bb5bbc5c4e899603abfb76a3f6d6",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@ -1,5 +1,7 @@
{ {
inputs.nixpkgs.url = "nixpkgs/nixos-unstable"; inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
# This maps to https://github.com/NixOS/nixpkgs/tree/nixos-unstable
# The `url` option is the pattern of `github:USER_OR_ORG/REPO/BRANCH`
outputs = { outputs = {
self, self,
@ -32,7 +34,9 @@
packwiz = pkgs.callPackage ./nix { packwiz = pkgs.callPackage ./nix {
version = substring 0 8 self.rev or "dirty"; version = substring 0 8 self.rev or "dirty";
vendorSha256 = readFile ./nix/vendor-sha256; vendorSha256 = readFile ./nix/vendor-sha256;
buildGoModule = pkgs.buildGo119Module; buildGoModule = pkgs.buildGoModule;
# As of writing, `pkgs.buildGoModule` is aliased to
# `pkgs.buildGo121Module` in Nixpkgs.
}; };
# Build packwiz by default when no package name is specified # Build packwiz by default when no package name is specified
default = packwiz; default = packwiz;

View File

@ -9,6 +9,7 @@ import (
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
"net/url" "net/url"
"os" "os"
"sort"
"strconv" "strconv"
"github.com/packwiz/packwiz/core" "github.com/packwiz/packwiz/core"
@ -172,6 +173,10 @@ var exportCmd = &cobra.Command{
} }
} }
} }
// sort by `path` property before serialising to ensure reproducibility
sort.Slice(manifestFiles, func(i, j int) bool {
return manifestFiles[i].Path < manifestFiles[j].Path
})
err = session.SaveIndex() err = session.SaveIndex()
if err != nil { if err != nil {

View File

@ -186,7 +186,7 @@ func getProjectTypeFolder(projectType string, fileLoaders []string, packLoaders
var urlRegexes = [...]*regexp.Regexp{ var urlRegexes = [...]*regexp.Regexp{
// Slug/version number regex from https://github.com/modrinth/labrinth/blob/1679a3f844497d756d0cf272c5374a5236eabd42/src/util/validate.rs#L8 // Slug/version number regex from https://github.com/modrinth/labrinth/blob/1679a3f844497d756d0cf272c5374a5236eabd42/src/util/validate.rs#L8
regexp.MustCompile("^https?://modrinth\\.com/(?P<urlCategory>[^/]+)/(?P<slug>[a-zA-Z0-9!@$()`.+,_\"-]{3,64})(?:/version/(?P<version>[a-zA-Z0-9!@$()`.+,_\"-]{1,32}))?"), regexp.MustCompile("^https?://(www.)?modrinth\\.com/(?P<urlCategory>[^/]+)/(?P<slug>[a-zA-Z0-9!@$()`.+,_\"-]{3,64})(?:/version/(?P<version>[a-zA-Z0-9!@$()`.+,_\"-]{1,32}))?"),
// Version/project IDs are more restrictive: [a-zA-Z0-9]+ (base62) // Version/project IDs are more restrictive: [a-zA-Z0-9]+ (base62)
regexp.MustCompile("^https?://cdn\\.modrinth\\.com/data/(?P<slug>[a-zA-Z0-9]+)/versions/(?P<versionID>[a-zA-Z0-9]+)/(?P<filename>[^/]+)$"), regexp.MustCompile("^https?://cdn\\.modrinth\\.com/data/(?P<slug>[a-zA-Z0-9]+)/versions/(?P<versionID>[a-zA-Z0-9]+)/(?P<filename>[^/]+)$"),
regexp.MustCompile("^(?P<slug>[a-zA-Z0-9!@$()`.+,_\"-]{3,64})$"), regexp.MustCompile("^(?P<slug>[a-zA-Z0-9!@$()`.+,_\"-]{3,64})$"),

View File

@ -3,7 +3,12 @@
pkgs ? import <nixpkgs> {}, pkgs ? import <nixpkgs> {},
}: }:
pkgs.callPackage (import ./.) { pkgs.callPackage (import ./.) {
buildGoModule = pkgs.buildGo118Module;
buildGoModule = pkgs.buildGoModule;
## As of writing, `pkgs.buildGoModule` is aliased to
## `pkgs.buildGo121Module` in Nixpkgs.
## `buildGoModule` is set as `pkgs.buildGoModule` to try and work around
## `vendorHash` issues in the future.
vendorSha256 = sha256; vendorSha256 = sha256;
} }
// { // {

View File

@ -1 +0,0 @@
sha256-yL5pWbVqf6mEpgYsItLnv8nwSmoMP+SE0rX/s7u2vCg=

View File

@ -5,7 +5,6 @@ import (
"github.com/packwiz/packwiz/cmdshared" "github.com/packwiz/packwiz/cmdshared"
"github.com/packwiz/packwiz/core" "github.com/packwiz/packwiz/core"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/unascribed/FlexVer/go/flexver" "github.com/unascribed/FlexVer/go/flexver"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
"os" "os"
@ -42,8 +41,7 @@ var acceptableVersionsCommand = &cobra.Command{
} }
} }
// Check our flags to see if we're adding or removing // Check our flags to see if we're adding or removing
if viper.GetBool("settings.acceptable-versions.add") { if flagAdd {
// Adding
acceptableVersion := args[0] acceptableVersion := args[0]
// Check if the version is already in the list // Check if the version is already in the list
if slices.Contains(currentVersions, acceptableVersion) { if slices.Contains(currentVersions, acceptableVersion) {
@ -63,9 +61,9 @@ var acceptableVersionsCommand = &cobra.Command{
} }
// Print success message // Print success message
prettyList := strings.Join(currentVersions, ", ") prettyList := strings.Join(currentVersions, ", ")
prettyList += ", " + modpack.Versions["minecraft"]
fmt.Printf("Added %s to acceptable versions list, now %s\n", acceptableVersion, prettyList) fmt.Printf("Added %s to acceptable versions list, now %s\n", acceptableVersion, prettyList)
} else if viper.GetBool("settings.acceptable-versions.remove") { } else if flagRemove {
// Removing
acceptableVersion := args[0] acceptableVersion := args[0]
// Check if the version is in the list // Check if the version is in the list
if !slices.Contains(currentVersions, acceptableVersion) { if !slices.Contains(currentVersions, acceptableVersion) {
@ -87,6 +85,7 @@ var acceptableVersionsCommand = &cobra.Command{
} }
// Print success message // Print success message
prettyList := strings.Join(currentVersions, ", ") prettyList := strings.Join(currentVersions, ", ")
prettyList += ", " + modpack.Versions["minecraft"]
fmt.Printf("Removed %s from acceptable versions list, now %s\n", acceptableVersion, prettyList) fmt.Printf("Removed %s from acceptable versions list, now %s\n", acceptableVersion, prettyList)
} else { } else {
// Overwriting // Overwriting
@ -131,17 +130,19 @@ var acceptableVersionsCommand = &cobra.Command{
} }
// Print success message // Print success message
prettyList := strings.Join(acceptableVersionsDeduped, ", ") prettyList := strings.Join(acceptableVersionsDeduped, ", ")
prettyList += ", " + modpack.Versions["minecraft"]
fmt.Printf("Set acceptable versions to %s\n", prettyList) fmt.Printf("Set acceptable versions to %s\n", prettyList)
} }
}, },
} }
var flagAdd bool
var flagRemove bool
func init() { func init() {
settingsCmd.AddCommand(acceptableVersionsCommand) settingsCmd.AddCommand(acceptableVersionsCommand)
// Add and remove flags for adding or removing specific versions // Add and remove flags for adding or removing specific versions
acceptableVersionsCommand.Flags().BoolP("add", "a", false, "Add a version to the list") acceptableVersionsCommand.Flags().BoolVarP(&flagAdd, "add", "a", false, "Add a version to the list")
acceptableVersionsCommand.Flags().BoolP("remove", "r", false, "Remove a version from the list") acceptableVersionsCommand.Flags().BoolVarP(&flagRemove, "remove", "r", false, "Remove a version from the list")
_ = viper.BindPFlag("settings.acceptable-versions.add", acceptableVersionsCommand.Flags().Lookup("add"))
_ = viper.BindPFlag("settings.acceptable-versions.remove", acceptableVersionsCommand.Flags().Lookup("remove"))
} }