File scm-manager-cli-1.0.1.obscpio of Package scm-manager-cli

07070100000000000081A400000000000000000000000162D515C00000010E000000000000000000000000000000000000002400000000scm-manager-cli-1.0.1/.editorconfig# EditorConfig is awesome: https://EditorConfig.org

# top-most EditorConfig file
root = true

# Match golang fmt
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = tab
indent_size = 4

[{*.yml, *.yaml}]
indent_style = space
indent_size = 2
07070100000001000081A400000000000000000000000162D515C0000000E0000000000000000000000000000000000000002100000000scm-manager-cli-1.0.1/.gitignore# Default ignored files
/shelf/
/.idea/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
scm
scm.exe
.cache/
.gnupg/

.idea

dist/
07070100000002000081A400000000000000000000000162D515C000000D12000000000000000000000000000000000000002700000000scm-manager-cli-1.0.1/.goreleaser.yaml# This is an example .goreleaser.yml file with some sensible defaults.
# Make sure to check the documentation at https://goreleaser.com
project_name: scm
release:
  disable: true

before:
  hooks:
    # You may remove this if you don't use go modules.
    - go mod tidy
    # you may remove this if you don't need go generate
    - go generate ./...
builds:
  - env:
      - CGO_ENABLED=0
    goos:
      - linux
      - windows
      - darwin
      - freebsd
    goarch:
      - amd64
      - arm64
    ldflags:
      - -w -s
      - -X github.com/scm-manager/cli/pkg.version={{.Version}}
      - -X github.com/scm-manager/cli/pkg.commitHash={{.Commit}}
      - -X github.com/scm-manager/cli/pkg.buildTime={{.Date}}

archives:
  - id: archives
    name_template: "{{ .ProjectName }}-cli_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
    replacements:
      darwin: Darwin
      linux: Linux
      windows: Windows
      386: i386
      amd64: x86_64
    format_overrides:
    - goos: windows
      format: zip

snapshot:
  name_template: "{{ incpatch .Version }}-SNAPSHOT"

changelog:
  skip: true

nfpms:
  - id: rpm
    package_name: scm-cli
    vendor: Cloudogu GmbH
    # TODO CLI subpage
    homepage: https://scm-manager.org
    maintainer: SCM Team <scm-team@cloudogu.com>
    description: SCM-Manager CLI Client
    license: MIT
    formats:
      - rpm
    bindir: /usr/bin
    priority: extra
    section: devel
    rpm:
      group: Development/Tools
      signature:
        key_file: '{{ .Env.GPG_KEY_PATH }}'

  - id: deb
    package_name: scm-cli
    vendor: Cloudogu GmbH
    homepage: https://scm-manager.org/cli
    maintainer: SCM Team <scm-team@cloudogu.com>
    description: SCM-Manager CLI Client
    license: MIT
    formats:
      - deb
    bindir: /usr/bin
    priority: extra
    section: devel
    deb:
      signature:
        key_file: '{{ .Env.GPG_KEY_PATH }}'

brews:
  - name: scm-cli
    tap:
      owner: scm-manager
      name: homebrew-tap
      branch: master
    url_template: https://packages.scm-manager.org/repository/scm-cli-releases/{{.Tag}}/{{.ArtifactName}}
    homepage: https://scm-manager.org/cli
    description: SCM-Manager CLI Client
    license: MIT
    skip_upload: true

scoop:
  name: scm-cli
  url_template: https://packages.scm-manager.org/repository/scm-cli-releases/{{.Tag}}/{{.ArtifactName}}
  bucket:
    owner: scm-manager
    name: scoop-bucket
    branch: main
  homepage: https://scm-manager.org/cli
  description: SCM-Manager CLI Client
  license: MIT
  skip_upload: true

uploads:
  - name: default
    ids:
    - archives
    mode: archive
    checksum: true
    method: PUT
    target: https://packages.scm-manager.org/repository/scm-cli-releases/{{.Version}}
  - name: rpm
    ids:
    - rpm
    mode: archive
    method: PUT
    target: https://packages.scm-manager.org/repository/yum-v2-releases/
  - name: deb
    ids:
    - deb
    mode: archive
    method: POST
    custom_artifact_name: true
    target: https://packages.scm-manager.org/repository/apt-v2-releases/

checksum:
  name_template: 'checksums.txt'
  ids:
  - archives

signs:
  - artifacts: checksum
    args:
    - --batch
    - --pinentry-mode
    - loopback
    - --passphrase
    - "{{ .Env.GPG_PASSWORD }}"
    - --yes
    - --armor
    - --output
    - "${signature}"
    - "--detach-sign"
    - "${artifact}"
07070100000003000081A400000000000000000000000162D515C000000181000000000000000000000000000000000000002300000000scm-manager-cli-1.0.1/CHANGELOG.md# Changelog
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 1.0.1 - 2022-07-18
### Fixed
- Improve error messages
- Scoop bucket directory

## 1.0.0 - 2022-04-29
### Added
- Initial release
07070100000004000081A400000000000000000000000162D515C00000130A000000000000000000000000000000000000002200000000scm-manager-cli-1.0.1/Jenkinsfile#!groovy
pipeline {

  options {
    buildDiscarder(logRotator(numToKeepStr: '10'))
    disableConcurrentBuilds()
  }

  agent {
    node {
      label 'docker'
    }
  }

  environment {
    HOME = "${env.WORKSPACE}"
   	LANGUAGE = "en"
  }

  stages {

    stage('Set Version') {
      when {
          branch pattern: 'release/*', comparator: 'GLOB'
      }
      steps {
        // fetch all remotes from origin
        sh 'git config --replace-all "remote.origin.fetch" "+refs/heads/*:refs/remotes/origin/*"'
        sh 'git fetch --all'

		// checkout, reset and merge
		sh 'git checkout main'
		sh 'git reset --hard origin/main'
		sh "git merge --ff-only ${env.BRANCH_NAME}"

        // set tag
        tag releaseVersion
      }
    }

    stage('Tests') {
      agent {
        docker {
          image 'golang:1.17.5'
          reuseNode true
        }
      }
      steps {
        sh 'go test ./...'
      }
    }

    stage('Build') {
      agent {
        docker {
          image 'golang:1.17.5'
          reuseNode true
        }
      }
      steps {
        sh 'make build'
      }
    }

	stage('Publish') {
      when {
        branch pattern: 'release/*', comparator: 'GLOB'
        expression { return isBuildSuccess() }
      }
      agent {
        docker {
          image 'golang:1.17.5'
          reuseNode true
        }
      }
      steps {
        withPublishEnvironment {
		  ansiColor('xterm') {
       	    sh 'VERSION=v1.7.0 curl -sL https://git.io/goreleaser | bash -s -- release --rm-dist'
		  }
		  sh "go run pkg/build/upload/app.go dist/scm-cli.json scoop-bucket main bucket/scm-cli.json \"Update scoop scm-cli to ${releaseVersion}\""
		  sh "go run pkg/build/upload/app.go dist/scm-cli.rb homebrew-tap master Formula/scm-cli.rb \"Update brew scm-cli to ${releaseVersion}\""
		  sh "go run pkg/build/descriptor/app.go dist > dist/release.yaml"
		  sh "go run pkg/build/upload/app.go dist/release.yaml website master content/cli/releases/${hyphenatedReleaseVersion}.yaml \"Release cli version ${releaseVersion}\""
        }
      }
	}

    stage('Update Repository') {
	  when {
		branch pattern: 'release/*', comparator: 'GLOB'
	  }
	  steps {
		// merge main in to develop
		sh 'git checkout develop'
		sh 'git merge main'

		// push changes back to remote repository
		authGit 'cesmarvin-github', 'push origin main --tags'
		authGit 'cesmarvin-github', 'push origin develop --tags'
		authGit 'cesmarvin-github', "push origin :${env.BRANCH_NAME}"
	  }
    }
  }

  post {
    failure {
      mail to: "scm-team@cloudogu.com",
        subject: "${JOB_NAME} - Build #${BUILD_NUMBER} - ${currentBuild.currentResult}!",
        body: "Check console output at ${BUILD_URL} to view the results."
    }
  }

}

