From bed0ac475ecd13fe3352170e8dda23b9bae2e360 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Thu, 6 Mar 2014 21:06:50 +0400 Subject: [PATCH] Short syntax for aptly mirror create to support ppa:user/project mirror URLs. --- cmd/mirror_create.go | 23 +++++++++++++++++-- debian/ppa.go | 54 ++++++++++++++++++++++++++++++++++++++++++++ debian/ppa_test.go | 34 ++++++++++++++++++++++++++++ utils/config.go | 4 ++++ utils/config_test.go | 4 +++- 5 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 debian/ppa.go create mode 100644 debian/ppa_test.go diff --git a/cmd/mirror_create.go b/cmd/mirror_create.go index b9f9415d..540d7434 100644 --- a/cmd/mirror_create.go +++ b/cmd/mirror_create.go @@ -6,18 +6,34 @@ import ( "github.com/gonuts/flag" "github.com/smira/aptly/debian" "github.com/smira/aptly/utils" + "strings" ) func aptlyMirrorCreate(cmd *commander.Command, args []string) error { var err error - if len(args) < 3 { + if !(len(args) == 2 && strings.HasPrefix(args[1], "ppa:") || len(args) >= 3) { cmd.Usage() return err } downloadSources := utils.Config.DownloadSourcePackages || cmd.Flag.Lookup("with-sources").Value.Get().(bool) - repo, err := debian.NewRemoteRepo(args[0], args[1], args[2], args[3:], context.architecturesList, downloadSources) + var ( + mirrorName, archiveURL, distribution string + components []string + ) + + mirrorName = args[0] + if len(args) == 2 { + archiveURL, distribution, components, err = debian.ParsePPA(args[1]) + if err != nil { + return err + } + } else { + archiveURL, distribution, components = args[1], args[2], args[3:] + } + + repo, err := debian.NewRemoteRepo(mirrorName, archiveURL, distribution, components, context.architecturesList, downloadSources) if err != nil { return fmt.Errorf("unable to create mirror: %s", err) } @@ -51,6 +67,9 @@ func makeCmdMirrorCreate() *commander.Command { Long: ` Create records information about new mirror and fetches Release file (it doesn't download packages). +PPA url could specified in short format when running on Debian/Ubuntu: + $ aptly mirror create some_ppa ppa:user/project + ex: $ aptly mirror create wheezy-main http://mirror.yandex.ru/debian/ wheezy main `, diff --git a/debian/ppa.go b/debian/ppa.go new file mode 100644 index 00000000..f83b787f --- /dev/null +++ b/debian/ppa.go @@ -0,0 +1,54 @@ +package debian + +import ( + "fmt" + "github.com/smira/aptly/utils" + "os/exec" + "regexp" + "strings" +) + +var ppaRegexp = regexp.MustCompile("^ppa:([^/]+)/(.+)$") + +// ParsePPA converts ppa URL like ppa:user/ppa-name to full HTTP url +func ParsePPA(ppaURL string) (url string, distribution string, components []string, err error) { + matches := ppaRegexp.FindStringSubmatch(ppaURL) + if matches == nil { + err = fmt.Errorf("unable to parse ppa URL: %v", ppaURL) + return + } + + distributorID := utils.Config.PpaDistributorID + if distributorID == "" { + distributorID, err = getDistributorID() + if err != nil { + err = fmt.Errorf("unable to figure out Distributor ID: %s, please set config option ppaDistributorID", err) + return + } + } + + codename := utils.Config.PpaCodename + if codename == "" { + codename, err = getCodename() + if err != nil { + err = fmt.Errorf("unable to figure out Codename: %s, please set config option ppaCodename", err) + return + } + } + + distribution = codename + components = []string{"main"} + url = fmt.Sprintf("http://ppa.launchpad.net/%s/%s/%s", matches[1], matches[2], distributorID) + + return +} + +func getCodename() (string, error) { + out, err := exec.Command("lsb_release", "-sc").Output() + return strings.TrimSpace(string(out)), err +} + +func getDistributorID() (string, error) { + out, err := exec.Command("lsb_release", "-si").Output() + return strings.ToLower(strings.TrimSpace(string(out))), err +} diff --git a/debian/ppa_test.go b/debian/ppa_test.go new file mode 100644 index 00000000..778642b0 --- /dev/null +++ b/debian/ppa_test.go @@ -0,0 +1,34 @@ +package debian + +import ( + "github.com/smira/aptly/utils" + . "launchpad.net/gocheck" +) + +type PpaSuite struct { + savedConfig utils.ConfigStructure +} + +var _ = Suite(&PpaSuite{}) + +func (s *PpaSuite) SetUpTest(c *C) { + s.savedConfig = utils.Config +} + +func (s *PpaSuite) TearDownTest(c *C) { + utils.Config = s.savedConfig +} + +func (s *PpaSuite) TestParsePPA(c *C) { + _, _, _, err := ParsePPA("ppa:dedeed") + c.Check(err, ErrorMatches, "unable to parse ppa URL.*") + + utils.Config.PpaDistributorID = "debian" + utils.Config.PpaCodename = "wheezy" + + url, distribution, components, err := ParsePPA("ppa:user/project") + c.Check(err, IsNil) + c.Check(url, Equals, "http://ppa.launchpad.net/user/project/debian") + c.Check(distribution, Equals, "wheezy") + c.Check(components, DeepEquals, []string{"main"}) +} diff --git a/utils/config.go b/utils/config.go index 01c8439e..61253a96 100644 --- a/utils/config.go +++ b/utils/config.go @@ -18,6 +18,8 @@ type ConfigStructure struct { GpgDisableSign bool `json:"gpgDisableSign"` GpgDisableVerify bool `json:"gpgDisableVerify"` DownloadSourcePackages bool `json:"downloadSourcePackages"` + PpaDistributorID string `json:"ppaDistributorID"` + PpaCodename string `json:"ppaCodename"` } // Config is configuration for aptly, shared by all modules @@ -32,6 +34,8 @@ var Config = ConfigStructure{ GpgDisableSign: false, GpgDisableVerify: false, DownloadSourcePackages: false, + PpaDistributorID: "ubuntu", + PpaCodename: "", } // LoadConfig loads configuration from json file diff --git a/utils/config_test.go b/utils/config_test.go index bfc28304..962a4a58 100644 --- a/utils/config_test.go +++ b/utils/config_test.go @@ -51,7 +51,9 @@ func (s *ConfigSuite) TestSaveConfig(c *C) { " \"dependencyFollowSource\": false,\n"+ " \"gpgDisableSign\": false,\n"+ " \"gpgDisableVerify\": false,\n"+ - " \"downloadSourcePackages\": false\n"+ + " \"downloadSourcePackages\": false,\n"+ + " \"ppaDistributorID\": \"\",\n"+ + " \"ppaCodename\": \"\"\n"+ "}") }