-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
119 changed files
with
26,442 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
#!/bin/sh | ||
set -e | ||
|
||
# debugging if anything fails is tricky as dh-golang eats up all output | ||
# uncomment the lines below to get a useful trace if you have to touch | ||
# this again (my advice is: DON'T) | ||
#set -x | ||
#logfile=/tmp/mkversions.log | ||
#exec >> $logfile 2>&1 | ||
#echo "env: $(set)" | ||
#echo "mkversion.sh run from: $0" | ||
#echo "pwd: $(pwd)" | ||
|
||
# we have two directories we need to care about: | ||
# - our toplevel pkg builddir which is where "mkversion.sh" is located | ||
# and where "snap-confine" expects its cmd/VERSION file | ||
# - the GO_GENERATE_BUILDDIR which may be the toplevel pkg dir. but | ||
# during "dpkg-buildpackage" it will become a different _build/ dir | ||
# that dh-golang creates and that only contains a subset of the | ||
# files of the toplevel buildir. | ||
PKG_BUILDDIR=$(dirname "$0")/.. | ||
GO_GENERATE_BUILDDIR="$(pwd)" | ||
|
||
# run from "go generate" adjust path | ||
if [ "$GOPACKAGE" = "cmd" ]; then | ||
GO_GENERATE_BUILDDIR="$(pwd)/.." | ||
fi | ||
|
||
OUTPUT_ONLY=false | ||
if [ "$1" = "--output-only" ]; then | ||
OUTPUT_ONLY=true | ||
shift | ||
fi | ||
|
||
# If the version is passed in as an argument to mkversion.sh, let's use that. | ||
if [ -n "$1" ]; then | ||
v="$1" | ||
o=shell | ||
fi | ||
|
||
if [ -z "$v" ]; then | ||
# Let's try to derive the version from git.. | ||
if command -v git >/dev/null; then | ||
# not using "--dirty" here until the following bug is fixed: | ||
# https://bugs.launchpad.net/snapcraft/+bug/1662388 | ||
v="$(git describe --always | sed -e 's/-/+git/;y/-/./' )" | ||
o=git | ||
fi | ||
fi | ||
|
||
if [ -z "$v" ]; then | ||
# at this point we maybe in _build/src/github etc where we have no | ||
# debian/changelog (dh-golang only exports the sources here) | ||
# switch to the real source dir for the changelog parsing | ||
v="$(cd "$PKG_BUILDDIR"; dpkg-parsechangelog --show-field Version)"; | ||
o=debian/changelog | ||
fi | ||
|
||
if [ -z "$v" ]; then | ||
exit 1 | ||
fi | ||
|
||
if [ "$OUTPUT_ONLY" = true ]; then | ||
echo "$v" | ||
exit 0 | ||
fi | ||
|
||
echo "*** Setting version to '$v' from $o." >&2 | ||
|
||
cat <<EOF > "$GO_GENERATE_BUILDDIR/cmd/version_generated.go" | ||
package cmd | ||
// generated by mkversion.sh; do not edit | ||
func init() { | ||
Version = "$v" | ||
} | ||
EOF | ||
|
||
cat <<EOF > "$PKG_BUILDDIR/cmd/VERSION" | ||
$v | ||
EOF | ||
|
||
#cat <<EOF > "$PKG_BUILDDIR/data/info" | ||
#VERSION=$v | ||
#EOF |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Copyright (c) 2014-2020 Canonical Ltd | ||
// | ||
// This program is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License version 3 as | ||
// published by the Free Software Foundation. | ||
// | ||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
|
||
package main | ||
|
||
type cmdDebug struct{} | ||
|
||
var shortDebugHelp = "Run debug commands" | ||
var longDebugHelp = ` | ||
The debug command contains a selection of additional sub-commands. | ||
Debug commands can be removed without notice and may not work on | ||
non-development systems. | ||
` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,255 @@ | ||
// Copyright (c) 2014-2020 Canonical Ltd | ||
// | ||
// This program is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License version 3 as | ||
// published by the Free Software Foundation. | ||
// | ||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
package main | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"io" | ||
"regexp" | ||
"strings" | ||
"unicode/utf8" | ||
|
||
"github.com/jessevdk/go-flags" | ||
) | ||
|
||
var shortHelpHelp = "Show help about a command" | ||
var longHelpHelp = ` | ||
The help command displays information about commands. | ||
` | ||
|
||
// addHelp adds --help like what go-flags would do for us, but hidden | ||
func addHelp(parser *flags.Parser) error { | ||
var help struct { | ||
ShowHelp func() error `short:"h" long:"help"` | ||
} | ||
help.ShowHelp = func() error { | ||
// this function is called via --help (or -h). In that | ||
// case, parser.Command.Active should be the command | ||
// on which help is being requested (like "pebble foo | ||
// --help", active is foo), or nil in the toplevel. | ||
if parser.Command.Active == nil { | ||
// this means *either* a bare 'pebble --help', | ||
// *or* 'pebble --help command' | ||
// | ||
// If we return nil in the first case go-flags | ||
// will throw up an ErrCommandRequired on its | ||
// own, but in the second case it'll go on to | ||
// run the command, which is very unexpected. | ||
// | ||
// So we force the ErrCommandRequired here. | ||
|
||
// toplevel --help gets handled via ErrCommandRequired | ||
return &flags.Error{Type: flags.ErrCommandRequired} | ||
} | ||
// not toplevel, so ask for regular help | ||
return &flags.Error{Type: flags.ErrHelp} | ||
} | ||
hlpgrp, err := parser.AddGroup("Help Options", "", &help) | ||
if err != nil { | ||
return err | ||
} | ||
hlpgrp.Hidden = true | ||
hlp := parser.FindOptionByLongName("help") | ||
hlp.Description = "Show this help message" | ||
hlp.Hidden = true | ||
|
||
return nil | ||
} | ||
|
||
type cmdHelp struct { | ||
All bool `long:"all"` | ||
Manpage bool `long:"man" hidden:"true"` | ||
Positional struct { | ||
Subs []string `positional-arg-name:"<command>"` | ||
} `positional-args:"yes"` | ||
parser *flags.Parser | ||
} | ||
|
||
func init() { | ||
addCommand("help", shortHelpHelp, longHelpHelp, func() flags.Commander { return &cmdHelp{} }, | ||
map[string]string{ | ||
"all": "Show a short summary of all commands", | ||
"man": "Generate the manpage", | ||
}, nil) | ||
} | ||
|
||
func (cmd *cmdHelp) setParser(parser *flags.Parser) { | ||
cmd.parser = parser | ||
} | ||
|
||
// manfixer is a hackish way to fix drawbacks in the generated manpage: | ||
// - no way to get it into section 8 | ||
// - duplicated TP lines that break older groff (e.g. 14.04), lp:1814767 | ||
type manfixer struct { | ||
bytes.Buffer | ||
done bool | ||
} | ||
|
||
func (w *manfixer) Write(buf []byte) (int, error) { | ||
if !w.done { | ||
w.done = true | ||
if bytes.HasPrefix(buf, []byte(".TH pebble 1 ")) { | ||
// io.Writer.Write must not modify the buffer, even temporarily | ||
n, _ := w.Buffer.Write(buf[:9]) | ||
w.Buffer.Write([]byte{'8'}) | ||
m, err := w.Buffer.Write(buf[10:]) | ||
return n + m + 1, err | ||
} | ||
} | ||
return w.Buffer.Write(buf) | ||
} | ||
|
||
var tpRegexp = regexp.MustCompile(`(?m)(?:^\.TP\n)+`) | ||
|
||
func (w *manfixer) flush() { | ||
str := tpRegexp.ReplaceAllLiteralString(w.Buffer.String(), ".TP\n") | ||
io.Copy(Stdout, strings.NewReader(str)) | ||
} | ||
|
||
func (cmd cmdHelp) Execute(args []string) error { | ||
if len(args) > 0 { | ||
return ErrExtraArgs | ||
} | ||
if cmd.Manpage { | ||
// you shouldn't try to to combine --man with --all nor a | ||
// subcommand, but --man is hidden so no real need to check. | ||
out := &manfixer{} | ||
cmd.parser.WriteManPage(out) | ||
out.flush() | ||
return nil | ||
} | ||
if cmd.All { | ||
if len(cmd.Positional.Subs) > 0 { | ||
return fmt.Errorf("help accepts a command, or '--all', but not both.") | ||
} | ||
printLongHelp(cmd.parser) | ||
return nil | ||
} | ||
|
||
var subcmd = cmd.parser.Command | ||
for _, subname := range cmd.Positional.Subs { | ||
subcmd = subcmd.Find(subname) | ||
if subcmd == nil { | ||
sug := "pebble help" | ||
if x := cmd.parser.Command.Active; x != nil && x.Name != "help" { | ||
sug = "pebble help " + x.Name | ||
} | ||
return fmt.Errorf("unknown command %q, see '%s'.", subname, sug) | ||
} | ||
// this makes "pebble help foo" work the same as "pebble foo --help" | ||
cmd.parser.Command.Active = subcmd | ||
} | ||
if subcmd != cmd.parser.Command { | ||
return &flags.Error{Type: flags.ErrHelp} | ||
} | ||
return &flags.Error{Type: flags.ErrCommandRequired} | ||
} | ||
|
||
type helpCategory struct { | ||
Label string | ||
Description string | ||
Commands []string | ||
} | ||
|
||
// helpCategories helps us by grouping commands | ||
var helpCategories = []helpCategory{{ | ||
Label: "Basics", | ||
Description: "basic management", | ||
Commands: []string{"foo", "bar", "baz"}, | ||
}, { | ||
Label: "...more", | ||
Description: "slightly more advanced management", | ||
Commands: []string{"more-foo", "more-bar", "more-baz"}, | ||
}} | ||
|
||
var ( | ||
longPebbleDescription = strings.TrimSpace(` | ||
Pebble lets you control services and perform managemnet actions on | ||
the system that is running them. | ||
`) | ||
pebbleUsage = "Usage: pebble <command> [<options>...]" | ||
pebbleHelpCategoriesIntro = "Commands can be classified as follows:" | ||
pebbleHelpAllFooter = "For more information about a command, run 'pebble help <command>'." | ||
pebbleHelpFooter = "For a short summary of all commands, run 'pebble help --all'." | ||
) | ||
|
||
func printHelpHeader() { | ||
fmt.Fprintln(Stdout, longPebbleDescription) | ||
fmt.Fprintln(Stdout) | ||
fmt.Fprintln(Stdout, pebbleUsage) | ||
fmt.Fprintln(Stdout) | ||
fmt.Fprintln(Stdout, pebbleHelpCategoriesIntro) | ||
fmt.Fprintln(Stdout) | ||
} | ||
|
||
func printHelpAllFooter() { | ||
fmt.Fprintln(Stdout) | ||
fmt.Fprintln(Stdout, pebbleHelpAllFooter) | ||
} | ||
|
||
func printHelpFooter() { | ||
printHelpAllFooter() | ||
fmt.Fprintln(Stdout, pebbleHelpFooter) | ||
} | ||
|
||
// this is called when the Execute returns a flags.Error with ErrCommandRequired | ||
func printShortHelp() { | ||
printHelpHeader() | ||
maxLen := 0 | ||
for _, categ := range helpCategories { | ||
if l := utf8.RuneCountInString(categ.Label); l > maxLen { | ||
maxLen = l | ||
} | ||
} | ||
for _, categ := range helpCategories { | ||
fmt.Fprintf(Stdout, "%*s: %s\n", maxLen+2, categ.Label, strings.Join(categ.Commands, ", ")) | ||
} | ||
printHelpFooter() | ||
} | ||
|
||
// this is "pebble help --all" | ||
func printLongHelp(parser *flags.Parser) { | ||
printHelpHeader() | ||
maxLen := 0 | ||
for _, categ := range helpCategories { | ||
for _, command := range categ.Commands { | ||
if l := len(command); l > maxLen { | ||
maxLen = l | ||
} | ||
} | ||
} | ||
|
||
// flags doesn't have a LookupCommand? | ||
commands := parser.Commands() | ||
cmdLookup := make(map[string]*flags.Command, len(commands)) | ||
for _, cmd := range commands { | ||
cmdLookup[cmd.Name] = cmd | ||
} | ||
|
||
for _, categ := range helpCategories { | ||
fmt.Fprintln(Stdout) | ||
fmt.Fprintf(Stdout, " %s (%s):\n", categ.Label, categ.Description) | ||
for _, name := range categ.Commands { | ||
cmd := cmdLookup[name] | ||
if cmd == nil { | ||
fmt.Fprintf(Stderr, "??? Cannot find command %q mentioned in help categories, please report!\n", name) | ||
} else { | ||
fmt.Fprintf(Stdout, " %*s %s\n", -maxLen, name, cmd.ShortDescription) | ||
} | ||
} | ||
} | ||
printHelpAllFooter() | ||
} |
Oops, something went wrong.