From 2c84faaf8d5719e6dfe474ac2c512fac7dc017af Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Tue, 30 Sep 2014 21:26:28 +0400 Subject: [PATCH] System test for repo adding .udebs. #108 --- cmd/repo_add.go | 17 ++++++--- system/lib.py | 1 + system/t09_repo/AddRepo12Test_gold | 2 + system/t09_repo/AddRepo12Test_repo_show | 7 ++++ system/t09_repo/AddRepo13Test_gold | 6 +++ system/t09_repo/AddRepo13Test_repo_show | 11 ++++++ system/t09_repo/add.py | 35 ++++++++++++++++++ .../dmraid-udeb_1.0.0.rc16-4.1_amd64.udeb | Bin 0 -> 11806 bytes .../dmraid-udeb_1.0.0.rc16-4.1_i386.udeb | Bin 0 -> 11022 bytes 9 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 system/t09_repo/AddRepo12Test_gold create mode 100644 system/t09_repo/AddRepo12Test_repo_show create mode 100644 system/t09_repo/AddRepo13Test_gold create mode 100644 system/t09_repo/AddRepo13Test_repo_show create mode 100644 system/udebs/dmraid-udeb_1.0.0.rc16-4.1_amd64.udeb create mode 100644 system/udebs/dmraid-udeb_1.0.0.rc16-4.1_i386.udeb diff --git a/cmd/repo_add.go b/cmd/repo_add.go index a1370b95..7626efc0 100644 --- a/cmd/repo_add.go +++ b/cmd/repo_add.go @@ -61,14 +61,16 @@ func aptlyRepoAdd(cmd *commander.Command, args []string) error { return nil } - if strings.HasSuffix(info.Name(), ".deb") || strings.HasSuffix(info.Name(), ".dsc") { + if strings.HasSuffix(info.Name(), ".deb") || strings.HasSuffix(info.Name(), ".udeb") || + strings.HasSuffix(info.Name(), ".dsc") { packageFiles = append(packageFiles, path) } return nil }) } else { - if strings.HasSuffix(info.Name(), ".deb") || strings.HasSuffix(info.Name(), ".dsc") { + if strings.HasSuffix(info.Name(), ".deb") || strings.HasSuffix(info.Name(), ".udeb") || + strings.HasSuffix(info.Name(), ".dsc") { packageFiles = append(packageFiles, location) } else { context.Progress().ColoredPrintf("@y[!]@| @!Unknwon file extenstion: %s@|", location) @@ -93,6 +95,7 @@ func aptlyRepoAdd(cmd *commander.Command, args []string) error { candidateProcessedFiles := []string{} isSourcePackage := strings.HasSuffix(file, ".dsc") + isUdebPackage := strings.HasSuffix(file, ".udeb") if isSourcePackage { stanza, err = deb.GetControlFileFromDsc(file, verifier) @@ -105,7 +108,11 @@ func aptlyRepoAdd(cmd *commander.Command, args []string) error { } } else { stanza, err = deb.GetControlFileFromDeb(file) - p = deb.NewPackageFromControlFile(stanza) + if isUdebPackage { + p = deb.NewUdebPackageFromControlFile(stanza) + } else { + p = deb.NewPackageFromControlFile(stanza) + } } if err != nil { context.Progress().ColoredPrintf("@y[!]@| @!Unable to read file %s: %s@|", file, err) @@ -216,8 +223,8 @@ func makeCmdRepoAdd() *commander.Command { UsageLine: "add | ...", Short: "add packages to local repository", Long: ` -Command adds packages to local repository from .deb (binary packages) and .dsc (source packages) files. -When importing from directory aptly would do recursive scan looking for all files matching *.deb or *.dsc +Command adds packages to local repository from .deb, .udeb (binary packages) and .dsc (source packages) files. +When importing from directory aptly would do recursive scan looking for all files matching *.[u]deb or *.dsc patterns. Every file discovered would be analyzed to extract metadata, package would then be created and added to the database. Files would be imported to internal package pool. For source packages, all required files are added automatically as well. Extra files for source package should be in the same directory as *.dsc file. diff --git a/system/lib.py b/system/lib.py index 34b5f684..e3e84f6a 100644 --- a/system/lib.py +++ b/system/lib.py @@ -155,6 +155,7 @@ class BaseTest(object): if not hasattr(command, "__iter__"): params = { 'files': os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "files"), + 'udebs': os.path.join(os.path.dirname(inspect.getsourcefile(BaseTest)), "udebs"), 'testfiles': os.path.join(os.path.dirname(inspect.getsourcefile(self.__class__)), self.__class__.__name__), } if self.fixtureWebServer: diff --git a/system/t09_repo/AddRepo12Test_gold b/system/t09_repo/AddRepo12Test_gold new file mode 100644 index 00000000..362cf9ac --- /dev/null +++ b/system/t09_repo/AddRepo12Test_gold @@ -0,0 +1,2 @@ +Loading packages... +[+] dmraid-udeb_1.0.0.rc16-4.1_amd64 added diff --git a/system/t09_repo/AddRepo12Test_repo_show b/system/t09_repo/AddRepo12Test_repo_show new file mode 100644 index 00000000..b5cda2da --- /dev/null +++ b/system/t09_repo/AddRepo12Test_repo_show @@ -0,0 +1,7 @@ +Name: repo12 +Comment: Repo12 +Default Distribution: squeeze +Default Component: main +Number of packages: 1 +Packages: + dmraid-udeb_1.0.0.rc16-4.1_amd64 diff --git a/system/t09_repo/AddRepo13Test_gold b/system/t09_repo/AddRepo13Test_gold new file mode 100644 index 00000000..89051da0 --- /dev/null +++ b/system/t09_repo/AddRepo13Test_gold @@ -0,0 +1,6 @@ +Loading packages... +[+] libboost-program-options-dev_1.49.0.1_i386 added +[+] pyspi_0.6.1-1.4_source added +[+] pyspi_0.6.1-1.3_source added +[+] dmraid-udeb_1.0.0.rc16-4.1_amd64 added +[+] dmraid-udeb_1.0.0.rc16-4.1_i386 added diff --git a/system/t09_repo/AddRepo13Test_repo_show b/system/t09_repo/AddRepo13Test_repo_show new file mode 100644 index 00000000..b921958a --- /dev/null +++ b/system/t09_repo/AddRepo13Test_repo_show @@ -0,0 +1,11 @@ +Name: repo13 +Comment: Repo13 +Default Distribution: squeeze +Default Component: main +Number of packages: 5 +Packages: + dmraid-udeb_1.0.0.rc16-4.1_amd64 + dmraid-udeb_1.0.0.rc16-4.1_i386 + libboost-program-options-dev_1.49.0.1_i386 + pyspi_0.6.1-1.3_source + pyspi_0.6.1-1.4_source diff --git a/system/t09_repo/add.py b/system/t09_repo/add.py index 1e91c2ee..9b5d9319 100644 --- a/system/t09_repo/add.py +++ b/system/t09_repo/add.py @@ -232,3 +232,38 @@ class AddRepo11Test(BaseTest): def check(self): self.check_output() self.check_cmd_output("aptly repo show -with-packages repo11", "repo_show") + + +class AddRepo12Test(BaseTest): + """ + add package to local repo: .udeb file + """ + fixtureCmds = [ + "aptly repo create -comment=Repo12 -distribution=squeeze repo12", + ] + runCmd = "aptly repo add repo12 ${udebs}/dmraid-udeb_1.0.0.rc16-4.1_amd64.udeb" + + def check(self): + self.check_output() + self.check_cmd_output("aptly repo show -with-packages repo12", "repo_show") + + # check pool + self.check_exists('pool/72/16/dmraid-udeb_1.0.0.rc16-4.1_amd64.udeb') + + +class AddRepo13Test(BaseTest): + """ + add package to local repo: .udeb and .deb files + """ + fixtureCmds = [ + "aptly repo create -comment=Repo13 -distribution=squeeze repo13", + ] + runCmd = "aptly repo add repo13 ${udebs} ${files}" + + def check(self): + self.check_output() + self.check_cmd_output("aptly repo show -with-packages repo13", "repo_show") + + # check pool + self.check_exists('pool/72/16/dmraid-udeb_1.0.0.rc16-4.1_amd64.udeb') + self.check_exists('pool/b7/2c/pyspi_0.6.1-1.3.dsc') diff --git a/system/udebs/dmraid-udeb_1.0.0.rc16-4.1_amd64.udeb b/system/udebs/dmraid-udeb_1.0.0.rc16-4.1_amd64.udeb new file mode 100644 index 0000000000000000000000000000000000000000..0e7f0635801f6d0210e63ec5d5fb82b54d5e976c GIT binary patch literal 11806 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