Skip to content

aqua cp on windows #4046

@W1M0R

Description

@W1M0R

aqua info

$ aqua info
{
  "version": "2.53.7",
  "commit_hash": "635b59b152b4ea1c2cafb0c618dc658438dc619e",
  "os": "windows",
  "arch": "amd64",
  "pwd": "C:\\Users\\(USER)\\sdl\\bin\\ubi\\stubs",
  "root_dir": "C:\\Users\\(USER)\\AppData\\Local\\aquaproj-aqua",
  "env": {
    "GITHUB_TOKEN": "(masked)"
  },
  "config_files": [
    {
      "path": "C:\\Users\\(USER)\\sdl\\bin\\ubi\\stubs\\aqua.yaml"
    },
    {
      "path": "C:\\Users\\(USER)\\sdl\\aqua.yaml"
    }
  ]
}

Overview

The aqua cp -o ./some-location command does not copy executables with the correct extension on Windows. The tools exist in some-location but without .exe, e.g. I expected hurl.exe but got hurl.

How to reproduce

aqua.yaml

---
registries:
  - type: standard
    # ref: v4.215.0-2 # renovate: depName=aquaproj/aqua-registry
    ref: v4.396.0 # renovate: depName=aquaproj/aqua-registry
    # ref: b1b803eb9e1eb9759908616413978dc1d6f92eea
    # ref: e833e85f301e8ed08c06c253463028bef80b8b8d
packages:
  - name: Orange-OpenSource/hurl@6.0.0
    tags:
      - example

Other related code such as local Registry


Executed command and output