void withPublishEnvironment(Closure<Void> closure) {
  withCredentials([
    usernamePassword(credentialsId: 'maven.scm-manager.org', usernameVariable: 'UPLOAD_DEFAULT_USERNAME', passwordVariable: 'UPLOAD_DEFAULT_SECRET'),
    usernamePassword(credentialsId: 'maven.scm-manager.org', usernameVariable: 'UPLOAD_RPM_USERNAME', passwordVariable: 'UPLOAD_RPM_SECRET'),
    usernamePassword(credentialsId: 'maven.scm-manager.org', usernameVariable: 'UPLOAD_DEB_USERNAME', passwordVariable: 'UPLOAD_DEB_SECRET'),
    file(credentialsId: 'oss-gpg-secring', variable: 'GPG_KEY_PATH'),
    usernamePassword(credentialsId: 'oss-keyid-and-passphrase', usernameVariable: 'GPG_KEY_ID', passwordVariable: 'GPG_PASSWORD'),
    usernamePassword(credentialsId: 'oss-keyid-and-passphrase', usernameVariable: 'NFPM_RPM_KEY_ID', passwordVariable: 'NFPM_RPM_PASSPHRASE'),
    usernamePassword(credentialsId: 'oss-keyid-and-passphrase', usernameVariable: 'NFPM_DEB_KEY_ID', passwordVariable: 'NFPM_DEB_PASSPHRASE'),
    usernamePassword(credentialsId: 'cesmarvin-github', usernameVariable: 'GITHUB_USERNAME', passwordVariable: 'GITHUB_API_TOKEN'),
  ]) {
      sh 'gpg --no-tty --batch --yes --import $GPG_KEY_PATH'
  	  closure.call()
  }
}

String getHyphenatedReleaseVersion() {
  return getReleaseVersion().replace('.', '-')
}

String getReleaseVersion() {
  return env.BRANCH_NAME.substring("release/".length());
}

void commit(String message) {
  sh "git -c user.name='CES Marvin' -c user.email='cesmarvin@cloudogu.com' commit -m '${message}'"
}

void tag(String version) {
  String message = "Release version ${version}"
  sh "git -c user.name='CES Marvin' -c user.email='cesmarvin@cloudogu.com' tag -m '${message}' ${version}"
}

boolean isBuildSuccess() {
  return currentBuild.result == null || currentBuild.result == 'SUCCESS'
}

void authGit(String credentials, String command) {
  withCredentials([
    usernamePassword(credentialsId: credentials, usernameVariable: 'AUTH_USR', passwordVariable: 'AUTH_PSW')
  ]) {
    sh "git -c credential.helper=\"!f() { echo username='\$AUTH_USR'; echo password='\$AUTH_PSW'; }; f\" ${command}"
  }
}
07070100000005000081A400000000000000000000000162D515C000000434000000000000000000000000000000000000001E00000000scm-manager-cli-1.0.1/LICENSEThe MIT License (MIT)

Copyright (c) 2015 gatsbyjs

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

07070100000006000081A400000000000000000000000162D515C000000146000000000000000000000000000000000000001F00000000scm-manager-cli-1.0.1/MakefileGITHASH:=$(shell git rev-parse --short HEAD)
BUILDTIME:=$(shell TZ=UTC date +"%Y-%m-%dT%H:%M:%SZ")

LDFLAGS='-w -extldflags "-static" -s -X github.com/scm-manager/cli/pkg.commitHash=${GITHASH} -X github.com/scm-manager/cli/pkg.buildTime=${BUILDTIME}'

.PHONY:
build:
	go build -a -tags netgo -ldflags ${LDFLAGS} -o scm scm.go
07070100000007000081A400000000000000000000000162D515C00000016F000000000000000000000000000000000000002000000000scm-manager-cli-1.0.1/README.md# Usage

1. Run `go build scm.go` to compile the binary
2. Start using the cli with `./scm login {server_url}`
3. Find out which commands are available on your server using `./scm`

