Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support recommending and suggesting packages #5

Merged
merged 7 commits into from
Feb 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading