Răsfoiți Sursa

Update "pault.ag/go/debian" vendoring

Tianon Gravi 8 ani în urmă
părinte
comite
1087b55cf9

+ 2 - 2
bashbrew/go/vendor/manifest

@@ -28,7 +28,7 @@
 		{
 			"importpath": "pault.ag/go/debian",
 			"repository": "https://github.com/paultag/go-debian",
-			"revision": "e7a23c7df0f545cdb75afbcc6d296bb93ce2786f",
+			"revision": "b655795f4ac31a20d5455c331fe5c1cf3c779bf3",
 			"branch": "master"
 		},
 		{
@@ -38,4 +38,4 @@
 			"branch": "master"
 		}
 	]
-}
+}

+ 3 - 0
bashbrew/go/vendor/src/pault.ag/go/debian/AUTHORS

@@ -0,0 +1,3 @@
+Paul Tagliamonte <[email protected]>
+Tianon Gravi <[email protected]>
+Michael Stapelberg <[email protected]>

+ 53 - 0
bashbrew/go/vendor/src/pault.ag/go/debian/LICENSE

@@ -0,0 +1,53 @@
+Copyright (c) Paul R. Tagliamonte <[email protected]>, 2015-2016
+
+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.
+
+
+
+Version module
+==============
+
+Copyright © 2012 Michael Stapelberg and contributors
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+    * Neither the name of Michael Stapelberg nor the
+      names of contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY Michael Stapelberg ''AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL Michael Stapelberg BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 8 - 0
bashbrew/go/vendor/src/pault.ag/go/debian/README.md

@@ -0,0 +1,8 @@
+go-debian
+=========
+
+`go-debian` is a Debian Toolbelt for Go hackers! This package contains a bunch
+of helpful routines to help work with fun bits of Debian data.
+
+
+[![GoDoc](https://godoc.org/pault.ag/go/debian?status.svg)](https://godoc.org/pault.ag/go/debian)

+ 177 - 0
bashbrew/go/vendor/src/pault.ag/go/debian/changelog/changelog.go

@@ -0,0 +1,177 @@
+/* {{{ Copyright (c) Paul R. Tagliamonte <[email protected]>, 2015
+ *
+ * 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. }}} */
+
+package changelog
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+	"os"
+	"strings"
+	"time"
+
+	"pault.ag/go/debian/version"
+)
+
+// A ChangelogEntry is the encapsulation for each entry for a given version
+// in a series of uploads.
+type ChangelogEntry struct {
+	Source    string
+	Version   version.Version
+	Target    string
+	Arguments map[string]string
+	Changelog string
+	ChangedBy string
+	When      time.Time
+}
+
+const whenLayout = time.RFC1123Z // "Mon, 02 Jan 2006 15:04:05 -0700"
+
+type ChangelogEntries []ChangelogEntry
+
+func trim(line string) string {
+	return strings.Trim(line, "\n\r\t ")
+}
+
+func partition(line, delim string) (string, string) {
+	entries := strings.SplitN(line, delim, 2)
+	if len(entries) != 2 {
+		return line, ""
+	}
+	return entries[0], entries[1]
+
+}
+
+func ParseOne(reader *bufio.Reader) (*ChangelogEntry, error) {
+	changeLog := ChangelogEntry{}
+
+	var header string
+	for {
+		line, err := reader.ReadString('\n')
+		if err != nil {
+			return nil, err
+		}
+		if line == "\n" {
+			continue
+		}
+		if !strings.HasPrefix(line, " ") {
+			/* Great. Let's work with this. */
+			header = line
+			break
+		} else {
+			return nil, fmt.Errorf("Unexpected line: %s", line)
+		}
+	}
+
+	/* OK, so, we have a header. Let's run with it
+	 * hello (2.10-1) unstable; urgency=low */
+
+	arguments, options := partition(header, ";")
+	/* Arguments: hello (2.10-1) unstable
+	 * Options:   urgency=low, other=bar */
+
+	source, remainder := partition(arguments, "(")
+	versionString, suite := partition(remainder, ")")
+
+	var err error
+
+	changeLog.Source = trim(source)
+	changeLog.Version, err = version.Parse(trim(versionString))
+	if err != nil {
+		return nil, err
+	}
+	changeLog.Target = trim(suite)
+
+	changeLog.Arguments = map[string]string{}
+
+	for _, entry := range strings.Split(options, ",") {
+		key, value := partition(trim(entry), "=")
+		changeLog.Arguments[trim(key)] = trim(value)
+	}
+
+	var signoff string
+	/* OK, we've got the header. Let's zip down. */
+	for {
+		line, err := reader.ReadString('\n')
+		if err != nil {
+			return nil, err
+		}
+		if !strings.HasPrefix(line, " ") && trim(line) != "" {
+			return nil, fmt.Errorf("Error! Didn't get ending line!")
+		}
+
+		if strings.HasPrefix(line, " -- ") {
+			signoff = line
+			break
+		}
+
+		changeLog.Changelog = changeLog.Changelog + line
+	}
+
+	/* Right, so we have a signoff line */
+	_, signoff = partition(signoff, "--")  /* Get rid of the leading " -- " */
+	whom, when := partition(signoff, "  ") /* Split on the "  " */
+	changeLog.ChangedBy = trim(whom)
+	changeLog.When, err = time.Parse(whenLayout, trim(when))
+	if err != nil {
+		return nil, fmt.Errorf("Failed parsing When %q: %v", when, err)
+	}
+
+	return &changeLog, nil
+}
+
+func ParseFileOne(path string) (*ChangelogEntry, error) {
+	f, err := os.Open(path)
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+
+	return ParseOne(bufio.NewReader(f))
+}
+
+func Parse(reader io.Reader) (ChangelogEntries, error) {
+	stream := bufio.NewReader(reader)
+	ret := ChangelogEntries{}
+	for {
+		entry, err := ParseOne(stream)
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			return ChangelogEntries{}, err
+		}
+		ret = append(ret, *entry)
+	}
+	return ret, nil
+}
+
+func ParseFile(path string) (ChangelogEntries, error) {
+	f, err := os.Open(path)
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+
+	return Parse(bufio.NewReader(f))
+}
+
+// vim: foldmethod=marker

+ 102 - 0
bashbrew/go/vendor/src/pault.ag/go/debian/changelog/changelog_test.go

@@ -0,0 +1,102 @@
+/* {{{ Copyright (c) Paul R. Tagliamonte <[email protected]>, 2015
+ *
+ * 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. }}} */
+
+package changelog_test
+
+import (
+	"bufio"
+	"io"
+	"log"
+	"strings"
+	"testing"
+
+	"pault.ag/go/debian/changelog"
+)
+
+/*
+ *
+ */
+
+func isok(t *testing.T, err error) {
+	if err != nil && err != io.EOF {
+		log.Printf("Error! Error is not nil! %s\n", err)
+		t.FailNow()
+	}
+}
+
+func notok(t *testing.T, err error) {
+	if err == nil {
+		log.Printf("Error! Error is nil!\n")
+		t.FailNow()
+	}
+}
+
+func assert(t *testing.T, expr bool) {
+	if !expr {
+		log.Printf("Assertion failed!")
+		t.FailNow()
+	}
+}
+
+/*
+ *
+ */
+
+// {{{ test changelog entry
+var changeLog = `hello (2.10-1) unstable; urgency=low
+
+  * New upstream release.
+  * debian/patches: Drop 01-fix-i18n-of-default-message, no longer needed.
+  * debian/patches: Drop 99-config-guess-config-sub, no longer needed.
+  * debian/rules: Drop override_dh_auto_build hack, no longer needed.
+  * Standards-Version: 3.9.6 (no changes for this).
+
+ -- Santiago Vila <[email protected]>  Sun, 22 Mar 2015 11:56:00 +0100
+
+hello (2.9-2) unstable; urgency=low
+
+  * Apply patch from Reuben Thomas to fix i18n of default message.
+    This is upstream commit c4aed00. Closes: #767172.
+  * The previous change in src/hello.c trigger a rebuild of man/hello.1
+    that we don't need. Add a "touch man/hello.1" to avoid it.
+  * Use Breaks: hello-debhelper (<< 2.9), not Conflicts,
+    as hello-debhelper is deprecated.
+  * Restore simple watch file from old hello package that was lost
+    when the packages were renamed.
+  * Update 99-config-guess-config-sub patch.
+
+ -- Santiago Vila <[email protected]>  Thu, 06 Nov 2014 12:03:40 +0100
+`
+
+// }}}
+
+func TestChangelogEntry(t *testing.T) {
+	changeLog, err := changelog.ParseOne(bufio.NewReader(strings.NewReader(changeLog)))
+	isok(t, err)
+	assert(t, changeLog.ChangedBy == "Santiago Vila <[email protected]>")
+}
+
+func TestChangelogEntries(t *testing.T) {
+	changeLogs, err := changelog.Parse(strings.NewReader(changeLog))
+	isok(t, err)
+	assert(t, len(changeLogs) == 2)
+}
+
+// vim: foldmethod=marker

