mirror of
https://github.com/syncthing/syncthing.git
synced 2026-05-07 22:55:24 -04:00
`syncthing cli` subcommand was using urfave/cli as the command parser. This PR replace it with kong, which the main command uses. Some help texts and error message format are changed. Other than that, all the command usage and logic remains unchanged. There's only one place which still uses urfave/cli, which is `syncthing cli config`, because it uses some magic to dynamically build commands from struct reflects. I used kong's `passthrough:""` tag to pass any argument following `syncthing cli config` to urfave/cli parser. This PR also fixes #9041 --------- Co-authored-by: Jakob Borg <jakob@kastelo.net>
152 lines
3.2 KiB
Go
152 lines
3.2 KiB
Go
// Copyright (C) 2019 The Syncthing Authors.
|
|
//
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
|
|
package cli
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"mime"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/syncthing/syncthing/lib/config"
|
|
"github.com/syncthing/syncthing/lib/db/backend"
|
|
"github.com/syncthing/syncthing/lib/locations"
|
|
)
|
|
|
|
func responseToBArray(response *http.Response) ([]byte, error) {
|
|
bytes, err := io.ReadAll(response.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return bytes, response.Body.Close()
|
|
}
|
|
|
|
func emptyPost(url string, apiClientFactory *apiClientFactory) error {
|
|
client, err := apiClientFactory.getClient()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = client.Post(url, "")
|
|
return err
|
|
}
|
|
|
|
func indexDumpOutputWrapper(apiClientFactory *apiClientFactory) func(url string) error {
|
|
return func(url string) error {
|
|
return indexDumpOutput(url, apiClientFactory)
|
|
}
|
|
}
|
|
|
|
func indexDumpOutput(url string, apiClientFactory *apiClientFactory) error {
|
|
client, err := apiClientFactory.getClient()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
response, err := client.Get(url)
|
|
if errors.Is(err, errNotFound) {
|
|
return errors.New("not found (folder/file not in database)")
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return prettyPrintResponse(response)
|
|
}
|
|
|
|
func saveToFile(url string, apiClientFactory *apiClientFactory) error {
|
|
client, err := apiClientFactory.getClient()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
response, err := client.Get(url)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, params, err := mime.ParseMediaType(response.Header.Get("Content-Disposition"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
filename := params["filename"]
|
|
if filename == "" {
|
|
return errors.New("Missing filename in response")
|
|
}
|
|
bs, err := responseToBArray(response)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
f, err := os.Create(filename)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = f.Write(bs)
|
|
if err != nil {
|
|
_ = f.Close()
|
|
return err
|
|
}
|
|
err = f.Close()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fmt.Println("Wrote results to", filename)
|
|
return nil
|
|
}
|
|
|
|
func getConfig(c APIClient) (config.Configuration, error) {
|
|
cfg := config.Configuration{}
|
|
response, err := c.Get("system/config")
|
|
if err != nil {
|
|
return cfg, err
|
|
}
|
|
bytes, err := responseToBArray(response)
|
|
if err != nil {
|
|
return cfg, err
|
|
}
|
|
err = json.Unmarshal(bytes, &cfg)
|
|
if err != nil {
|
|
return config.Configuration{}, err
|
|
}
|
|
return cfg, nil
|
|
}
|
|
|
|
func prettyPrintJSON(data interface{}) error {
|
|
enc := json.NewEncoder(os.Stdout)
|
|
enc.SetIndent("", " ")
|
|
return enc.Encode(data)
|
|
}
|
|
|
|
func prettyPrintResponse(response *http.Response) error {
|
|
bytes, err := responseToBArray(response)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var data interface{}
|
|
if err := json.Unmarshal(bytes, &data); err != nil {
|
|
return err
|
|
}
|
|
// TODO: Check flag for pretty print format
|
|
return prettyPrintJSON(data)
|
|
}
|
|
|
|
func getDB() (backend.Backend, error) {
|
|
return backend.OpenLevelDBRO(locations.Get(locations.Database))
|
|
}
|
|
|
|
func nulString(bs []byte) string {
|
|
for i := range bs {
|
|
if bs[i] == 0 {
|
|
return string(bs[:i])
|
|
}
|
|
}
|
|
return string(bs)
|
|
}
|
|
|
|
func normalizePath(path string) string {
|
|
return filepath.ToSlash(filepath.Clean(path))
|
|
}
|