$ aqua cp -o "C:\Users\user2\AppData\Local\example" -t example
time=2025-07-31T12:41:46+02:00 level=debug msg=no version_constraint matches env=windows/amd64 package_version=0.12 program=aqua program_version=2.53.7 version_constraint=false
time=2025-07-31T12:41:46+02:00 level=debug msg=match the version_constraint env=windows/amd64 package_name=Orange-OpenSource/hurl package_semver=6.0.0 package_version=6.0.0 program=aqua program_version=2.53.7 registry=standard registry_ref=v4.396.0 version_constraint=true
time=2025-07-31T12:41:46+02:00 level=debug msg=installing the package env=windows/amd64 package_name=Orange-OpenSource/hurl package_version=6.0.0 program=aqua program_version=2.53.7 registry=standard
time=2025-07-31T12:41:46+02:00 level=debug msg=check if the package is already installed env=windows/amd64 package_name=Orange-OpenSource/hurl package_version=6.0.0 program=aqua program_version=2.53.7 registry=standard    
time=2025-07-31T12:41:46+02:00 level=debug msg=check the permission env=windows/amd64 file_name=hurl package_name=Orange-OpenSource/hurl package_version=6.0.0 program=aqua program_version=2.53.7 registry=standard
time=2025-07-31T12:41:46+02:00 level=debug msg=add the permission to execute the command env=windows/amd64 file_name=hurl package_name=Orange-OpenSource/hurl package_version=6.0.0 program=aqua program_version=2.53.7 registry=standard
time=2025-07-31T12:41:46+02:00 level=info msg=copying an executable file env=windows/amd64 file_name=hurl package_name=Orange-OpenSource/hurl package_version=6.0.0 program=aqua program_version=2.53.7 registry=standard     
time=2025-07-31T12:41:46+02:00 level=debug msg=check the permission env=windows/amd64 file_name=hurlfmt package_name=Orange-OpenSource/hurl package_version=6.0.0 program=aqua program_version=2.53.7 registry=standard       
time=2025-07-31T12:41:46+02:00 level=debug msg=add the permission to execute the command env=windows/amd64 file_name=hurlfmt package_name=Orange-OpenSource/hurl package_version=6.0.0 program=aqua program_version=2.53.7 registry=standard
time=2025-07-31T12:41:46+02:00 level=info msg=copying an executable file env=windows/amd64 file_name=hurlfmt package_name=Orange-OpenSource/hurl package_version=6.0.0 program=aqua program_version=2.53.7 registry=standard  
time=2025-07-31T12:41:46+02:00 level=debug msg=no version_constraint env=windows/amd64 package_name=golang/go package_version=go1.24.0 program=aqua program_version=2.53.7 registry=standard registry_ref=v4.392.0
time=2025-07-31T12:41:46+02:00 level=debug msg=match the version_constraint env=windows/amd64 package_name=Orange-OpenSource/hurl package_semver=6.0.0 package_version=6.0.0 program=aqua program_version=2.53.7 registry=standard registry_ref=v4.392.0 version_constraint=true
time=2025-07-31T12:41:46+02:00 level=debug msg=no version_constraint env=windows/amd64 package_name=mattn/goreman package_version=v0.3.16 program=aqua program_version=2.53.7 registry=standard registry_ref=v4.392.0
time=2025-07-31T12:41:46+02:00 level=debug msg=match the version_constraint env=windows/amd64 package_name=nodejs/node package_semver=v22.6.0 package_version=v22.6.0 program=aqua program_version=2.53.7 registry=standard registry_ref=v4.392.0 version_constraint=true
time=2025-07-31T12:41:46+02:00 level=debug msg=no version_constraint env=windows/amd64 package_name=protocolbuffers/protobuf/protoc package_version=v21.8 program=aqua program_version=2.53.7 registry=standard registry_ref=v4.392.0
time=2025-07-31T12:41:46+02:00 level=debug msg=match the version_constraint env=windows/amd64 package_name=google/flatbuffers package_semver=v24.12.23 package_version=v24.12.23 program=aqua program_version=2.53.7 registry=local version_constraint=true
time=2025-07-31T12:41:46+02:00 level=debug msg=no version_constraint env=windows/amd64 package_name=github.com/brianvoe/gofakeit/v7/cmd/gofakeit package_version=v7.2.1 program=aqua program_version=2.53.7 registry=local    
time=2025-07-31T12:41:46+02:00 level=debug msg=no version_constraint env=windows/amd64 package_name=crates.io/fake package_version=3.1.0 program=aqua program_version=2.53.7 registry=local
time=2025-07-31T12:41:46+02:00 level=debug msg=no version_constraint env=windows/amd64 package_name=github.com/stefanlogue/meteor package_version=v0.25.0 program=aqua program_version=2.53.7 registry=local
time=2025-07-31T12:41:46+02:00 level=debug msg=no version_constraint env=windows/amd64 package_name=github.com/legaard/uuidy package_version=v0.2.1 program=aqua program_version=2.53.7 registry=local
time=2025-07-31T12:41:46+02:00 level=debug msg=match the version_constraint env=windows/amd64 package_name=goreleaser/goreleaser package_semver=v2.7.0 package_version=v2.7.0 program=aqua program_version=2.53.7 registry=standard registry_ref=v4.392.0 version_constraint=true
time=2025-07-31T12:41:46+02:00 level=debug msg=match the version_constraint env=windows/amd64 package_name=gitlab.com/gitlab-org/cli package_semver=v1.53.0 package_version=v1.53.0 program=aqua program_version=2.53.7 registry=standard registry_ref=v4.392.0 version_constraint=true
time=2025-07-31T12:41:46+02:00 level=debug msg=no version_constraint env=windows/amd64 package_name=github.com/josephspurrier/goversioninfo/cmd/goversioninfo package_version=v1.4.1 program=aqua program_version=2.53.7 registry=local
time=2025-07-31T12:41:46+02:00 level=debug msg=skip installing the package because package tags are unmatched env=windows/amd64 package_name=golang/go package_version=go1.24.0 program=aqua program_version=2.53.7 registry=standard
time=2025-07-31T12:41:46+02:00 level=debug msg=skip installing the package because package tags are unmatched env=windows/amd64 package_name=Orange-OpenSource/hurl package_version=6.0.0 program=aqua program_version=2.53.7 registry=standard
time=2025-07-31T12:41:46+02:00 level=debug msg=skip installing the package because package tags are unmatched env=windows/amd64 package_name=mattn/goreman package_version=v0.3.16 program=aqua program_version=2.53.7 registry=standard
time=2025-07-31T12:41:46+02:00 level=debug msg=skip installing the package because package tags are unmatched env=windows/amd64 package_name=nodejs/node package_version=v22.6.0 program=aqua program_version=2.53.7 registry=standard
time=2025-07-31T12:41:46+02:00 level=debug msg=skip installing the package because package tags are unmatched env=windows/amd64 package_name=protocolbuffers/protobuf/protoc package_version=v21.8 program=aqua program_version=2.53.7 registry=standard
time=2025-07-31T12:41:46+02:00 level=debug msg=skip installing the package because package tags are unmatched env=windows/amd64 package_name=google/flatbuffers package_version=v24.12.23 program=aqua program_version=2.53.7 registry=local
time=2025-07-31T12:41:46+02:00 level=debug msg=skip installing the package because package tags are unmatched env=windows/amd64 package_name=github.com/brianvoe/gofakeit/v7/cmd/gofakeit package_version=v7.2.1 program=aqua program_version=2.53.7 registry=local
time=2025-07-31T12:41:46+02:00 level=debug msg=skip installing the package because package tags are unmatched env=windows/amd64 package_name=crates.io/fake package_version=3.1.0 program=aqua program_version=2.53.7 registry=local
time=2025-07-31T12:41:46+02:00 level=debug msg=skip installing the package because package tags are unmatched env=windows/amd64 package_name=github.com/stefanlogue/meteor package_version=v0.25.0 program=aqua program_version=2.53.7 registry=local
time=2025-07-31T12:41:46+02:00 level=debug msg=skip installing the package because package tags are unmatched env=windows/amd64 package_name=github.com/legaard/uuidy package_version=v0.2.1 program=aqua program_version=2.53.7 registry=local
time=2025-07-31T12:41:46+02:00 level=debug msg=skip installing the package because package tags are unmatched env=windows/amd64 package_name=goreleaser/goreleaser package_version=v2.7.0 program=aqua program_version=2.53.7 registry=standard
time=2025-07-31T12:41:46+02:00 level=debug msg=skip installing the package because package tags are unmatched env=windows/amd64 package_name=gitlab.com/gitlab-org/cli package_version=v1.53.0 program=aqua program_version=2.53.7 registry=standard
time=2025-07-31T12:41:46+02:00 level=debug msg=skip installing the package because package tags are unmatched env=windows/amd64 package_name=github.com/josephspurrier/goversioninfo/cmd/goversioninfo package_version=v1.4.1 program=aqua program_version=2.53.7 registry=local