+ 6 - 0
bashbrew/go/vendor/src/pault.ag/go/debian/changelog/doc.go

@@ -0,0 +1,6 @@
+/*
+
+Parse the Debian changelog format.
+
+*/
+package changelog

+ 16 - 0
bashbrew/go/vendor/src/pault.ag/go/debian/control/changes.go

@@ -24,6 +24,7 @@ import (
 	"bufio"
 	"fmt"
 	"os"
+	"path"
 	"path/filepath"
 	"strconv"
 	"strings"
@@ -123,6 +124,21 @@ func ParseChanges(reader *bufio.Reader, path string) (*Changes, error) {
 	return ret, Unmarshal(ret, reader)
 }
 
+// Return a list of FileListChangesFileHash entries from the `changes.Files`
+// entry, with the exception that each `Filename` will be joined to the root
+// directory of the Changes file.
+func (changes *Changes) AbsFiles() []FileListChangesFileHash {
+	ret := []FileListChangesFileHash{}
+
+	baseDir := filepath.Dir(changes.Filename)
+	for _, hash := range changes.Files {
+		hash.Filename = path.Join(baseDir, hash.Filename)
+		ret = append(ret, hash)
+	}
+
+	return ret
+}
+
 // Return a DSC struct for the DSC listed in the .changes file. This requires
 // Changes.Filename to be correctly set, and for the .dsc file to exist
 // in the correct place next to the .changes.

+ 1 - 1
bashbrew/go/vendor/src/pault.ag/go/debian/control/dsc.go

@@ -31,7 +31,7 @@ import (
 	"pault.ag/go/topsort"
 )
 
-// A DSC is the ecapsulation of a Debian .dsc control file. This contains
+// A DSC is the encapsulation of a Debian .dsc control file. This contains
 // information about the source package, and is general handy.
 //
 // The Debian source control file is generated by dpkg-source when it builds

+ 1 - 1
bashbrew/go/vendor/src/pault.ag/go/debian/control/encode.go

@@ -55,7 +55,7 @@ func ConvertToParagraph(incoming interface{}) (*Paragraph, error) {
 	return convertToParagraph(data.Elem())
 }
 
-// Top-level conversaion dispatch {{{
+// Top-level conversion dispatch {{{
 
 func convertToParagraph(data reflect.Value) (*Paragraph, error) {
 	order := []string{}

+ 1 - 1
bashbrew/go/vendor/src/pault.ag/go/debian/control/parse.go

@@ -267,7 +267,7 @@ func (p *ParagraphReader) Next() (*Paragraph, error) {
 func (p *ParagraphReader) decodeClearsig(keyring *openpgp.EntityList) error {
 	// One *massive* downside here is that the OpenPGP module in Go operates
 	// on byte arrays in memory, and *not* on Readers and Writers. This is a
-	// huge PITA because it does't need to be that way, and this forces
+	// huge PITA because it doesn't need to be that way, and this forces
 	// clearsigned documents into memory. Which fucking sucks. But here
 	// we are. It's likely worth a bug or two on this.
 

+ 204 - 0
bashbrew/go/vendor/src/pault.ag/go/debian/deb/ar.go

@@ -0,0 +1,204 @@
+/* {{{ Copyright (c) Paul R. Tagliamonte <[email protected]>, 2015
+ *
+ * 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. }}} */
+
+package deb
+
+import (
+	"fmt"
+	"io"
+	"io/ioutil"
+	"strconv"
+	"strings"
+)
+
+// ArEntry {{{
+
+// Container type to access the different parts of a Debian `ar(1)` Archive.
+//
+// The most interesting parts of this are the `Name` attribute, Data
+// `io.Reader`, and the Tarfile helpers. This will allow the developer to
+// programmatically inspect the information inside without forcing her to
+// unpack the .deb to the filesystem.
+type ArEntry struct {
+	Name      string
+	Timestamp int64
+	OwnerID   int64
+	GroupID   int64
+	FileMode  string
+	Size      int64
+	Data      io.Reader
+}
+
+// }}}
+
+// Ar {{{
+
+// This struct encapsulates a Debian .deb flavored `ar(1)` archive.
+type Ar struct {
+	in         io.Reader
+	lastReader *io.Reader
+	offset     bool
+}
+
+// LoadAr {{{
+
+// Load an Ar archive reader from an io.Reader
+func LoadAr(in io.Reader) (*Ar, error) {
+	if err := checkAr(in); err != nil {
+		return nil, err
+	}
+	debFile := Ar{in: in}
+	return &debFile, nil
+}
+
+// }}}
+
+// Next {{{
+
+// Function to jump to the next file in the Debian `ar(1)` archive, and
+// return the next member.
+func (d *Ar) Next() (*ArEntry, error) {
+	if d.lastReader != nil {
+		/* Before we do much more, let's empty out the reader, since we
+		 * can't be sure of our position in the reader until the LimitReader
+		 * is empty */
+		if _, err := io.Copy(ioutil.Discard, *d.lastReader); err != nil {
+			return nil, err
+		}
+		if d.offset {
+			/* .ar archives align on 2 byte boundaries, so if we're odd, go
+			 * ahead and read another byte. If we get an io.EOF, it's fine
+			 * to return it. */
+			_, err := d.in.Read(make([]byte, 1))
+			if err != nil {
+				return nil, err
+			}
+		}
+	}
+
+	line := make([]byte, 60)
+
+	count, err := d.in.Read(line)
+	if err != nil {
+		return nil, err
+	}
+	if count == 1 && line[0] == '\n' {
+		return nil, io.EOF
+	}
+	if count != 60 {
+		return nil, fmt.Errorf("Caught a short read at the end")
+	}
+	entry, err := parseArEntry(line)
+	if err != nil {
+		return nil, err
+	}
+
+	entry.Data = io.LimitReader(d.in, entry.Size)
+	d.lastReader = &entry.Data
+	d.offset = (entry.Size % 2) == 1
+
+	return entry, nil
+}
+
+// }}}
+
+// toDecimal {{{
+
+// Take a byte array, and return an int64
+func toDecimal(input []byte) (int64, error) {
+	stream := strings.TrimSpace(string(input))
+	out, err := strconv.Atoi(stream)
+	return int64(out), err
+}
+
+// }}}
+
+// }}}
+
+// AR Format Hackery {{{
+
+// parseArEntry {{{
+
+// Take the AR format line, and create an ArEntry (without .Data set)
+// to be returned to the user later.
+//
+// +-------------------------------------------------------
+// | Offset  Length  Name                         Format
+// +-------------------------------------------------------
+// | 0       16      File name                    ASCII
+// | 16      12      File modification timestamp  Decimal
+// | 28      6       Owner ID                     Decimal
+// | 34      6       Group ID                     Decimal
+// | 40      8       File mode                    Octal
+// | 48      10      File size in bytes           Decimal
+// | 58      2       File magic                   0x60 0x0A
+//
+func parseArEntry(line []byte) (*ArEntry, error) {
+	if len(line) != 60 {
+		return nil, fmt.Errorf("Malformed file entry line length")
+	}
+
+	if line[58] != 0x60 && line[59] != 0x0A {
+		return nil, fmt.Errorf("Malformed file entry line endings")
+	}
+
+	entry := ArEntry{
+		Name:     strings.TrimSpace(string(line[0:16])),
+		FileMode: strings.TrimSpace(string(line[48:58])),
+	}
+
+	for target, value := range map[*int64][]byte{
+		&entry.Timestamp: line[16:28],
+		&entry.OwnerID:   line[28:34],
+		&entry.GroupID:   line[34:40],
+		&entry.Size:      line[48:58],
+	} {
+		intValue, err := toDecimal(value)
+		if err != nil {
+			return nil, err
+		}
+		*target = intValue
+	}
+
+	return &entry, nil
+}
+
+// }}}
+
+// checkAr {{{
+
+// Given a brand spank'n new os.File entry, go ahead and make sure it looks
+// like an `ar(1)` archive, and not some random file.
+func checkAr(reader io.Reader) error {
+	header := make([]byte, 8)
+	if _, err := reader.Read(header); err != nil {
+		return err
+	}
+	if string(header) != "!<arch>\n" {
+		return fmt.Errorf("Header doesn't look right!")
+	}
+	return nil
+}
+
+// }}}
+
+// }}}
+
+// vim: foldmethod=marker

+ 242 - 0
bashbrew/go/vendor/src/pault.ag/go/debian/deb/deb.go

@@ -0,0 +1,242 @@
+/* {{{ Copyright (c) Paul R. Tagliamonte <[email protected]>, 2015
+ *
+ * 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. }}} */
+
+package deb
+
+import (
+	"archive/tar"
+	"bufio"
+	"fmt"
+	"io"
+	"os"
+	"path"
+	"strings"
+
+	"pault.ag/go/debian/control"
+	"pault.ag/go/debian/dependency"
+	"pault.ag/go/debian/version"
+)
+
+// Control {{{
+
+// Binary Control format, as exists in the Control section of the `.deb`
+// archive, as defined in Debian Policy, section 5.3, entitled "Binary
+// package control files -- DEBIAN/control".
+type Control struct {
+	control.Paragraph
+
+	Package       string `required:"true"`
+	Source        string
+	Version       version.Version `required:"true"`
+	Architecture  dependency.Arch `required:"true"`
+	Maintainer    string          `required:"true"`
+	InstalledSize int             `control:"Installed-Size"`
+	Depends       dependency.Dependency
+	Recommends    dependency.Dependency
+	Suggests      dependency.Dependency
+	Breaks        dependency.Dependency
+	Replaces      dependency.Dependency
+	BuiltUsing    dependency.Dependency `control:"Built-Using"`
+	Section       string
+	Priority      string
+	Homepage      string
+	Description   string `required:"true"`
+}
+
+func (c Control) SourceName() string {
+	if c.Source == "" {
+		return c.Package
+	}
+	return c.Source
+}
+
+// }}}
+
+// Deb {{{
+
+// Container struct to encapsulate a `.deb` file on disk. This contains
+// information about what exactly we're looking at. When loaded. information
+// regarding the Control file is read from the control section of the .deb,
+// and Unmarshaled into the `Control` member of the Struct.
+type Deb struct {
+	Control Control
+	Path    string
+	Data    *tar.Reader
+}
+
+// Load {{{
+
+// Load {{{
+
+// Given a reader, and the file path to the file (for use in the Deb later)
+// create a deb.Deb object, and populate the Control and Data members.
+func Load(in io.Reader, pathname string) (*Deb, error) {
+	ar, err := LoadAr(in)
+	if err != nil {
+		return nil, err
+	}
+	deb, err := loadDeb(ar)
+	if err != nil {
+		return nil, err
+	}
+	deb.Path = pathname
+	return deb, nil
+}
+
+// }}}
+
+// LoadFile {{{
+
+type Closer func() error
+
+func LoadFile(path string) (*Deb, Closer, error) {
+	fd, err := os.Open(path)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	debFile, err := Load(fd, path)
+	if err != nil {
+		fd.Close()
+		return nil, nil, err
+	}
+
+	return debFile, fd.Close, nil
+
+}
+
+// }}}
+
+// Debian .deb Loader Internals {{{
+
+// Top-level .deb loader dispatch on Version {{{
+
+// Look for the debian-binary member and figure out which version to read
+// it as. Return the newly created .deb struct.
+func loadDeb(archive *Ar) (*Deb, error) {
+	for {
+		member, err := archive.Next()
+		if err == io.EOF {
+			return nil, fmt.Errorf("Archive contains no binary version member!")
+		}
+		if err != nil {
+			return nil, err
+		}
+		if member.Name == "debian-binary" {
+			reader := bufio.NewReader(member.Data)
+			version, err := reader.ReadString('\n')
+			if err != nil {
+				return nil, err
+			}
+			switch version {
+			case "2.0\n":
+				return loadDeb2(archive)
+			default:
+				return nil, fmt.Errorf("Unknown binary version: '%s'", version)
+			}
+		}
+	}
+}
+
+// }}}
+
+// Debian .deb format 2.0 {{{
+
+// Top-level .deb loader dispatch for 2.0 {{{
+
+// Load a Debian 2.x series .deb - track down the control and data members.
+func loadDeb2(archive *Ar) (*Deb, error) {
+	ret := Deb{}
+
+	if err := loadDeb2Control(archive, &ret); err != nil {
+		return nil, err
+	}
+
+	if err := loadDeb2Data(archive, &ret); err != nil {
+		return nil, err
+	}
+
+	return &ret, nil
+}
+
+// }}}
+
+// Decode .deb 2.0 control data into the struct {{{
+
+// Load a Debian 2.x series .deb control file and write it out to
+// the deb.Deb.Control member.
+func loadDeb2Control(archive *Ar, deb *Deb) error {
+	for {
+		member, err := archive.Next()
+		if err == io.EOF {
+			return fmt.Errorf("Missing or out of order .deb member 'control'")
+		}
+		if err != nil {
+			return err
+		}
+		if strings.HasPrefix(member.Name, "control.") {
+			archive, err := member.Tarfile()
+			if err != nil {
+				return err
+			}
+			for {
+				member, err := archive.Next()
+				if err != nil {
+					return err
+				}
+				if path.Clean(member.Name) == "control" {
+					return control.Unmarshal(&deb.Control, archive)
+				}
+			}
+		}
+	}
+}
+
+// }}}
+
+// Decode .deb 2.0 package data into the struct {{{
+
+// Load a Debian 2.x series .deb data file and write it out to
+// the deb.Deb.Data member.
+func loadDeb2Data(archive *Ar, deb *Deb) error {
+	for {
+		member, err := archive.Next()
+		if err == io.EOF {
+			return fmt.Errorf("Missing or out of order .deb member 'data'")
+		}
+		if err != nil {
+			return err
+		}
+		if strings.HasPrefix(member.Name, "data.") {
+			archive, err := member.Tarfile()
+			if err != nil {
+				return err
+			}
+			deb.Data = archive
+			return nil
+		}
+	}
+}
+
+// }}}
+
+// }}} }}} }}} }}}
+
+// vim: foldmethod=marker

+ 40 - 0
bashbrew/go/vendor/src/pault.ag/go/debian/deb/doc.go

@@ -0,0 +1,40 @@
+/*
+
+This module provides an API to access and programmatically process
+Debian `.deb` archives on disk.
+
+Debian files, at a high level, are `ar(1)` archives, which
+contain a few sections, most notably the `control` member, which contains
+information about the Debian package itself, and the `data` member, which
+contains the actual contents of the files, as they should be written out
+on disk.
+
+Here's a trivial example, which will print out the Package name for a
+`.deb` archive given on the command line:
+
+	package main
+
+	import (
+		"log"
+		"os"
+
+		"pault.ag/go/debian/deb"
+	)
+
+	func main() {
+		path := os.Args[1]
+		fd, err := os.Open(path)
+		if err != nil {
+			panic(err)
+		}
+		defer fd.Close()
+
+		debFile, err := deb.Load(fd, path)
+		if err != nil {
+			panic(err)
+		}
+		log.Printf("Package: %s\n", debFile.Control.Package)
+	}
+
+*/
+package deb

+ 105 - 0
bashbrew/go/vendor/src/pault.ag/go/debian/deb/tarfile.go

@@ -0,0 +1,105 @@
+/* {{{ Copyright (c) Paul R. Tagliamonte <[email protected]>, 2015
+ *
+ * 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. }}} */
+
+package deb
+
+import (
+	"fmt"
+	"io"
+	"strings"
+
+	"archive/tar"
+
+	"compress/bzip2"
+	"compress/gzip"
+	"xi2.org/x/xz"
+)
+
+// known compression types {{{
+
+type compressionReader func(io.Reader) (io.Reader, error)
+
+func gzipNewReader(r io.Reader) (io.Reader, error) {
+	return gzip.NewReader(r)
+}
+
+func xzNewReader(r io.Reader) (io.Reader, error) {
+	return xz.NewReader(r, 0)
+}
+
+func bzipNewReader(r io.Reader) (io.Reader, error) {
+	return bzip2.NewReader(r), nil
+}
+
+var knownCompressionAlgorithms = map[string]compressionReader{
+	".tar.gz":  gzipNewReader,
+	".tar.bz2": bzipNewReader,
+	".tar.xz":  xzNewReader,
+}
+
+// }}}
+
+// IsTarfile {{{
+
+// Check to see if the given ArEntry is, in fact, a Tarfile. This method
+// will return `true` for `control.tar.*` and `data.tar.*` files.
+//
+// This will return `false` for the `debian-binary` file. If this method
+// returns `true`, the `.Tarfile()` method will be around to give you a
+// tar.Reader back.
+func (e *ArEntry) IsTarfile() bool {
+	return e.getCompressionReader() != nil
+}
+
+// }}}
+
+// Tarfile {{{
+
+// `.Tarfile()` will return a `tar.Reader` created from the ArEntry member
+// to allow further inspection of the contents of the `.deb`.
+func (e *ArEntry) Tarfile() (*tar.Reader, error) {
+	decompressor := e.getCompressionReader()
+	if decompressor == nil {
+		return nil, fmt.Errorf("%s appears to not be a tarfile", e.Name)
+	}
+	reader, err := (*decompressor)(e.Data)
+	if err != nil {
+		return nil, err
+	}
+	return tar.NewReader(reader), nil
+}
+
+// }}}
+
+// getCompressionReader {{{
+
+// Get a compressionReader that we can use to unpack the member.
+func (e *ArEntry) getCompressionReader() *compressionReader {
+	for key, decompressor := range knownCompressionAlgorithms {
+		if strings.HasSuffix(e.Name, key) {
+			return &decompressor
+		}
+	}
+	return nil
+}
+
+// }}}
+
+// vim: foldmethod=marker

+ 1 - 1
bashbrew/go/vendor/src/pault.ag/go/debian/dependency/string.go

@@ -31,7 +31,7 @@ func (a Arch) MarshalControl() (string, error) {
 func (a Arch) String() string {
 	/* ABI-OS-CPU -- gnu-linux-amd64 */
 	els := []string{}
-	if a.ABI != "any" && a.ABI != "all" && a.ABI != "gnu" {
+	if a.ABI != "any" && a.ABI != "all" && a.ABI != "gnu" && a.ABI != "" {
 		els = append(els, a.ABI)
 	}