Skip to content

Commit

Permalink
Merge pull request #5 from goreleaser/recommends
Browse files Browse the repository at this point in the history
feat: support recommending and suggesting packages
  • Loading branch information
caarlos0 committed Feb 18, 2018
2 parents ce0f322 + 4d7ea97 commit 8bb63d1
Show file tree
Hide file tree
Showing 11 changed files with 465 additions and 79 deletions.
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
dist: trusty
addons:
apt:
packages:
Expand All @@ -9,6 +8,8 @@ go: '1.10'
# - docker
install:
- make setup
before_script:
- rpmbuild --version
script:
- make ci
after_success:
Expand Down
2 changes: 2 additions & 0 deletions cmd/nfpm/nfpm.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ provides:
depends:
- foo
- bar
recommends:
- whatever
conflicts:
- not-foo
- not-bar
Expand Down
20 changes: 13 additions & 7 deletions deb/deb.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ Installed-Size: {{.InstalledSize}}
Replaces: {{join .Info.Replaces}}
Provides: {{join .Info.Provides}}
Depends: {{join .Info.Depends}}
Recommends: {{join .Info.Recommends}}
Recommends: {{join .Info.Suggests}}
Conflicts: {{join .Info.Conflicts}}
Homepage: {{.Info.Homepage}}
Description: {{.Info.Description}}
Expand All @@ -172,13 +174,7 @@ func createControl(now time.Time, instSize int64, md5sums []byte, info nfpm.Info
defer compress.Close() // nolint: errcheck

var body bytes.Buffer
var tmpl = template.New("control")
tmpl.Funcs(template.FuncMap{
"join": func(strs []string) string {
return strings.Trim(strings.Join(strs, ", "), " ")
},
})
if err := template.Must(tmpl.Parse(controlTemplate)).Execute(&body, controlData{
if err := writeControl(&body, controlData{
Info: info,
InstalledSize: instSize / 1024,
}); err != nil {
Expand All @@ -204,6 +200,16 @@ func createControl(now time.Time, instSize int64, md5sums []byte, info nfpm.Info
return buf.Bytes(), nil
}

func writeControl(w io.Writer, data controlData) error {
var tmpl = template.New("control")
tmpl.Funcs(template.FuncMap{
"join": func(strs []string) string {
return strings.Trim(strings.Join(strs, ", "), " ")
},
})
return template.Must(tmpl.Parse(controlTemplate)).Execute(w, data)
}

func newFileInsideTarGz(out *tar.Writer, name string, content []byte, now time.Time) error {
var header = tar.Header{
Name: name,
Expand Down
79 changes: 56 additions & 23 deletions deb/deb_test.go
Original file line number Diff line number Diff line change
@@ -1,38 +1,71 @@
package deb

import (
"bytes"
"flag"
"io/ioutil"
"testing"

"github.com/goreleaser/nfpm"
"github.com/stretchr/testify/assert"
)

var update = flag.Bool("update", false, "update .golden files")

var info = nfpm.WithDefaults(nfpm.Info{
Name: "foo",
Arch: "amd64",
Depends: []string{
"bash",
},
Recommends: []string{
"git",
},
Suggests: []string{
"bash",
},
Replaces: []string{
"svn",
},
Provides: []string{
"bzr",
},
Conflicts: []string{
"zsh",
},
Description: "Foo does things",
Priority: "extra",
Maintainer: "Carlos A Becker <pkg@carlosbecker.com>",
Version: "1.0.0",
Section: "default",
Homepage: "http://carlosbecker.com",
Vendor: "nope",
Files: map[string]string{
"../testdata/fake": "/usr/local/bin/fake",
},
ConfigFiles: map[string]string{
"../testdata/whatever.conf": "/etc/fake/fake.conf",
},
})

func TestDeb(t *testing.T) {
var err = Default.Package(
nfpm.WithDefaults(nfpm.Info{
Name: "foo",
Arch: "amd64",
Depends: []string{
"bash",
},
Description: "Foo does things",
Priority: "extra",
Maintainer: "Carlos A Becker <pkg@carlosbecker.com>",
Version: "1.0.0",
Section: "default",
Homepage: "http://carlosbecker.com",
Vendor: "nope",
Files: map[string]string{
"../testdata/fake": "/usr/local/bin/fake",
},
ConfigFiles: map[string]string{
"../testdata/whatever.conf": "/etc/fake/fake.conf",
},
}),
ioutil.Discard,
)
var err = Default.Package(info, ioutil.Discard)
assert.NoError(t, err)
}

func TestControl(t *testing.T) {
var w bytes.Buffer
assert.NoError(t, writeControl(&w, controlData{
Info: info,
InstalledSize: 10,
}))
var golden = "testdata/control.golden"
if *update {
ioutil.WriteFile(golden, w.Bytes(), 0655)
}
bts, err := ioutil.ReadFile(golden)
assert.NoError(t, err)
assert.Equal(t, string(bts), w.String())
}

func TestDebFileDoesNotExist(t *testing.T) {
Expand Down
16 changes: 16 additions & 0 deletions deb/testdata/control.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Package: foo
Version: 1.0.0
Section: default
Priority: extra
Architecture: amd64
Maintainer: Carlos A Becker <pkg@carlosbecker.com>
Vendor: nope
Installed-Size: 10
Replaces: svn
Provides: bzr
Depends: bash
Recommends: git
Recommends: bash
Conflicts: zsh
Homepage: http://carlosbecker.com
Description: Foo does things
2 changes: 2 additions & 0 deletions nfpm.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ type Info struct {
Replaces []string `yaml:"replaces,omitempty"`
Provides []string `yaml:"provides,omitempty"`
Depends []string `yaml:"depends,omitempty"`
Recommends []string `yaml:"recommends,omitempty"`
Suggests []string `yaml:"suggests,omitempty"`
Conflicts []string `yaml:"conflicts,omitempty"`
Maintainer string `yaml:"maintainer,omitempty"`
Description string `yaml:"description,omitempty"`
Expand Down
100 changes: 78 additions & 22 deletions rpm/rpm.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"text/template"

Expand All @@ -32,6 +33,10 @@ func (*RPM) Package(info nfpm.Info, w io.Writer) error {
if info.Arch == "amd64" {
info.Arch = "x86_64"
}
_, err := exec.LookPath("rpmbuild")
if err != nil {
return fmt.Errorf("rpmbuild not present in $PATH")
}
temps, err := setupTempFiles(info)
if err != nil {
return err
Expand Down Expand Up @@ -70,21 +75,62 @@ func (*RPM) Package(info nfpm.Info, w io.Writer) error {
return errors.Wrap(err, "failed to copy rpm file to writer")
}

type rpmbuildVersion struct {
Major, Minor, Path int
}

func getRpmbuildVersion() (rpmbuildVersion, error) {
// #nosec
bts, err := exec.Command("rpmbuild", "--version").CombinedOutput()
if err != nil {
return rpmbuildVersion{}, errors.Wrap(err, "failed to get rpmbuild version")
}
var v = make([]int, 3)
vs := strings.TrimSuffix(strings.TrimPrefix(string(bts), "RPM version "), "\n")
for i, part := range strings.Split(vs, ".")[:3] {
pi, err := strconv.Atoi(part)
if err != nil {
return rpmbuildVersion{}, errors.Wrapf(err, "could not parse version %s", vs)
}
v[i] = pi
}
return rpmbuildVersion{
Major: v[0],
Minor: v[1],
Path: v[2],
}, nil
}

func createSpec(info nfpm.Info, path string) error {
var body bytes.Buffer
file, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0600)
if err != nil {
return errors.Wrap(err, "failed to create spec")
}
vs, err := getRpmbuildVersion()
if err != nil {
return err
}
return writeSpec(file, info, vs)
}

func writeSpec(w io.Writer, info nfpm.Info, vs rpmbuildVersion) error {
var tmpl = template.New("spec")
tmpl.Funcs(template.FuncMap{
"join": func(strs []string) string {
return strings.Trim(strings.Join(strs, ", "), " ")
},
"first_line": func(str string) string {
return strings.Split(str, "\n")[0]
},
})
if err := template.Must(tmpl.Parse(specTemplate)).Execute(&body, info); err != nil {
type data struct {
Info nfpm.Info
RPM413 bool
}
if err := template.Must(tmpl.Parse(specTemplate)).Execute(w, data{
Info: info,
RPM413: vs.Major >= 4 && vs.Minor >= 13,
}); err != nil {
return errors.Wrap(err, "failed to parse spec template")
}
return errors.Wrap(ioutil.WriteFile(path, body.Bytes(), 0644), "failed to write spec file")
return nil
}

type tempFiles struct {
Expand Down Expand Up @@ -196,37 +242,47 @@ const specTemplate = `
%define __spec_install_post %{nil}
%define debug_package %{nil}
%define __os_install_post %{_dbpath}/brp-compress
%define _arch {{.Arch}}
%define _bindir {{.Bindir}}
%define _arch {{ .Info.Arch }}
%define _bindir {{ .Info.Bindir }}
Name: {{ .Name }}
Summary: {{ first_line .Description }}
Version: {{ .Version }}
Name: {{ .Info.Name }}
Summary: {{ first_line .Info.Description }}
Version: {{ .Info.Version }}
Release: 1
License: {{ .License }}
License: {{ .Info.License }}
Group: Development/Tools
SOURCE0 : %{name}-%{version}.tar.gz
URL: {{ .Homepage }}
URL: {{ .Info.Homepage }}
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
{{ range $index, $element := .Replaces }}
Obsolotes: {{ . }}
{{ range $index, $element := .Info.Replaces }}
Obsoletes: {{ . }}
{{ end }}
{{ range $index, $element := .Conflicts }}
{{ range $index, $element := .Info.Conflicts }}
Conflicts: {{ . }}
{{ end }}
{{ range $index, $element := .Provides }}
{{ range $index, $element := .Info.Provides }}
Provides: {{ . }}
{{ end }}
{{ range $index, $element := .Depends }}
{{ range $index, $element := .Info.Depends }}
Requires: {{ . }}
{{ end }}
{{ if .RPM413 }}
{{ range $index, $element := .Info.Recommends }}
Recommends: {{ . }}
{{ end }}
{{ range $index, $element := .Info.Suggests }}
Suggests: {{ . }}
{{ end }}
{{ end }}
%description
{{ .Description }}
{{ .Info.Description }}
%prep
%setup -q
Expand All @@ -246,14 +302,14 @@ rm -rf %{buildroot}
%files
%defattr(-,root,root,-)
{{ range $index, $element := .Files }}
{{ range $index, $element := .Info.Files }}
{{ . }}
{{ end }}
%{_bindir}/*
{{ range $index, $element := .ConfigFiles }}
{{ range $index, $element := .Info.ConfigFiles }}
{{ . }}
{{ end }}
{{ range $index, $element := .ConfigFiles }}
{{ range $index, $element := .Info.ConfigFiles }}
%config(noreplace) {{ . }}
{{ end }}
Expand Down

0 comments on commit 8bb63d1

Please sign in to comment.