$ aqua which hurl
time=2025-07-31T12:49:37+02:00 level=debug msg=reading registry cache config_file_path=C:\Users\user2\sdl\bin\ubi\stubs\aqua.yaml env=windows/amd64 exe_name=hurl program=aqua program_version=2.53.7
time=2025-07-31T12:49:37+02:00 level=debug msg=getting a package from a registry cache config_file_path=C:\Users\user2\sdl\bin\ubi\stubs\aqua.yaml env=windows/amd64 exe_name=hurl package_name=Orange-OpenSource/hurl program=aqua program_version=2.53.7 registry_file_path=C:\Users\user2\AppData\Local\aquaproj-aqua\registries\github_content\github.com\aquaproj\aqua-registry\v4.396.0\registry.yaml registry_name=standard
time=2025-07-31T12:49:37+02:00 level=debug msg=match the version_constraint config_file_path=C:\Users\user2\sdl\bin\ubi\stubs\aqua.yaml env=windows/amd64 exe_name=hurl package_name=Orange-OpenSource/hurl package_semver=6.0.0 package_version=6.0.0 program=aqua program_version=2.53.7 registry_name=standard version_constraint=true    
time=2025-07-31T12:49:37+02:00 level=debug msg=updating registry cache config_file_path=C:\Users\user2\sdl\bin\ubi\stubs\aqua.yaml env=windows/amd64 exe_name=hurl program=aqua program_version=2.53.7
C:\Users\user2\AppData\Local\aquaproj-aqua\pkgs\github_release\github.com\Orange-OpenSource\hurl\6.0.0\hurl-6.0.0-x86_64-pc-windows-msvc.zip\hurl.exe

$ ls "C:\Users\user2\AppData\Local\example"
hurl
hurlfmt

Notice that aqua which hurl correctly lists hurl.exe: C:\Users\user2\AppData\Local\aquaproj-aqua\pkgs\github_release\github.com\Orange-OpenSource\hurl\6.0.0\hurl-6.0.0-x86_64-pc-windows-msvc.zip\hurl.exe.

Expected behaviour

The copied binary tools must have a .exe extension:

$ ls "C:\Users\user2\AppData\Local\example"
hurl.exe
hurlfmt.exe

Actual behaviour

Instead, the binary files are copied without the .exe extension:

$ ls "C:\Users\user2\AppData\Local\example"
hurl
hurlfmt

Note

When you specify a specific tool to copy, then it correctly adds the .exe extension:

