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