# Documentation
Find out how to implement own cli commands in the related [cli guidelines](https://github.com/scm-manager/scm-manager/blob/develop/docs/en/development/cli-guideline.md)
07070100000008000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000001B00000000scm-manager-cli-1.0.1/docs07070100000009000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000001E00000000scm-manager-cli-1.0.1/docs/en0707010000000A000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000002B00000000scm-manager-cli-1.0.1/docs/en/installation0707010000000B000081A400000000000000000000000162D515C0000005B3000000000000000000000000000000000000003500000000scm-manager-cli-1.0.1/docs/en/installation/debian.md---
title: Debian/Ubuntu
subtitle: Installation of SCM-Manager CLI Client for Debian-based linux distributions
displayToc: true
---

## Quickstart

The following code block will configure an apt repository for SCM-Manager CLI Client and install it.

```bash
echo "deb [arch=$(dpkg --print-architecture)] https://packages.scm-manager.org/repository/apt-v2-releases/ stable main" | sudo tee /etc/apt/sources.list.d/scm-manager.list
sudo apt-key adv --recv-keys --keyserver hkps://keys.openpgp.org 0x975922F193B07D6E
sudo apt-get update
sudo apt-get install scm-cli
```

## Detailed installation

To install SCM-Manager CLI as a debian package (.deb), we have to configure an apt repository.
Replace `<arch>` with your system architecture. You can find it out by using `dpkg --print-architecture`.
Create a file at `/etc/apt/sources.list.d/scm-manager.list` with the following content:

```text
deb [arch=<arch>] https://packages.scm-manager.org/repository/apt-v2-releases/ stable main
```

This will add the apt repository of the SCM-Manager stable releases to the list of your apt repositories.
To ensure the integrity of the debian packages we have to import the gpg key for the repository.

```bash
sudo apt-key adv --recv-keys --keyserver hkps://keys.openpgp.org 0x975922F193B07D6E
```

After we have imported the gpg key, we can update the package index and install the SCM-Manager CLI Client:

```bash
sudo apt-get update
sudo apt-get install scm-cli
```
0707010000000C000081A400000000000000000000000162D515C00000028C000000000000000000000000000000000000003700000000scm-manager-cli-1.0.1/docs/en/installation/homebrew.md---
title: Homebrew
subtitle: SCM-Manager CLI Client installation using homebrew
displayToc: true
---

# Homebrew
To install the SCM-Manager CLI Client we offer a [Homebrew](https://brew.sh/) tap.
This CLI Client does not work standalone but need a running SCM-Manager server.

## Quickstart

```bash
brew install scm-manager/tap/scm-cli
```

## Detailed installation

To install SCM-Manager with homebrew we had to add the SCM-Manager tap:
```bash
brew tap scm-manager/tap
```
After the tap was added, we can install the SCM-Manager CLI Client:
```bash
brew install scm-cli
```

Now the CLI Client can be started:

```bash
scm login {server_url}
```

0707010000000D000081A400000000000000000000000162D515C0000000E4000000000000000000000000000000000000003400000000scm-manager-cli-1.0.1/docs/en/installation/index.md---
title: Installation
subtitle: Installation of SCM-Manager CLI CLient
partiallyActive: true
---

* [Debian/Ubuntu](debian/)
* [Red Hat/CentOS/Fedora](redhat/)
* [Windows](windows/)
* [Darwin](darwin/)
* [Unix General](unix/)
0707010000000E000081A400000000000000000000000162D515C0000005C1000000000000000000000000000000000000003500000000scm-manager-cli-1.0.1/docs/en/installation/redhat.md---
title: Redhat/CentOS/Fedora
subtitle: Installation of SCM-Manager CLI Client for RedHat-based linux distributions
displayToc: true
---

## Quickstart

The following code block will configure a yum repository for scm-manager and install it.

```bash
cat << EOF | sudo tee /etc/yum.repos.d/SCM-Manager.repo
[scm-manager]
name=SCM-Manager Repository
baseurl=https://packages.scm-manager.org/repository/yum-v2-releases/
enabled=1
gpgcheck=1
priority=1
gpgkey=file:///etc/pki/rpm-gpg/SCM-Manager
EOF
sudo curl -o /etc/pki/rpm-gpg/SCM-Manager https://packages.scm-manager.org/repository/keys/gpg/oss-cloudogu-com.pub
sudo yum install scm-cli
```

## Detailed installation

To install SCM-Manager as a redhat package (.rpm), we have to configure a yum repository.
Create a file at `/etc/yum.repos.d/SCM-Manager.repo` with the following content:

```ini
[scm-manager]
name=SCM-Manager Repository
baseurl=https://packages.scm-manager.org/repository/yum-v2-releases/
enabled=1
gpgcheck=1
priority=1
gpgkey=file:///etc/pki/rpm-gpg/SCM-Manager
```

This will add the yum repository of the scm-manager stable releases to the list of your yum repositories.
To ensure the integrity of the rpm packages we have to import the gpg key for the repository.

```bash
sudo curl -o /etc/pki/rpm-gpg/SCM-Manager https://packages.scm-manager.org/repository/keys/gpg/oss-cloudogu-com.pub
```

After we have imported the gpg key, we can install scm-manager:

```bash
sudo yum install scm-cli
```
0707010000000F000081A400000000000000000000000162D515C0000002E6000000000000000000000000000000000000003300000000scm-manager-cli-1.0.1/docs/en/installation/unix.md---
title: Unix
subtitle: General unix installation
displayToc: true
---

## Requirements
This tool does not work standalone but need a running SCM-Manager server.

## Installation
Grab the latest version and checksum from [download page](/cli) and replace `<version>` and `<checksum>` in the code blocks below.
Download and verify the checksum.

```bash
wget https://packages.scm-manager.org/repository/scm-cli-releases/<version>/scm-cli_<version>_<os>_<arch>.tar.gz
echo "<checksum> *scm-cli_<version>_<os>_<arch>.tar.gz" | sha256sum -c -
```
Extract the archive:
```bash
sudo tar xvfz scm-cli_<version>_<os>_<arch>.tar.gz -C /usr/local/bin
```

## First start
The cli client can be started by using `scm` in your terminal.
```bash
scm
```
07070100000010000081A400000000000000000000000162D515C000000632000000000000000000000000000000000000003600000000scm-manager-cli-1.0.1/docs/en/installation/windows.md---
title: Windows
subtitle: Install SCM-Manager CLI Client on Windows
displayToc: true
---

The following document describes the installation process for SCM-Manager CLI Client on Windows.

## Install SCM-Manager CLI

### Install via Scoop
To install the CLI CLient via Scoop run the following commands:
```
scoop bucket add scm https://github.com/scm-manager/scoop-bucket
scoop install scm-cli
```

### Manual installation

To install SCM-Manager CLI you have to download the latest Windows package from the [download page](/cli/).
After unpacking the archive move the file to a new directory. 
To make it available on your `PATH` you can follow this [instruction](https://stackoverflow.com/questions/1618280/where-can-i-set-path-to-make-exe-on-windows).


## First start
Now we have to open a Terminal (PowerShell, Bash or CMD), in order to run the SCM-Manager CLI Client.
For this to work you must have an SCM-Manager server running and connect your client first. 
You can start with the following command:

```bash
scm.exe login {server_url}
```

### Known problems with mintty (Git Bash, Cygwin)
On some terminals under Windows, problems with stdin or stdout/stderr may occur. For example, when you try to log in,
hitting enter on your username generates a second enter which prevents the possibility to enter your password and the
login fails.

Or, if you have previously logged in e.g. via Powershell, running the CLI won't create any output and the
CLI won't exit.

You can fix these problems by adding the following line to your `.minttyrc` file:

```properties
ConPTY=on
```
07070100000011000081A400000000000000000000000162D515C000000279000000000000000000000000000000000000001D00000000scm-manager-cli-1.0.1/go.modmodule github.com/scm-manager/cli

go 1.17

require (
	github.com/Xuanwo/go-locale v1.1.0
	github.com/stretchr/testify v1.7.1
	github.com/zalando/go-keyring v0.2.1
	golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)

require (
	github.com/alessio/shellescape v1.4.1 // indirect
	github.com/danieljoos/wincred v1.1.0 // indirect
	github.com/davecgh/go-spew v1.1.0 // indirect
	github.com/godbus/dbus/v5 v5.0.6 // indirect
	github.com/pmezard/go-difflib v1.0.0 // indirect
	golang.org/x/sys v0.0.0-20211023085530-d6a326fbbf70 // indirect
	golang.org/x/text v0.3.7 // indirect
)
07070100000012000081A400000000000000000000000162D515C0000011DC000000000000000000000000000000000000001D00000000scm-manager-cli-1.0.1/go.sumgithub.com/Xuanwo/go-locale v1.1.0 h1:51gUxhxl66oXAjI9uPGb2O0qwPECpriKQb2hl35mQkg=
github.com/Xuanwo/go-locale v1.1.0/go.mod h1:UKrHoZB3FPIk9wIG2/tVSobnHgNnceGSH3Y8DY5cASs=
github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0=
github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
github.com/danieljoos/wincred v1.1.0 h1:3RNcEpBg4IhIChZdFRSdlQt1QjCp1sMAPIrOnm7Yf8g=
github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
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/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.7 h1:I6tZjLXD2Q1kjvNbIzB1wvQBsXmKXiVrhpRE8ZjP5jY=
github.com/smartystreets/goconvey v1.6.7/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/zalando/go-keyring v0.2.1 h1:MBRN/Z8H4U5wEKXiD67YbDAr5cj/DOStmSga70/2qKc=
github.com/zalando/go-keyring v0.2.1/go.mod h1:g63M2PPn0w5vjmEbwAX3ib5I+41zdm4esSETOn9Y6Dw=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211023085530-d6a326fbbf70 h1:SeSEfdIxyvwGJliREIJhRPPXvW6sDlLT+UQ3B0hD0NA=
golang.org/x/sys v0.0.0-20211023085530-d6a326fbbf70/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
07070100000013000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000001A00000000scm-manager-cli-1.0.1/pkg07070100000014000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000001E00000000scm-manager-cli-1.0.1/pkg/api07070100000015000081A400000000000000000000000162D515C00000078F000000000000000000000000000000000000002800000000scm-manager-cli-1.0.1/pkg/api/apikey.gopackage api

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/scm-manager/cli/pkg"
	"io"
	"io/ioutil"
	"net/http"
)

type CreateApiKeyRequest struct {
	ApiKey string `json:"apiKey"`
}

func Create(serverUrl string, username string, password string, apiKeyName string) (string, error) {
	loginRequest := CreateApiKeyRequest{ApiKey: apiKeyName}
	payloadBuf := new(bytes.Buffer)
	err := json.NewEncoder(payloadBuf).Encode(loginRequest)
	if err != nil {
		return "", fmt.Errorf("could not encode hostname: %w", err)
	}
	req, _ := http.NewRequest("POST", serverUrl+"/api/v2/cli/login", payloadBuf)
	req.Header.Add("Content-Type", "application/json")
	req.SetBasicAuth(username, password)
	client := pkg.CreateHttpClient()
	res, err := client.Do(req)
	if err != nil {
		return "", fmt.Errorf("could not send login request: %w", err)
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(res.Body)
	if res.StatusCode >= 400 {
		return "", fmt.Errorf("could not create new api key on server. Server returned status code: %d", res.StatusCode)
	}
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return "", fmt.Errorf("could not read login response: %w", err)
	}
	return string(body), nil
}

func Remove(serverUrl string, apiKey string, apiKeyName string) error {
	// Remove api key on server
	req, err := http.NewRequest("DELETE", serverUrl+"/api/v2/cli/logout/"+apiKeyName, nil)
	if err != nil {
		return fmt.Errorf("could not create delete request: %w", err)
	}
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Authorization", "Bearer "+apiKey)
	client := pkg.CreateHttpClient()
	res, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("could not revoke api key on server: %w", err)
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(res.Body)
	if res.StatusCode >= 400 {
		return fmt.Errorf("could not remove api key. Server returned status code: %d", res.StatusCode)
	}
	return nil
}
07070100000016000081A400000000000000000000000162D515C0000004FC000000000000000000000000000000000000002D00000000scm-manager-cli-1.0.1/pkg/api/apikey_test.gopackage api

import (
	"fmt"
	"github.com/stretchr/testify/assert"
	"github.com/zalando/go-keyring"
	"net/http"
	"net/http/httptest"
	"testing"
)

func init() {
	keyring.MockInit()
}

func TestCreate(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		_, err := fmt.Fprintf(w, "api-secret")
		assert.NoError(t, err)
		assert.Equal(t, "Basic YXJ0aHVyOnNlY3JldA==", r.Header.Get("Authorization"))
	}))
	defer server.Close()

	apiKey, err := Create(server.URL, "arthur", "secret", "test-key")
	assert.NoError(t, err)
	assert.Equal(t, "api-secret", apiKey)
}

func TestRemoveIfKeyNotExist(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		assert.Equal(t, "Bearer api-token", r.Header.Get("Authorization"))
	}))
	defer server.Close()

	err := Remove(server.URL, "api-token", "scm-test")
	assert.NoError(t, err)
}

func TestRemove(t *testing.T) {
	serviceName := "scm-test"
	apiKey := "api-token"
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		assert.Equal(t, "Bearer "+apiKey, r.Header.Get("Authorization"))
	}))
	defer server.Close()

	err := Remove(server.URL, apiKey, serviceName)
	assert.NoError(t, err)
}
07070100000017000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000002000000000scm-manager-cli-1.0.1/pkg/build07070100000018000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000002B00000000scm-manager-cli-1.0.1/pkg/build/descriptor07070100000019000081A400000000000000000000000162D515C000000C45000000000000000000000000000000000000003200000000scm-manager-cli-1.0.1/pkg/build/descriptor/app.gopackage main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"gopkg.in/yaml.v3"
	"io/ioutil"
	"log"
	"os"
	"path"
	"path/filepath"
	"strings"
	"time"
)

type MetadataJson struct {
	Tag  string
	Date string
}

type Artifact struct {
	Name   string
	Type   string
	Goarch string
	Goos   string
}

type Package struct {
	Type     string
	Os       string `yaml:",omitempty"`
	Arch     string `yaml:",omitempty"`
	Url      string `yaml:",omitempty"`
	Checksum string `yaml:",omitempty"`
}

type Descriptor struct {
	Tag      string
	Date     string
	Type     string
	Packages []Package
}

func main() {
	dir := os.Args[1]
	file, err := ioutil.ReadFile(path.Join(dir, "metadata.json"))
	if err != nil {
		log.Fatal("could not read metadata.json")
	}

	metadata := MetadataJson{}
	err = json.Unmarshal(file, &metadata)
	if err != nil {
		log.Fatal("could not unmarshal metadata.json")
	}

	file, err = ioutil.ReadFile(path.Join(dir, "artifacts.json"))
	if err != nil {
		log.Fatal("could not read artifacts.json")
	}

	var artifacts []Artifact
	err = json.Unmarshal(file, &artifacts)
	if err != nil {
		log.Fatal("could not unmarshal artifacts.json")
	}

	var packages []Package
	checksums := readChecksums(dir)
	for _, a := range artifacts {
		if a.Type == "Archive" {
			checksum := checksums[a.Name]
			url := fmt.Sprintf("https://packages.scm-manager.org/repository/scm-cli-releases/%s/%s", metadata.Tag, a.Name)
			packages = append(packages, Package{
				Os:       a.Goos,
				Arch:     a.Goarch,
				Checksum: checksum,
				Type:     filepath.Ext(a.Name)[1:],
				Url:      url,
			})
		} else if a.Type == "Linux Package" {
			packages = append(packages, Package{Os: a.Goos, Arch: a.Goarch, Type: filepath.Ext(a.Name)[1:]})
		} else if a.Type == "Brew Tap" {
			packages = append(packages, Package{Type: "homebrew", Os: "linux", Arch: "arm64"})
			packages = append(packages, Package{Type: "homebrew", Os: "linux", Arch: "amd64"})
			packages = append(packages, Package{Type: "homebrew", Os: "darwin", Arch: "arm64"})
			packages = append(packages, Package{Type: "homebrew", Os: "darwin", Arch: "amd64"})
		} else if a.Type == "Scoop Manifest" {
			packages = append(packages, Package{Type: "scoop", Os: "windows", Arch: "amd64"})
		}
	}

	date, err := time.Parse(time.RFC3339Nano, metadata.Date)
	if err != nil {
		log.Fatal("could not parse release date")
	}
	descriptor := Descriptor{Tag: metadata.Tag, Date: date.UTC().Format(time.RFC3339), Type: "cli", Packages: packages}

	bytes, err := yaml.Marshal(&descriptor)
	if err != nil {
		log.Fatal("could not unmarshal artifacts.json")
	}
	fmt.Println(string(bytes))

}

func readChecksums(dir string) map[string]string {
	checksumFile, err := os.Open(path.Join(dir, "checksums.txt"))
	if err != nil {
		log.Fatal("could not read checksums.txt")
	}
	defer checksumFile.Close()
	scanner := bufio.NewScanner(checksumFile)
	checksums := make(map[string]string)
	for scanner.Scan() {
		line := scanner.Text()
		result := strings.Split(line, "  ")
		checksums[result[1]] = result[0]
	}
	err = scanner.Err()
	if err != nil {
		log.Fatal("error during scanning checksums.txt")
	}
	return checksums
}
0707010000001A000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000002700000000scm-manager-cli-1.0.1/pkg/build/upload0707010000001B000081A400000000000000000000000162D515C000000ACC000000000000000000000000000000000000002E00000000scm-manager-cli-1.0.1/pkg/build/upload/app.gopackage main

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
)

type Person struct {
	Name  string `json:"name"`
	Email string `json:"email"`
}

type GitHubUploadRequest struct {
	Message string `json:"message"`
	Branch  string `json:"branch"`
	Author  Person `json:"author"`
	Content string `json:"content"`
	Sha     string `json:"sha,omitempty"`
}

type GitHubContent struct {
	Sha string
}

func receiveSha(token string, url string, branch string) string {
	request, err := http.NewRequest("GET", url+"?ref="+branch, nil)
	if err != nil {
		log.Fatal("Failed to create get request", err)
	}

	request.Header.Set("Authorization", "Token "+token)
	request.Header.Set("Accept", "application/vnd.github.v3+json")

	response, err := http.DefaultClient.Do(request)
	if err != nil {
		log.Fatal("Get request failed", err)
	}

	defer response.Body.Close()

	if response.StatusCode == 404 {
		return ""
	}

	if response.StatusCode >= 300 {
		log.Fatal("Get request failed with status code", response.StatusCode)
	}

	data, err := ioutil.ReadAll(response.Body)
	if err != nil {
		log.Fatal("failed to read response body")
	}

	content := GitHubContent{}
	err = json.Unmarshal(data, &content)
	if err != nil {
		log.Fatal("Failed to unmarshal content", err)
	}

	return content.Sha
}

func main() {
	token := os.Getenv("GITHUB_API_TOKEN")
	if token == "" {
		log.Fatal("missing GitHub API Token")
	}

	args := os.Args

	source := args[1]
	repo := args[2]
	branch := args[3]
	path := args[4]
	commitMessage := args[5]

	url := fmt.Sprintf("https://api.github.com/repos/scm-manager/%s/contents/%s", repo, path)

	file, err := ioutil.ReadFile(source)
	if err != nil {
		log.Fatal("could not read source file")
	}
	content := base64.StdEncoding.EncodeToString(file)

	uploadRequest := GitHubUploadRequest{
		Message: commitMessage,
		Branch:  branch,
		Author:  Person{Name: "CES Marvin", Email: "cesmarvin@cloudogu.com"},
		Content: content,
		Sha:     receiveSha(token, url, branch),
	}

	data, err := json.Marshal(&uploadRequest)
	if err != nil {
		log.Fatal("Could not marshal json")
	}
	request, err := http.NewRequest("PUT", url, bytes.NewBuffer(data))
	if err != nil {
		log.Fatal("could not create upload request")
	}
	request.Header.Set("Authorization", "Token "+token)
	request.Header.Set("Accept", "application/vnd.github.v3+json")

	response, err := http.DefaultClient.Do(request)
	if err != nil {
		log.Fatal("could not send upload request")
	}

	if response.StatusCode >= 300 {
		defer response.Body.Close()
		body, err := ioutil.ReadAll(response.Body)
		if err != nil {
			log.Fatal("Could not read response body")
		}

		log.Fatalf("upload request failed: %d\n\n%s", response.StatusCode, string(body))
	}

}
0707010000001C000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000002200000000scm-manager-cli-1.0.1/pkg/command0707010000001D000081A400000000000000000000000162D515C000000CDC000000000000000000000000000000000000002A00000000scm-manager-cli-1.0.1/pkg/command/exec.gopackage command

import (
	"encoding/json"
	"fmt"
	"github.com/Xuanwo/go-locale"
	"github.com/scm-manager/cli/pkg"
	"io"
	"net/http"
	"os"
)

type ExecuteResponse struct {
	Out  string
	Err  string
	Exit int
}

func CreateExecutor(stdout io.Writer, stderr io.Writer, stdin io.Reader, config *pkg.Configuration) *Executor {
	return &Executor{stdout: stdout, stderr: stderr, stdin: stdin, config: config}
}

func CreateDefaultExecutor(config *pkg.Configuration) (*Executor, error) {
	stdin, err := createStdin()
	if err != nil {
		return nil, err
	}
	return CreateExecutor(os.Stdout, os.Stderr, stdin, config), nil
}

func createStdin() (io.Reader, error) {
	stat, err := os.Stdin.Stat()
	if err != nil {
		return nil, fmt.Errorf("failed to read stat from stdin: %w", err)
	}
	if (stat.Mode() & os.ModeCharDevice) == 0 {
		return os.Stdin, nil
	}
	return nil, nil
}

type Executor struct {
	stdout io.Writer
	stderr io.Writer
	stdin  io.Reader
	config *pkg.Configuration
}

func (e *Executor) Execute(args ...string) (int, error) {
	req, err := e.createRequest(args)
	if err != nil {
		return -1, err
	}
	res, err := e.sendRequest(req)
	if err != nil {
		return -1, err
	}
	defer func(Body io.ReadCloser) {
		_ = Body.Close()
	}(res.Body)
	return e.processResponse(res)
}

func (e *Executor) sendRequest(req *http.Request) (*http.Response, error) {
	client := pkg.CreateHttpClient()
	res, err := client.Do(req)
	if err != nil {
		return res, fmt.Errorf("could not send execution request: %w", err)
	}
	if res.StatusCode >= 400 {
		return res, fmt.Errorf("HTTP Error %d", res.StatusCode)
	}
	return res, nil
}

func (e *Executor) createRequest(args []string) (*http.Request, error) {
	req, _ := http.NewRequest("POST", e.config.ServerUrl+"/api/v2/cli/exec", e.stdin)
	req.Header.Add("Authorization", "Bearer "+e.config.ApiKey)
	e.setCommandVarArgs(req, args)
	err := e.setRequestLocale(req)
	if err != nil {
		return req, err
	}
	return req, nil
}

func (e *Executor) processResponse(res *http.Response) (int, error) {
	decoder := json.NewDecoder(res.Body)
	_, err := decoder.Token()
	if err != nil {
		return -1, fmt.Errorf("could not read token from json: %w", err)
	}

	for decoder.More() {
		response := &ExecuteResponse{}
		err := decoder.Decode(response)
		if err != nil {
			if err == io.EOF {
				break
			}
			return -1, fmt.Errorf("could not decode response body: %w", err)
		}
		if response.Out != "" {
			_, err := e.stdout.Write([]byte(response.Out))
			if err != nil {
				return -1, fmt.Errorf("could not write to stdout: %w", err)
			}
		}
		if response.Err != "" {
			_, err := e.stderr.Write([]byte(response.Err))
			if err != nil {
				return -1, fmt.Errorf("could not write to stderr: %w", err)
			}
		}
		if response.Exit != 0 {
			return response.Exit, nil
		}
	}
	return 0, nil
}

func (e *Executor) setCommandVarArgs(req *http.Request, args []string) {
	queryString := req.URL.Query()
	for _, arg := range args {
		queryString.Add("args", arg)
	}
	req.URL.RawQuery = queryString.Encode()
}

func (e *Executor) setRequestLocale(req *http.Request) error {
	language, err := locale.Detect()
	if err != nil {
		return fmt.Errorf("could not detect client locale: %w", err)
	}
	baseLang, _ := language.Base()
	req.Header.Add("Accept-Language", baseLang.String())
	return nil
}
0707010000001E000081A400000000000000000000000162D515C00000111C000000000000000000000000000000000000002F00000000scm-manager-cli-1.0.1/pkg/command/exec_test.gopackage command

import (
	"bytes"
	"fmt"
	"github.com/scm-manager/cli/pkg"
	"github.com/stretchr/testify/assert"
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestExecutor_Execute(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		_, err := fmt.Fprintf(w, "[{\"out\":\"Hello World\"}]")
		assert.NoError(t, err)
	}))
	defer server.Close()
	var stdout bytes.Buffer
	configuration := &pkg.Configuration{ServerUrl: server.URL, Username: "scmadmin", ApiKey: "secret"}

	executor := CreateExecutor(&stdout, nil, nil, configuration)
	exitCode, err := executor.Execute("some", "command")

	assert.NoError(t, err)
	assert.Equal(t, 0, exitCode)
	assert.Equal(t, "Hello World", stdout.String())
}

func TestExecutor_ExecuteCheckForArgs(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		err := r.ParseForm()
		assert.NoError(t, err)
		assert.Equal(t, []string{"some", "command"}, r.Form["args"])
		_, err = fmt.Fprintf(w, "[{\"out\":\"Hello World\"}]")
		assert.NoError(t, err)
	}))
	defer server.Close()
	var stdout bytes.Buffer
	configuration := &pkg.Configuration{ServerUrl: server.URL, Username: "scmadmin", ApiKey: "secret"}

	executor := CreateExecutor(&stdout, nil, nil, configuration)
	_, err := executor.Execute("some", "command")

	assert.NoError(t, err)
}

func TestExecutor_ExecuteCheckWithApiKey(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		assert.Equal(t, "Bearer secret", r.Header.Get("Authorization"))
		_, err := fmt.Fprintf(w, "[{\"out\":\"Hello World\"}]")
		assert.NoError(t, err)
	}))
	defer server.Close()
	var stdout bytes.Buffer
	configuration := &pkg.Configuration{ServerUrl: server.URL, Username: "scmadmin", ApiKey: "secret"}

	executor := CreateExecutor(&stdout, nil, nil, configuration)
	_, err := executor.Execute("some", "command")

	assert.NoError(t, err)
}

func TestExecutor_ExecuteCheckStderr(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		_, err := fmt.Fprintf(w, "[{\"err\":\"Missing entity\"}]")
		assert.NoError(t, err)
	}))
	defer server.Close()
	var stderr bytes.Buffer
	configuration := &pkg.Configuration{ServerUrl: server.URL, Username: "scmadmin", ApiKey: "secret"}

	executor := CreateExecutor(nil, &stderr, nil, configuration)
	_, err := executor.Execute("some", "command")

	assert.NoError(t, err)
	assert.Equal(t, "Missing entity", stderr.String())
}

func TestExecutor_ExecuteCheckExitCode(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		_, err := fmt.Fprintf(w, "[{\"exit\":42}]")
		assert.NoError(t, err)
	}))
	defer server.Close()
	configuration := &pkg.Configuration{ServerUrl: server.URL, Username: "scmadmin", ApiKey: "secret"}

	executor := CreateExecutor(nil, nil, nil, configuration)
	exitCode, err := executor.Execute("some", "command")

	assert.NoError(t, err)
	assert.Equal(t, 42, exitCode)
}

func TestExecutor_ExecuteCheckLocale(t *testing.T) {
	t.Setenv("LANGUAGE", "es_MX")
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		assert.Equal(t, "es", r.Header.Get("Accept-Language"))
		_, err := fmt.Fprintf(w, "[{\"exit\":0}]")
		assert.NoError(t, err)
	}))
	defer server.Close()
	configuration := &pkg.Configuration{ServerUrl: server.URL, Username: "scmadmin", ApiKey: "secret"}

	executor := CreateExecutor(nil, nil, nil, configuration)
	_, err := executor.Execute("some", "command")

	assert.NoError(t, err)
}

func TestExecutor_ExecuteCheckHttpError(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, "Not found", http.StatusNotFound)
	}))
	defer server.Close()
	configuration := &pkg.Configuration{ServerUrl: server.URL, Username: "scmadmin", ApiKey: "secret"}

	executor := CreateExecutor(nil, nil, nil, configuration)
	_, err := executor.Execute("some", "command")

	assert.ErrorContains(t, err, "HTTP Error 404")
}

func TestCreateDefaultExecutor(t *testing.T) {
	configuration := &pkg.Configuration{ServerUrl: "myServer", Username: "scmadmin", ApiKey: "secret"}

	executor, err := CreateDefaultExecutor(configuration)

	assert.NoError(t, err)
	assert.NotNil(t, executor)
}
0707010000001F000081A400000000000000000000000162D515C00000006C000000000000000000000000000000000000002400000000scm-manager-cli-1.0.1/pkg/config.gopackage pkg

type Configuration struct {
	ServerUrl string
	Username  string
	ApiKey    string `json:"-"`
}
07070100000020000081A400000000000000000000000162D515C0000004E3000000000000000000000000000000000000002200000000scm-manager-cli-1.0.1/pkg/http.gopackage pkg

import (
	"fmt"
	"net/http"
	"runtime"
)

// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent
// name/version (os arch; commithash; buildtime)

const cliName = "scm-cli"

var (
	version    string = "x.y.z"
	commitHash string
	buildTime  string
)

func createDevUserAgent(version, osName, arch string) string {
	return fmt.Sprintf("%s/%s (%s %s)", cliName, version, osName, arch)
}

func createProdUserAgent(version, osName, arch, gitHash, buildTime string) string {
	return fmt.Sprintf("%s/%s (%s %s; %s; %s)", cliName, version, osName, arch, gitHash, buildTime)
}

func createUserAgent(version, osName, arch, gitHash, buildTime string) string {
	if gitHash != "" && buildTime != "" {
		return createProdUserAgent(version, osName, arch, gitHash, buildTime)
	}
	return createDevUserAgent(version, osName, arch)
}

func CreateHttpClient() *http.Client {
	client := &http.Client{}
	client.Transport = &userAgentTransport{}
	return client
}

type userAgentTransport struct {
}

func (t *userAgentTransport) RoundTrip(r *http.Request) (*http.Response, error) {
	ua := createUserAgent(version, runtime.GOOS, runtime.GOARCH, commitHash, buildTime)
	r.Header.Set("User-Agent", ua)
	return http.DefaultTransport.RoundTrip(r)
}
07070100000021000081A400000000000000000000000162D515C000000352000000000000000000000000000000000000002700000000scm-manager-cli-1.0.1/pkg/http_test.gopackage pkg

import (
	"github.com/stretchr/testify/assert"
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestCreateUserAgent(t *testing.T) {
	userAgent := createUserAgent("1.0.0", "linux", "arm64", "bb4d50d", "2022-04-04T09:41:03Z")
	assert.Equal(t, "scm-cli/1.0.0 (linux arm64; bb4d50d; 2022-04-04T09:41:03Z)", userAgent)
}

func TestCreateUserAgent_WithoutGitHashAndBuildTime(t *testing.T) {
	userAgent := createUserAgent("x.y.z", "darwin", "arm64", "", "")
	assert.Equal(t, "scm-cli/x.y.z (darwin arm64)", userAgent)
}

func TestCreateHttpClient(t *testing.T) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		assert.Contains(t, r.Header.Get("User-Agent"), "scm-cli/x.y.z")
	}))
	defer server.Close()

	client := CreateHttpClient()
	_, err := client.Get(server.URL)
	assert.NoError(t, err)
}
07070100000022000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000002000000000scm-manager-cli-1.0.1/pkg/store07070100000023000081A400000000000000000000000162D515C000000D61000000000000000000000000000000000000002900000000scm-manager-cli-1.0.1/pkg/store/store.gopackage store

import (
	"encoding/json"
	"fmt"
	"github.com/scm-manager/cli/pkg"
	"github.com/zalando/go-keyring"
	"io/ioutil"
	"os"
	"path"
)

const keyName = "scm-cli"

func readFromFilePath(filePath string) (*pkg.Configuration, error) {
	_, err := os.Stat(filePath)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		} else {
			return nil, fmt.Errorf("could not find config file: %w", err)
		}
	}
	data, err := ioutil.ReadFile(filePath)
	if err != nil {
		return nil, fmt.Errorf("could not read config file: %w", err)
	}
	configuration := &pkg.Configuration{}
	err = json.Unmarshal(data, configuration)
	if err != nil {
		return nil, fmt.Errorf("could not parse config file: %w", err)

	}
	key, err := readApiKey(keyName, configuration.Username)
	if err != nil {
		return nil, err
	}
	configuration.ApiKey = key
	return configuration, err
}

func Read() (*pkg.Configuration, error) {
	configFilePath, err := resolveConfigFilePath()
	if err != nil {
		return nil, err
	}
	return readFromFilePath(configFilePath)
}

func writeToFilePath(filePath string, configuration *pkg.Configuration) error {
	file, err := os.Create(filePath)
	if err != nil {
		return fmt.Errorf("could not create cli config file: %w", err)
	}

	defer func(file *os.File) {
		_ = file.Close()
	}(file)

	jsonConfig, err := json.Marshal(configuration)
	if err != nil {
		return fmt.Errorf("could not marshal config json: %w", err)
	}
	_, err = file.Write(jsonConfig)
	if err != nil {
		return fmt.Errorf("could not write config to file: %w", err)

	}
	err = storeApiKey(keyName, configuration.Username, configuration.ApiKey)
	if err != nil {
		return fmt.Errorf("could not store api key to keyring: %w", err)
	}
	return nil
}

func Write(configuration *pkg.Configuration) error {
	configFilePath, err := resolveConfigFilePath()
	if err != nil {
		return err
	}
	return writeToFilePath(configFilePath, configuration)
}

func removeFilePath(filePath string) error {
	config, err := readFromFilePath(filePath)
	if err != nil {
		return err
	}
	err = os.Remove(filePath)
	if err != nil {
		return fmt.Errorf("could not remove config file: %w", err)
	}
	err = removeApiKey(keyName, config.Username)
	if err != nil {
		return fmt.Errorf("could not remove api key from keystore: %w", err)
	}
	return nil
}

func Remove() error {
	configFilePath, err := resolveConfigFilePath()
	if err != nil {
		return err
	}
	return removeFilePath(configFilePath)
}

func storeApiKey(apiKeyName string, username string, apiKey string) error {
	err := keyring.Set(apiKeyName, username, apiKey)
	if err != nil {
		return fmt.Errorf("could not store apikey to keyring: %w", err)
	}
	return nil
}

func readApiKey(apiKeyName string, username string) (string, error) {
	apiKey, err := keyring.Get(apiKeyName, username)
	if err != nil {
		return apiKey, fmt.Errorf("could not read apikey from keyring: %w", err)
	}
	return apiKey, nil
}

func removeApiKey(apiKeyName string, username string) error {
	// Remove stored api key
	err := keyring.Delete(apiKeyName, username)
	if err != nil {
		if err != nil {
			return fmt.Errorf("could not remove stored api key: %w", err)
		}
	}
	return nil
}

func resolveConfigFilePath() (string, error) {
	// Read config (server url, username) => .scm-cli.json
	homeDir, err := os.UserHomeDir()
	if err != nil {
		return "", fmt.Errorf("could not find home directory: %w", err)
	}
	return path.Join(homeDir, ".scm-cli.json"), nil
}
07070100000024000081A400000000000000000000000162D515C0000007CB000000000000000000000000000000000000002E00000000scm-manager-cli-1.0.1/pkg/store/store_test.gopackage store

import (
	"github.com/scm-manager/cli/pkg"
	"github.com/stretchr/testify/assert"
	"github.com/zalando/go-keyring"
	"os"
	"path"
	"testing"
)

func init() {
	keyring.MockInit()
}

func TestRead(t *testing.T) {
	err := keyring.Set("scm-cli", "trillian", "secret")

	config, err := readFromFilePath(path.Join("testdata", "cli-config.json"))

	assert.NoError(t, err)
	assert.Equal(t, "localhost", config.ServerUrl)
	assert.Equal(t, "trillian", config.Username)
	assert.Equal(t, "secret", config.ApiKey)
}

func TestStore(t *testing.T) {
	filePath := path.Join(t.TempDir(), "testpath")
	err := writeToFilePath(filePath, &pkg.Configuration{ServerUrl: "server", Username: "user"})
	assert.NoError(t, err)

	config, err := readFromFilePath(filePath)
	assert.Equal(t, "server", config.ServerUrl)
	assert.Equal(t, "user", config.Username)
}

func TestRemoveIfConfigNotExist(t *testing.T) {
	filePath := path.Join(t.TempDir(), "testpath")

	err := removeFilePath(filePath)
	assert.Error(t, err)

	_, err = os.Stat(filePath)
	assert.True(t, os.IsNotExist(err))
}

func TestRemove(t *testing.T) {
	filePath := path.Join(t.TempDir(), "testpath")

	err := writeToFilePath(filePath, &pkg.Configuration{ServerUrl: "server", Username: "user"})
	assert.NoError(t, err)

	err = removeFilePath(filePath)
	assert.NoError(t, err)

	_, err = os.Stat(filePath)
	assert.True(t, os.IsNotExist(err))
}

func TestStoreApiKey(t *testing.T) {
	keyname := "scm-cli"
	username := "scmadmin"
	apiKey := "secret_key"
	err := storeApiKey(keyname, username, apiKey)

	assert.NoError(t, err)

	storedKey, err := readApiKey(keyname, username)
	assert.NoError(t, err)

	assert.Equal(t, apiKey, storedKey)
}

func TestRemoveApiKey(t *testing.T) {
	keyname := "scm-cli"
	username := "scmadmin"
	apiKey := "secret_key"
	err := keyring.Set(keyname, username, apiKey)
	assert.NoError(t, err)

	err = removeApiKey(keyname, username)
	assert.NoError(t, err)

	key, err := keyring.Get(keyname, username)
	assert.Empty(t, key)
}
07070100000025000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000002900000000scm-manager-cli-1.0.1/pkg/store/testdata07070100000026000081A400000000000000000000000162D515C000000037000000000000000000000000000000000000003900000000scm-manager-cli-1.0.1/pkg/store/testdata/cli-config.json{
	"ServerUrl": "localhost",
	"Username": "trillian"
}
07070100000027000041ED00000000000000000000000262D515C000000000000000000000000000000000000000000000002300000000scm-manager-cli-1.0.1/pkg/terminal07070100000028000081A400000000000000000000000162D515C000000219000000000000000000000000000000000000003200000000scm-manager-cli-1.0.1/pkg/terminal/credentials.gopackage terminal

import (
	"bufio"
	"fmt"
	"golang.org/x/term"
	"os"
	"strings"
)

func ReadCredentials() (string, string, error) {
	r := bufio.NewReader(os.Stdin)
	fmt.Print("Username: ")
	username, err := r.ReadString('\n')
	if err != nil {
		return "", "", fmt.Errorf("could not read username: %w", err)
	}
	fmt.Print("Password: ")
	password, err := term.ReadPassword(int(os.Stdin.Fd()))
	if err != nil {
		return "", "", fmt.Errorf("could not read password: %w", err)
	}
	return strings.TrimSpace(username), string(password), nil
}
07070100000029000081A400000000000000000000000162D515C000000ACE000000000000000000000000000000000000001D00000000scm-manager-cli-1.0.1/scm.gopackage main

import (
	"fmt"
	"github.com/scm-manager/cli/pkg"
	"github.com/scm-manager/cli/pkg/api"
	"github.com/scm-manager/cli/pkg/command"
	"github.com/scm-manager/cli/pkg/store"
	"github.com/scm-manager/cli/pkg/terminal"
	"log"
	"os"
	"strings"
)

func main() {
	configuration := readConfig()
	if configuration == nil {
		if len(os.Args) > 2 && os.Args[1] == "login" {
			login()
			return
		} else {
			fmt.Println("Please login first calling \"scm login 'https://{server-url:port}/scm'\"")
			os.Exit(1)
		}
	}

	if len(os.Args) > 1 && os.Args[1] == "logout" {
		logout(configuration)
	} else {
		executeCommand(configuration)
	}
}

func createApiKeyName() string {
	hostname, err := os.Hostname()
	if err != nil {
		return "scm-cli"
	}
	return "scm-cli-" + hostname
}

func readConfig() *pkg.Configuration {
	configuration, err := store.Read()
	if err != nil {
		log.Fatalf("Could not read configuration: %v", err)
	}
	return configuration
}

func login() {
	// Collect login parameters
	serverUrl := os.Args[2]
	if strings.HasSuffix(serverUrl, "/") {
		serverUrl = serverUrl[0 : len(serverUrl)-1]
	}

	username, password, err := terminal.ReadCredentials()
	// line break after Password:
	fmt.Println()
	if err != nil {
		printLoginError("Could not read credentials: %v", err)
	}

	// Create api key
	apiKey, err := api.Create(serverUrl, username, password, createApiKeyName())
	if err != nil {
		printLoginError("Could not create api key: %v\nMost likely there is already an api key for the CLI client issued for this user/system. Please delete this api key manually on your scm server and retry to log in via the CLI.", err)
	}
	// Write Config
	err = store.Write(&pkg.Configuration{ServerUrl: serverUrl, Username: username, ApiKey: apiKey})
	if err != nil {
		printLoginError("Could not write config to store: %v", err)
	}
	fmt.Println("Login successful")
}

func printLoginError(format string, err error) {
	fmt.Println()
	log.Fatalf(format, err)
}

func logout(configuration *pkg.Configuration) {
	err := api.Remove(configuration.ServerUrl, configuration.ApiKey, createApiKeyName())
	if err != nil {
		fmt.Printf("Failed to remove api key from server: %v", err)
		fmt.Println("")
		fmt.Println("We suggest you remove the api key manually on your SCM-Manager server.")
	}
	err = store.Remove()
	if err != nil {
		log.Fatalf("Could not remove local config: %v", err)
	}
	fmt.Println("Successfully logged out")
}

func executeCommand(configuration *pkg.Configuration) {
	executor, err := command.CreateDefaultExecutor(configuration)
	if err != nil {
		log.Fatalf("Failed to create default executor: %v", err)
	}
	exitCode, err := executor.Execute(os.Args[1:]...)
	if err != nil {
		log.Fatalf("Failed to execute command: %v", err)
	}
	os.Exit(exitCode)
}
07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!111 blocks
openSUSE Build Service is sponsored by