> aqua cp -o "C:\Users\user2\AppData\Local\example" hurl
time=2025-07-31T13:10:27+02:00 level=debug msg=no version_constraint matches env=windows/amd64 package_version=0.12 program=aqua program_version=2.53.7 version_constraint=false
time=2025-07-31T13:10:27+02:00 level=debug msg=reading registry cache config_file_path=C:\Users\user2\sdl\bin\ubi\stubs\aqua.yaml env=windows/amd64 exe_name=hurl program=aqua program_version=2.53.7
time=2025-07-31T13:10:27+02:00 level=debug msg=getting a package from a registry cache config_file_path=C:\Users\user2\sdl\bin\ubi\stubs\aqua.yaml env=windows/amd64 exe_name=hurl package_name=Orange-OpenSource/hurl program=aqua program_version=2.53.7 registry_file_path=C:\Users\user2\AppData\Local\aquaproj-aqua\registries\github_content\github.com\aquaproj\aqua-registry\v4.396.0\registry.yaml registry_name=standard
time=2025-07-31T13:10:27+02:00 level=debug msg=match the version_constraint config_file_path=C:\Users\user2\sdl\bin\ubi\stubs\aqua.yaml env=windows/amd64 exe_name=hurl package_name=Orange-OpenSource/hurl package_semver=6.0.0 package_version=6.0.0 program=aqua program_version=2.53.7 registry_name=standard version_constraint=true    
time=2025-07-31T13:10:27+02:00 level=debug msg=updating registry cache config_file_path=C:\Users\user2\sdl\bin\ubi\stubs\aqua.yaml env=windows/amd64 exe_name=hurl program=aqua program_version=2.53.7
time=2025-07-31T13:10:27+02:00 level=debug msg=installing the package env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl package_name=Orange-OpenSource/hurl package_version=6.0.0 program=aqua program_version=2.53.7 registry=standard
time=2025-07-31T13:10:27+02:00 level=debug msg=check if the package is already installed env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl package_name=Orange-OpenSource/hurl package_version=6.0.0 program=aqua program_version=2.53.7 registry=standard
time=2025-07-31T13:10:27+02:00 level=debug msg=check the permission env=windows/amd64 exe_name=hurl file_name=hurl package=Orange-OpenSource/hurl package_name=Orange-OpenSource/hurl package_version=6.0.0 program=aqua program_version=2.53.7 registry=standard
time=2025-07-31T13:10:27+02:00 level=debug msg=add the permission to execute the command env=windows/amd64 exe_name=hurl file_name=hurl package=Orange-OpenSource/hurl package_name=Orange-OpenSource/hurl package_version=6.0.0 program=aqua program_version=2.53.7 registry=standard
time=2025-07-31T13:10:27+02:00 level=debug msg=check the permission env=windows/amd64 exe_name=hurl file_name=hurlfmt package=Orange-OpenSource/hurl package_name=Orange-OpenSource/hurl package_version=6.0.0 program=aqua program_version=2.53.7 registry=standard
time=2025-07-31T13:10:27+02:00 level=debug msg=add the permission to execute the command env=windows/amd64 exe_name=hurl file_name=hurlfmt package=Orange-OpenSource/hurl package_name=Orange-OpenSource/hurl package_version=6.0.0 program=aqua program_version=2.53.7 registry=standard
time=2025-07-31T13:10:27+02:00 level=debug msg=check if exec file exists env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl program=aqua program_version=2.53.7
time=2025-07-31T13:10:27+02:00 level=debug msg=command isn't found. wait for lazy install env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl program=aqua program_version=2.53.7 retry_count=1
time=2025-07-31T13:10:27+02:00 level=debug msg=check if exec file exists env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl program=aqua program_version=2.53.7
time=2025-07-31T13:10:27+02:00 level=debug msg=command isn't found. wait for lazy install env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl program=aqua program_version=2.53.7 retry_count=2
time=2025-07-31T13:10:27+02:00 level=debug msg=check if exec file exists env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl program=aqua program_version=2.53.7
time=2025-07-31T13:10:27+02:00 level=debug msg=command isn't found. wait for lazy install env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl program=aqua program_version=2.53.7 retry_count=3
time=2025-07-31T13:10:27+02:00 level=debug msg=check if exec file exists env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl program=aqua program_version=2.53.7
time=2025-07-31T13:10:27+02:00 level=debug msg=command isn't found. wait for lazy install env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl program=aqua program_version=2.53.7 retry_count=4
time=2025-07-31T13:10:27+02:00 level=debug msg=check if exec file exists env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl program=aqua program_version=2.53.7
time=2025-07-31T13:10:27+02:00 level=debug msg=command isn't found. wait for lazy install env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl program=aqua program_version=2.53.7 retry_count=5
time=2025-07-31T13:10:27+02:00 level=debug msg=check if exec file exists env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl program=aqua program_version=2.53.7
time=2025-07-31T13:10:27+02:00 level=debug msg=command isn't found. wait for lazy install env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl program=aqua program_version=2.53.7 retry_count=6
time=2025-07-31T13:10:27+02:00 level=debug msg=check if exec file exists env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl program=aqua program_version=2.53.7
time=2025-07-31T13:10:27+02:00 level=debug msg=command isn't found. wait for lazy install env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl program=aqua program_version=2.53.7 retry_count=7
time=2025-07-31T13:10:27+02:00 level=debug msg=check if exec file exists env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl program=aqua program_version=2.53.7
time=2025-07-31T13:10:27+02:00 level=debug msg=command isn't found. wait for lazy install env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl program=aqua program_version=2.53.7 retry_count=8
time=2025-07-31T13:10:27+02:00 level=debug msg=check if exec file exists env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl program=aqua program_version=2.53.7
time=2025-07-31T13:10:27+02:00 level=debug msg=command isn't found. wait for lazy install env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl program=aqua program_version=2.53.7 retry_count=9
time=2025-07-31T13:10:27+02:00 level=debug msg=check if exec file exists env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl program=aqua program_version=2.53.7
time=2025-07-31T13:10:27+02:00 level=debug msg=command isn't found. wait for lazy install env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl program=aqua program_version=2.53.7 retry_count=10
time=2025-07-31T13:10:27+02:00 level=info msg=coping a file dest=C:\Users\user2\AppData\Local\ubi\hurl.exe env=windows/amd64 exe_name=hurl package=Orange-OpenSource/hurl program=aqua program_version=2.53.7

> ls "C:\Users\user2\AppData\Local\example"
hurl.exe

It looks like it is only a problem when copying all tools. The issue is probably related to something in this code:

if len(param.Args) == 0 {
return c.installer.Install(ctx, logE, param) //nolint:wrapcheck
}

I think that the issue lies here:

for exeName := range exeNames {
if err := is.Copy(filepath.Join(is.copyDir, exeName), exePath); err != nil {
return err
}
}

Maybe it should also do a similar check like this instead:

if c.runtime.GOOS == "windows" && filepath.Ext(exeName) == "" {
p += ".exe"
}

A Windows test could be added here:

func TestController_Copy(t *testing.T) { //nolint:funlen
t.Parallel()
data := []struct {
name string
param *config.Param
pkgInstaller cp.PackageInstaller
fs afero.Fs
rt *runtime.Runtime
whichCtrl cp.WhichController
installer cp.Installer
isErr bool
}{
{
name: "no arg",
param: &config.Param{},
fs: afero.NewMemMapFs(),
installer: &cp.MockInstaller{},
},
{
name: "gh",
param: &config.Param{
MaxParallelism: 5,
Args: []string{
"gh",
},
},
rt: &runtime.Runtime{
GOOS: "darwin",
GOARCH: "amd64",
},
fs: afero.NewMemMapFs(),
installer: &cp.MockInstaller{},
whichCtrl: &which.MockController{
FindResult: &which.FindResult{
ExePath: "/home/foo/.local/share/aquaproj-aqua/pkgs/github_release/github.com/cli/cli/v2.17.0/gh_2.17.0_macOS_amd64.tar.gz/gh_2.17.0_macOS_amd64/bin/gh",
Package: &config.Package{
Package: &aqua.Package{
Name: "cli/cli",
},
},
Config: &aqua.Config{
Checksum: &aqua.Checksum{
Enabled: ptr.Bool(true),
RequireChecksum: ptr.Bool(true),
},
},
ConfigFilePath: "aqua.yaml",
},
},
pkgInstaller: &cp.MockPackageInstaller{},
},
}
logE := logrus.NewEntry(logrus.New())
for _, d := range data {
t.Run(d.name, func(t *testing.T) {
t.Parallel()
ctx := t.Context()
ctrl := cp.New(d.param, d.pkgInstaller, d.fs, d.rt, d.whichCtrl, d.installer, &policy.MockReader{})
if err := ctrl.Copy(ctx, logE, d.param); err != nil {
if d.isErr {
return
}
t.Fatal(err)
}
if d.isErr {
t.Fatal("error should be returned")
}
})
}
}

Related links:

  1. feat: add cp command #1061
  2. 9e584e9#diff-42fd29080f94de3ec7b97d790bc689332b35659155a0d7fd28643409e01dbcf8
  3. 9e584e9#diff-6ac0cfd7ab01a4a01b4c1a5c837b676a522cd0744ce41513be35fd16cf137873
  4. b64bf43#diff-42fd29080f94de3ec7b97d790bc689332b35659155a0d7fd28643409e01dbcf8
  5. feat(cp): support copying all packages #1247

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions