npm2rpm 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZDQ1YTJmZjBlYjVkNWMxMjBlNTAyYjY2YjE5NzNmNGMwODk2ZjNmNQ==
5
+ data.tar.gz: !binary |-
6
+ ZDE3YjMwODM0MTFjN2Q0YTg1ZjhmOWJmZDdkYWQ4MTk4ODI0MjkyMg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MmFmNWU4YTdhMjY1YmRjMzc1NGI1NWI4ZDBjZDU3NmYyMmI1YWI1NzdkYWEy
10
+ ZmQ1NjE3MTgzMmZiMDk3ZGUyNjIzNGY1NzNmZGI4NjM0MjRlZjM4ZjAxZTlj
11
+ NjBhMzg2OTMxZDIxYTVlMzNkMDQ2ZjBmOTQ1NjhhMjJlZDdkYWU=
12
+ data.tar.gz: !binary |-
13
+ ODdmMGNlYzc4NWM3MGMwMzkyZmU0ZDg4YWI3YmM1ZmVmNmQ4MDQ3MWExNzc0
14
+ N2U0MjljZjJlNWI3NmEzOGU1ZWU4ZTU1NjgyYzI2ZDZjNDZjNmU2YzZkMGM4
15
+ MGMxYWZiYTYwODNkYWFjMTY4NTAyOTQ5NzA1MTQ4MWIwYTA1N2Q=
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in genprovider.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,57 @@
1
+ npm2rpm is copyrighted free software by Klaus Kaempf <kkaempf@suse.de>.
2
+ You can redistribute it and/or modify it under either the terms of the GPL
3
+ (see COPYING.txt file), or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) rename any non-standard executables so the names do not conflict
21
+ with standard executables, which must also be provided.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or executable
26
+ form, provided that you do at least ONE of the following:
27
+
28
+ a) distribute the executables and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c) give non-standard executables non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under this terms.
43
+
44
+ They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
45
+ files under the ./missing directory. See each file for the copying
46
+ condition.
47
+
48
+ 5. The scripts and library files supplied as input to or produced as
49
+ output from the software do not automatically fall under the
50
+ copyright of the software, but belong to whomever generated them,
51
+ and may be sold commercially, and may be aggregated with this
52
+ software.
53
+
54
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
55
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
56
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57
+ PURPOSE.
data/README.md ADDED
@@ -0,0 +1,15 @@
1
+ = Creating RPM packages for Nodejs modules
2
+
3
+ Picking up where https://github.com/lkundrak/npm2rpm left off, this
4
+ Rubygem creates RPM packages from Nodejs modules.
5
+
6
+ It differs from the original implementation as follows
7
+ * Uses Ruby
8
+ * Much more robust
9
+ * Ability to package multiple versions of the same module
10
+ * Spec generated from template
11
+ * Support for multiple Linux distributions possible
12
+
13
+ = License
14
+
15
+ Ruby
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ task :default => [:build]
data/bin/npm2rpm ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # npm2rpm
4
+ #
5
+ # Generate spec from Nodejs NPM
6
+ #
7
+ # Copyright (c) 2013 Klaus Kämpf <kkaempf@suse.de>
8
+ #
9
+ # Licensed under the Ruby license
10
+ #
11
+
12
+ require 'rubygems'
13
+
14
+ $:.push(File.join(File.dirname(__FILE__), '..', 'lib'))
15
+
16
+ require 'npm2rpm'
17
+
18
+ options = Npm2Rpm::Options.new
19
+
20
+ metadata = Npm2Rpm::Metadata.new options.package, options.version
21
+
22
+ spec = Npm2Rpm::Spec.new(metadata)
23
+
24
+ begin
25
+ Dir.mkdir spec.name
26
+ rescue Errno::EEXIST
27
+ end
28
+ Dir.chdir spec.name
29
+
30
+ spec.write
31
+ Npm2Rpm::Changes.new(spec.name, metadata, options).write
32
+ Npm2Rpm::Rpmlintrc.new(spec.name, metadata, options).write
33
+
34
+ Dir.chdir ".."
35
+
36
+ Kernel.system "osc add #{spec.name}"
37
+
38
+ Dir.chdir spec.name
39
+ Kernel.system "osc ci"
40
+ Dir.chdir ".."
data/doc/options ADDED
@@ -0,0 +1,77 @@
1
+ =head1 OPTIONS
2
+
3
+ =over
4
+
5
+ =item B<--specdir> B<< <specdir> >>
6
+
7
+ Where to write the resulting SPEC file to.
8
+ Defaults to B<%_specdir> RPM macro, which is usually
9
+ ~/rpmbuild/SPECS (or /usr/src/redhat/SPECS on ancient
10
+ RPM versions).
11
+
12
+ =item B<--sourcedir> B<< <sourcedir> >>
13
+
14
+ Where to download the upstream distribution tarball to.
15
+ Defaults to B<%_sourcedir> RPM macro, which is usually
16
+ ~/rpmbuild/SOURCES (or /usr/src/redhat/SOURCES on ancient
17
+ RPM versions).
18
+
19
+ =item B<--date> B<< <date> >>
20
+
21
+ Date to use for initial changelog entry (e.g. Mon Dec 20 2010).
22
+ Defaults to output of C<date +'%a %b %d %Y'>.
23
+
24
+ =item B<--user> B<< <user> >>
25
+
26
+ Name (in "Firstname Lastname") format to use for initial
27
+ changelog entry. Defaults to your account's real name.
28
+
29
+ =item B<--email> B<< <email> >>
30
+
31
+ E-mail address to use in initial changelog entry.
32
+ Defaults to your login.
33
+
34
+ =item [B<--package>] B<< <package> >>
35
+
36
+ The NPM package name to act upon. Mandatory.
37
+
38
+ =item B<-h>, B<--help>
39
+
40
+ Prints and error message and exits
41
+
42
+ =item B<-H>, B<--manual>
43
+
44
+ Show the complete manual page and exit.
45
+
46
+ =back
47
+
48
+ =head1 BUGS
49
+
50
+ The resulting package is ugly as hell -- due the way NPM currently
51
+ works the whole npm tree has to be copied for unprivileged build,
52
+ which is inefficient.
53
+
54
+ NPM packages sometimes lack pieces of metadata this tool uses;
55
+ you may see "uninitialized" warnings from perl, as well as empty
56
+ or "FIXME" tags in the resulting SPEC file.
57
+
58
+ While for simple packages and good configuration the package can
59
+ be used as it is, the weirder package is the higher are chances
60
+ you'll have to hand-edit it.
61
+
62
+ =head1 EXAMPLES
63
+
64
+ =over 4
65
+
66
+ =item C<npm2rpm jsdom>
67
+
68
+ Well, nothing particularly sophisticated.
69
+
70
+ =back
71
+
72
+ =head1 SEE ALSO
73
+
74
+ L<cpanspec>, L<https://fedoraproject.org/wiki/User:Lkundrak/NodeJS>
75
+
76
+
77
+ =cut
@@ -0,0 +1,23 @@
1
+ module Npm2Rpm
2
+
3
+ class Changes
4
+ def initialize name, metadata, options
5
+ @name = name
6
+ @metadata = metadata
7
+ @options = options
8
+ end
9
+ def write
10
+ # create .changes file as
11
+ # -------------------------------------------------------------------
12
+ # Sat Oct 5 12:29:03 UTC 2013 - kkaempf@suse.com
13
+
14
+ File.open("#{@name}.changes", "w+") do |f|
15
+ f.puts "-------------------------------------------------------------------"
16
+ f.puts "#{@options.date} - #{@options.email}@suse.com"
17
+ f.puts
18
+ f.puts "- Initial version #{@metadata.version}"
19
+ end
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,47 @@
1
+ #
2
+ # npm2rpm/lib/download.rb
3
+ #
4
+ # Implements http(s) download
5
+ #
6
+
7
+ require 'openssl'
8
+ require 'net/https'
9
+ require 'net/http'
10
+
11
+ module Npm2Rpm
12
+ class Download
13
+ attr_reader :content
14
+ # get url to local file, return local file name
15
+ def initialize url
16
+ puts "Download #{url.inspect}"
17
+ @uri = URI url
18
+ http = Net::HTTP.new(@uri.host, @uri.port)
19
+ if @uri.scheme == "https"
20
+ http.use_ssl = true
21
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
22
+
23
+ store = OpenSSL::X509::Store.new
24
+ store.set_default_paths # Optional method that will auto-include the system CAs.
25
+ crtpath = File.expand_path(File.join(File.dirname(__FILE__), "..", "registry.npmjs.org.crt"))
26
+ store.add_file(crtpath)
27
+ http.cert_store = store
28
+ end
29
+ response = http.request(Net::HTTP::Get.new(@uri.request_uri))
30
+ case response.code.to_i
31
+ when 200
32
+ when 404
33
+ abort "No such NPM module #{url}"
34
+ else
35
+ abort "HTTP error #{response.code.inspect}"
36
+ end
37
+ @content = response.body
38
+ end
39
+ def save
40
+ File.open(self.filename, "w+") { |f| f.write @content }
41
+ self
42
+ end
43
+ def filename
44
+ @filename ||= File.basename(@uri.path)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,164 @@
1
+ #
2
+ # npm2rpm/lib/metadata.rb
3
+ #
4
+ # Implements access to npmjs.org module metadata
5
+ #
6
+
7
+
8
+ # Metadata represents npmjs.org metadata
9
+ # {
10
+ # "_id": "grunt-contrib-jshint",
11
+ # "_rev": "50-de057965aacb5d6a72a6b06df06af685",
12
+ # "name": "grunt-contrib-jshint",
13
+ # "description": "Validate files with JSHint.",
14
+ # "dist-tags": {
15
+ # "latest": "0.6.4"
16
+ # },
17
+ # "readme": "# grunt-contrib-jshint [![Build Status](https://secure.travis-ci.org/gruntjs/grunt-contrib-jshint.png?branch=master)](http://travis-ci.org/gruntjs/grunt-contrib-jshint)\n\n> Validate files with JSHint.\n\n_Note that this plugin has not yet been released, and only works with the latest bleeding-edge, in-development version of grunt. See the [When will I be able to use in-development feature 'X'?](https://github.com/gruntjs/grunt/blob/devel/docs/faq.md#when-will-i-be-able-to-use-in-development-feature-x) FAQ entry for more information._\n\n## Getting Started\nIf you haven't used [grunt][] before, be sure to check out the [Getting Started][] guide, as it explains how to create a [gruntfile][Getting Started] as well as install and use grunt plugins. Once you're familiar with that process, install this plugin with this command:\n\n`shell\nnpm install grunt-contrib-jshint --save-dev\n`\n\n[grunt]: http://gruntjs.com/\n[Getting Started]: https://github.com/gruntjs/grunt/blob/devel/docs/getting_started.md\n\n\n## Jshint task\n_Run this task with the grunt jshint command._\n\n_This task is a [multi task][] so any targets, files and options should be specified according to the [multi task][] documentation._\n[multi task]: https://github.com/gruntjs/grunt/wiki/Configuring-tasks\n\n\n### Options\n\nAny specified option will be passed through directly to [JSHint][], thus you can specify any option that JSHint supports. See the [JSHint documentation][] for a list of supported options.\n\n[JSHint]: http://www.jshint.com/\n[JSHint documentation]: http://www.jshint.com/docs/\n\nA few additional options are supported:\n\n#### globals\nType: Object\nDefault value: null\n\nA map of global variables, with keys as names and a boolean value to determine if they are assignable. This is not a standard JSHint option, but is passed into the JSHINT function as its third argument. See the [JSHint documentation][] for more information.\n\n#### jshintrc\nType: String\nDefault value: null\n\nIf this filename is specified, options and globals defined therein will be used. The jshintrc file must be valid JSON and looks something like this:\n\n`json\n{\n \"curly\": true,\n \"eqnull\": true,\n \"eqeqeq\": true,\n \"undef\": true,\n \"globals\": {\n \"jQuery\": true\n }\n}\n`\n\n### Usage examples\n\n#### Wildcards\nIn this example, running grunt jshint:all (or grunt jshint because jshint is a [multi task][]) will lint the project's Gruntfile as well as all JavaScript files in the lib and test directories and their subdirectores, using the default JSHint options.\n\n`js\n// Project configuration.\ngrunt.initConfig({\n jshint: {\n all: ['Gruntfile.js', 'lib/**/*.js', 'test/**/*.js']\n }\n});\n`\n\n#### Linting before and after concatenating\nIn this example, running grunt jshint will lint both the \"beforeconcat\" set and \"afterconcat\" sets of files. This is not ideal, because dist/output.js may get linted before it gets created via the [grunt-contrib-concat plugin](https://github.com/gruntjs/grunt-contrib-concat) concat task.\n\nIn this case, you should lint the \"beforeconcat\" files first, then concat, then lint the \"afterconcat\" files, by running grunt jshint:beforeconcat concat jshint:afterconcat.\n\n`js\n// Project configuration.\ngrunt.initConfig({\n concat: {\n dist: {\n src: ['src/foo.js', 'src/bar.js'],\n dest: 'dist/output.js'\n }\n },\n jshint: {\n beforeconcat: ['src/foo.js', 'src/bar.js'],\n afterconcat: ['dist/output.js']\n }\n});\n`\n\n#### Specifying JSHint options and globals\n\nIn this example, custom JSHint options are specified. Note that when grunt jshint:uses_defaults is run, those files are linted using the default options, but when grunt jshint:with_overrides is run, those files are linted using _merged_ task/target options.\n\n`js\n// Project configuration.\ngrunt.initConfig({\n jshint: {\n options: {\n curly: true,\n eqeqeq: true,\n eqnull: true,\n browser: true,\n globals: {\n jQuery: true\n },\n },\n uses_defaults: ['dir1/**/*.js', 'dir2/**/*.js'],\n with_overrides: {\n options: {\n curly: false,\n undef: true,\n },\n files: {\n src: ['dir3/**/*.js', 'dir4/**/*.js']\n },\n }\n },\n});\n`\n\n\n## Release History\n\n * 2012-10-17   v0.1.0   Work in progress, not yet officially released.\n\n---\n\nTask submitted by [\"Cowboy\" Ben Alman](http://benalman.com/)\n\n*This file was generated on Wed Nov 28 2012 08:49:23.*\n",
18
+ # "maintainers": [
19
+ # {
20
+ # "name": "cowboy",
21
+ # "email": "cowboy@rj3.net"
22
+ # },
23
+ # ...
24
+ # ],
25
+ # "time": {
26
+ # "0.1.0": "2013-01-08T18:41:18.246Z",
27
+ # ...
28
+ # },
29
+ # "author": {
30
+ # "name": "Grunt Team",
31
+ # "url": "http://gruntjs.com/"
32
+ # },
33
+ # "repository": {
34
+ # "type": "git",
35
+ # "url": "git://github.com/gruntjs/grunt-contrib-jshint.git"
36
+ # },
37
+ # "users": {
38
+ # "paazmaya": true,
39
+ # ...
40
+ # },
41
+ # "_attachments": {
42
+ # "grunt-contrib-jshint-0.6.4.tgz": {
43
+ # "content_type": "application/octet-stream",
44
+ # "revpos": 48,
45
+ # "digest": "md5-LEuyQStwm+KcTmtVkwapDQ==",
46
+ # "length": 9834,
47
+ # "stub": true
48
+ # },
49
+ # ...
50
+ # },
51
+ # "versions": {
52
+ #
53
+ # == Versions
54
+ # "0.1.0": {
55
+ # "name": "grunt-contrib-jshint",
56
+ # "description": "Validate files with JSHint.",
57
+ # "version": "0.1.0",
58
+ # "homepage": "https://github.com/gruntjs/grunt-contrib-jshint",
59
+ # "author": {
60
+ # "name": "\"Cowboy\" Ben Alman",
61
+ # "email": "cowboy@rj3.net",
62
+ # "url": "http://gruntjs.com/"
63
+ # },
64
+ # "repository": {
65
+ # "type": "git",
66
+ # "url": "git://github.com/gruntjs/grunt-contrib-jshint.git"
67
+ # },
68
+ # "bugs": {
69
+ # "url": "https://github.com/gruntjs/grunt-contrib-jshint/issues"
70
+ # },
71
+ # "licenses": [
72
+ # {
73
+ # "type": "MIT",
74
+ # "url": "https://github.com/gruntjs/grunt-contrib-jshint/blob/master/LICENSE-MIT"
75
+ # }
76
+ # ],
77
+ # "main": "Gruntfile.js",
78
+ # "engines": {
79
+ # "node": ">= 0.8.0"
80
+ # },
81
+ # "dependencies": {
82
+ # "jshint": "~0.9.0"
83
+ # },
84
+ # "devDependencies": {
85
+ # "grunt-contrib-nodeunit": "~0.1.0",
86
+ # "grunt-contrib-internal": "~0.1.0",
87
+ # "grunt": "~0.4.0"
88
+ # },
89
+ # "keywords": [],
90
+ # "contributors": [
91
+ # {
92
+ # "name": "\"Cowboy\" Ben Alman",
93
+ # "url": "http://benalman.com/"
94
+ # },
95
+ # {
96
+ # "name": "Tyler Kellen",
97
+ # "url": "http://goingslowly.com/"
98
+ # }
99
+ # ],
100
+ # "readme": "# grunt-contrib-jshint [![Build Status](https://secure.travis-ci.org/gruntjs/grunt-contrib-jshint.png?branch=master)](http://travis-ci.org/gruntjs/grunt-contrib-jshint)\n\n> Validate files with JSHint.\n\n_Note that this plugin has not yet been released, and only works with the latest bleeding-edge, in-development version of grunt. See the [When will I be able to use in-development feature 'X'?](https://github.com/gruntjs/grunt/blob/devel/docs/faq.md#when-will-i-be-able-to-use-in-development-feature-x) FAQ entry for more information._\n\n## Getting Started\nIf you haven't used [grunt][] before, be sure to check out the [Getting Started][] guide, as it explains how to create a [gruntfile][Getting Started] as well as install and use grunt plugins. Once you're familiar with that process, install this plugin with this command:\n\n`shell\nnpm install grunt-contrib-jshint --save-dev\n`\n\n[grunt]: http://gruntjs.com/\n[Getting Started]: https://github.com/gruntjs/grunt/blob/devel/docs/getting_started.md\n\n\n## Jshint task\n_Run this task with the grunt jshint command._\n\n_This task is a [multi task][] so any targets, files and options should be specified according to the [multi task][] documentation._\n[multi task]: https://github.com/gruntjs/grunt/wiki/Configuring-tasks\n\n\n### Options\n\nAny specified option will be passed through directly to [JSHint][], thus you can specify any option that JSHint supports. See the [JSHint documentation][] for a list of supported options.\n\n[JSHint]: http://www.jshint.com/\n[JSHint documentation]: http://www.jshint.com/docs/\n\nA few additional options are supported:\n\n#### globals\nType: Object\nDefault value: null\n\nA map of global variables, with keys as names and a boolean value to determine if they are assignable. This is not a standard JSHint option, but is passed into the JSHINT function as its third argument. See the [JSHint documentation][] for more information.\n\n#### jshintrc\nType: String\nDefault value: null\n\nIf this filename is specified, options and globals defined therein will be used. The jshintrc file must be valid JSON and looks something like this:\n\n`json\n{\n \"curly\": true,\n \"eqnull\": true,\n \"eqeqeq\": true,\n \"undef\": true,\n \"globals\": {\n \"jQuery\": true\n }\n}\n`\n\n### Usage examples\n\n#### Wildcards\nIn this example, running grunt jshint:all (or grunt jshint because jshint is a [multi task][]) will lint the project's Gruntfile as well as all JavaScript files in the lib and test directories and their subdirectores, using the default JSHint options.\n\n`js\n// Project configuration.\ngrunt.initConfig({\n jshint: {\n all: ['Gruntfile.js', 'lib/**/*.js', 'test/**/*.js']\n }\n});\n`\n\n#### Linting before and after concatenating\nIn this example, running grunt jshint will lint both the \"beforeconcat\" set and \"afterconcat\" sets of files. This is not ideal, because dist/output.js may get linted before it gets created via the [grunt-contrib-concat plugin](https://github.com/gruntjs/grunt-contrib-concat) concat task.\n\nIn this case, you should lint the \"beforeconcat\" files first, then concat, then lint the \"afterconcat\" files, by running grunt jshint:beforeconcat concat jshint:afterconcat.\n\n`js\n// Project configuration.\ngrunt.initConfig({\n concat: {\n dist: {\n src: ['src/foo.js', 'src/bar.js'],\n dest: 'dist/output.js'\n }\n },\n jshint: {\n beforeconcat: ['src/foo.js', 'src/bar.js'],\n afterconcat: ['dist/output.js']\n }\n});\n`\n\n#### Specifying JSHint options and globals\n\nIn this example, custom JSHint options are specified. Note that when grunt jshint:uses_defaults is run, those files are linted using the default options, but when grunt jshint:with_overrides is run, those files are linted using _merged_ task/target options.\n\n`js\n// Project configuration.\ngrunt.initConfig({\n jshint: {\n options: {\n curly: true,\n eqeqeq: true,\n eqnull: true,\n browser: true,\n globals: {\n jQuery: true\n },\n },\n uses_defaults: ['dir1/**/*.js', 'dir2/**/*.js'],\n with_overrides: {\n options: {\n curly: false,\n undef: true,\n },\n files: {\n src: ['dir3/**/*.js', 'dir4/**/*.js']\n },\n }\n },\n});\n`\n\n\n## Release History\n\n * 2012-10-17   v0.1.0   Work in progress, not yet officially released.\n\n---\n\nTask submitted by [\"Cowboy\" Ben Alman](http://benalman.com/)\n\n*This file was generated on Wed Nov 28 2012 08:49:23.*\n",
101
+ # "_id": "grunt-contrib-jshint@0.1.0",
102
+ # "dist": {
103
+ # "shasum": "d2a2ab3495dae72f1d2b10d67ade598e3f66ddd8",
104
+ # "tarball": "http://registry.npmjs.org/grunt-contrib-jshint/-/grunt-contrib-jshint-0.1.0.tgz"
105
+ # },
106
+ # "_npmVersion": "1.1.62",
107
+ # "_npmUser": {
108
+ # "name": "cowboy",
109
+ # "email": "cowboy@rj3.net"
110
+ # },
111
+ # "maintainers": [
112
+ # {
113
+ # "name": "cowboy",
114
+ # "email": "cowboy@rj3.net"
115
+ # }
116
+ # ],
117
+ # "directories": {}
118
+ # },
119
+ #
120
+
121
+ require 'json'
122
+
123
+ module Npm2Rpm
124
+
125
+ class Metadata
126
+ # npmdata is version-specific information
127
+ attr_reader :name, :version, :npmdata
128
+ def initialize name, version = nil
129
+ # Get details from central NPM repository
130
+ # FIXME: Server returns... not quite JSON.
131
+ @metaurl = "https://registry.npmjs.org/#{name}"
132
+
133
+ json = Download.new(@metaurl).content
134
+ # $metadata_json =~ s/\b([^"':\s]+)(:\s+)/"$1"$2/gm;
135
+ # $metadata_json =~ s/'/"/gm;
136
+ @metadata = JSON.parse json
137
+ @version = version || @metadata["dist-tags"]["latest"] || abort("Can't determine version")
138
+ puts "#{name}-#{@version}"
139
+ @npmdata = @metadata["versions"][@version] || abort("No such version: #{@version.inspect}")
140
+ @name = @metadata["name"]
141
+ abort("Name mismatch, want #{name.inspect}, got #{@name.inspect}") unless name == @name
142
+ end
143
+
144
+ def tarball
145
+ url = @npmdata["dist"]["tarball"]
146
+ end
147
+
148
+ def method_missing name, *args
149
+ result = @metadata[name.to_s]
150
+ while args
151
+ s = args.shift
152
+ case result
153
+ when Hash
154
+ result = result[s.to_s]
155
+ else
156
+ result = nil
157
+ break
158
+ end
159
+ end
160
+ result
161
+ end
162
+ end
163
+
164
+ end
@@ -0,0 +1,77 @@
1
+ #
2
+ # npm2rpm/lib/options.rb
3
+ #
4
+ # Extract ARGV options
5
+ #
6
+
7
+ require 'getoptlong'
8
+
9
+ module Npm2Rpm
10
+ class Options
11
+ attr_reader :package, :version, :date, :email, :user
12
+
13
+ def initialize
14
+ # .changes format
15
+ @date = `date -u +'%a %b %d %T UTC %Y'`
16
+ @date.chomp!
17
+
18
+ @email = ENV["USER"]
19
+ @user = `getent passwd $email`.split(':')[4]
20
+ @package = nil
21
+
22
+ # Parse command line options
23
+ GetoptLong.new(
24
+ [ '-h', '--help', GetoptLong::NO_ARGUMENT ],
25
+ [ '-H', '--man', GetoptLong::NO_ARGUMENT ],
26
+ [ '--specdir', GetoptLong::REQUIRED_ARGUMENT ],
27
+ [ '--sourcedir', GetoptLong::REQUIRED_ARGUMENT ],
28
+ [ '--user', GetoptLong::REQUIRED_ARGUMENT ],
29
+ [ '--email', GetoptLong::REQUIRED_ARGUMENT ],
30
+ [ '--date', GetoptLong::REQUIRED_ARGUMENT ],
31
+ [ '--package', GetoptLong::REQUIRED_ARGUMENT ]
32
+ ).each do |opt, arg|
33
+ case opt
34
+ when '--specdir'
35
+ @specdir = arg
36
+ when '--sourcedir'
37
+ @sourcedir = arg
38
+ when '--user'
39
+ @user = arg
40
+ when '--email'
41
+ @email = arg
42
+ when '--date'
43
+ @date = arg
44
+ when '--package'
45
+ self.package = arg
46
+ else
47
+ "Run $0 -h or $0 -H for details on usage";
48
+ end
49
+ end
50
+ unless ARGV.empty?
51
+ if @package
52
+ abort "Extra arguments: #{ARGV}"
53
+ end
54
+ self.package = ARGV.shift
55
+ end
56
+
57
+ abort 'Missing package argument' unless @package;
58
+ abort "Extra arguments: #{ARGV}" unless ARGV.empty?;
59
+
60
+ end
61
+
62
+ def package= name
63
+ @package, @version = name.split "@"
64
+ case @version.split(".").size
65
+ when 1
66
+ @version << ".0.0"
67
+ when 2
68
+ @version << ".0"
69
+ when 3
70
+ # ok
71
+ else
72
+ raise "Not a semantic version #{@version.inspect}"
73
+ end if @version
74
+ end
75
+ end
76
+
77
+ end
@@ -0,0 +1,27 @@
1
+ module Npm2Rpm
2
+
3
+ class Rpmlintrc
4
+ def initialize name, metadata, options
5
+ @name = name
6
+ @metadata = metadata
7
+ @options = options
8
+ end
9
+
10
+ def write
11
+ File.open("#{@name}-rpmlintrc", "w+") do |f|
12
+ f.puts "addFilter(\"devel-file-in-non-devel-package .*\")"
13
+ f.puts "addFilter(\"file-contains-buildroot .*\")"
14
+ f.puts "addFilter(\"file-contains-date-and-time .*\")"
15
+ f.puts "addFilter(\"hidden-file-or-dir .*\")"
16
+ f.puts "addFilter(\"incorrect-fsf-address .*\")"
17
+ f.puts "addFilter(\"non-executable-script .*\")"
18
+ f.puts "addFilter(\"backup-file-in-package .*\")"
19
+ f.puts "addFilter(\"suse-filelist-forbidden-backup-file .*\")"
20
+ f.puts "addFilter(\"suse-filelist-forbidden .*\")"
21
+ f.puts "addFilter(\"summary-ended-with-dot .*\")"
22
+ # f.puts "addFilter(\" .*\")"
23
+ end
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,119 @@
1
+ #
2
+ # lib/npm2rpm/spec.rb
3
+ #
4
+ # Container for .spec related information
5
+ #
6
+
7
+ module Npm2Rpm
8
+ class Spec
9
+ attr_reader :name
10
+ private
11
+ # Convert Hash of npmjs dependencies to Array of RPM requires
12
+ # input:
13
+ # { "grunt-contrib-nodeunit": "~0.1.0", "grunt-contrib-internal": "~0.1.0", "grunt": "~0.4.0" }
14
+ # output
15
+ # [ "npm(grunt-contrib-nodeunit@0.1.0", npm(grunt-contrib-internal@0.1.0), "npm(grunt@0.4.0) }
16
+ def dependencies deps
17
+ result = Array.new
18
+ deps ||= Hash.new
19
+ deps.each do |name, version|
20
+ case version
21
+ # "~1.2.3"
22
+ when /^~?([\d\.]+)(-\d)?([a-z]+)?$/
23
+ result << "npm(#{name}@#{$1})"
24
+ # "1.2.0-1.2.3"
25
+ when /^([\d\.]+)-([\d\.]+)$/
26
+ result << "npm(#{name}@#{$2})"
27
+ # "1.2.x", "=0.7.x"
28
+ when /^~?<?>?=?([^xY]+)(\.[xX])(.*)$/
29
+ result << "npm(#{name}) > #{$1}"
30
+ # ">= 1.0.0 < 1.2.0"
31
+ when /^\>=?\s*([\d\.]+)(\s+\<\s*([\d\.]+))?$/
32
+ result << "npm(#{name}) >= #{$1}"
33
+ result << "npm(#{name}) < #{$3}" if $2
34
+ # "*"
35
+ # ""
36
+ when "*", ""
37
+ result << "npm(#{name})"
38
+ when /\w+/
39
+ result << "npm(#{name}@#{version})"
40
+ else
41
+ raise "Unrecognized dependency #{name.inspect}: #{version.inspect}"
42
+ end
43
+ end
44
+ result
45
+ end
46
+ public
47
+ def initialize metadata
48
+ @metadata = metadata
49
+ @name = "nodejs-#{@metadata.name}_#{@metadata.version}"
50
+ end
51
+
52
+ def npmname
53
+ @metadata.name
54
+ end
55
+ def version
56
+ @metadata.version
57
+ end
58
+ def licenses
59
+ [ @metadata.license.nil? ? "Unknown" : @metadata.license ]
60
+ end
61
+ def summary
62
+ @metadata.npmdata["description"]
63
+ end
64
+ def description
65
+ @metadata.npmdata["description"]
66
+ end
67
+ def homepage
68
+ @metadata.npmdata["homepage"] || @metadata.tarball || abort('FIXME: No homepage found')
69
+ end
70
+
71
+ def source
72
+ @metadata.tarball
73
+ end
74
+ def dir
75
+ # Find out the top-level directory from tarball
76
+ # The upstreams often use very weird ones
77
+ `tar tzf #{@local_source}` =~ /([^\/]+)/
78
+ $1
79
+ end
80
+ def binfiles
81
+ @metadata.npmdata["bin"]
82
+ end
83
+ def provides
84
+ prv = Array.new
85
+ prv << "npm(#{self.npmname}) = %{version}"
86
+ v = self.version.split "."
87
+ until v.empty? do
88
+ prv << "npm(#{self.npmname}@#{v.join('.')})"
89
+ v.pop
90
+ end
91
+ prv
92
+ end
93
+ def requires
94
+ req = dependencies(@metadata.npmdata["dependencies"])
95
+ req += dependencies(@metadata.npmdata["peerDependencies"])
96
+ req
97
+ end
98
+ def build_requires
99
+ dependencies @metadata.npmdata["devDependencies"]
100
+ end
101
+
102
+ def write
103
+ url = @metadata.tarball
104
+ @local_source = Download.new(url).save.filename
105
+
106
+ require 'erb'
107
+
108
+ template_name = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "templates", "nodejs-opensuse.spec.erb"))
109
+ template = File.read(template_name)
110
+ # -: omit blank lines ending in -%>
111
+ erb = ERB.new(template, nil, "-")
112
+ File.open("#{@name}.spec", "w+") do |f|
113
+ spec = self
114
+ f.puts erb.result
115
+ end
116
+ end
117
+ end
118
+
119
+ end
@@ -0,0 +1,6 @@
1
+ #
2
+ # npm2rpm/lib/npm2rpm/version.rb
3
+ #
4
+ module Npm2Rpm
5
+ VERSION = "0.1.0"
6
+ end
data/lib/npm2rpm.rb ADDED
@@ -0,0 +1,9 @@
1
+ module Npm2Rpm
2
+ require 'npm2rpm/changes'
3
+ require 'npm2rpm/download'
4
+ require 'npm2rpm/metadata'
5
+ require 'npm2rpm/options'
6
+ require 'npm2rpm/rpmlintrc'
7
+ require 'npm2rpm/spec'
8
+ require 'npm2rpm/version'
9
+ end
@@ -0,0 +1,16 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIChzCCAfACCQDauvz/KHp8ejANBgkqhkiG9w0BAQUFADCBhzELMAkGA1UEBhMC
3
+ VVMxCzAJBgNVBAgTAkNBMRAwDgYDVQQHEwdPYWtsYW5kMQwwCgYDVQQKEwNucG0x
4
+ IjAgBgNVBAsTGW5wbSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxDjAMBgNVBAMTBW5w
5
+ bUNBMRcwFQYJKoZIhvcNAQkBFghpQGl6cy5tZTAeFw0xMTA5MDUwMTQ3MTdaFw0y
6
+ MTA5MDIwMTQ3MTdaMIGHMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEDAOBgNV
7
+ BAcTB09ha2xhbmQxDDAKBgNVBAoTA25wbTEiMCAGA1UECxMZbnBtIENlcnRpZmlj
8
+ YXRlIEF1dGhvcml0eTEOMAwGA1UEAxMFbnBtQ0ExFzAVBgkqhkiG9w0BCQEWCGlA
9
+ aXpzLm1lMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLI4tIqPpRW+ACw9GE
10
+ OgBlJZwK5f8nnKCLK629Pv5yJpQKs3DENExAyOgDcyaF0HD0zk8zTp+ZsLaNdKOz
11
+ Gn2U181KGprGKAXP6DU6ByOJDWmTlY6+Ad1laYT0m64fERSpHw/hjD3D+iX4aMOl
12
+ y0HdbT5m1ZGh6SJz3ZqxavhHLQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAC4ySDbC
13
+ l7W1WpLmtLGEQ/yuMLUf6Jy/vr+CRp4h+UzL+IQpCv8FfxsYE7dhf/bmWTEupBkv
14
+ yNL18lipt2jSvR3v6oAHAReotvdjqhxddpe5Holns6EQd1/xEZ7sB1YhQKJtvUrl
15
+ ZNufy1Jf1r0ldEGeA+0ISck7s+xSh9rQD2Op
16
+ -----END CERTIFICATE-----
data/npm2rpm.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "npm2rpm/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "npm2rpm"
7
+ s.version = Npm2Rpm::VERSION
8
+
9
+ s.platform = Gem::Platform::RUBY
10
+ s.authors = ["Klaus Kämpf"]
11
+ s.email = ["kkaempf@suse.de"]
12
+ s.homepage = "https://github.com/kkaempf/npm2rpm"
13
+ s.summary = %q{Generate RPM packages for Nodejs modules}
14
+ s.description = %q{Automatically generates RPM packages for Nodejs modules}
15
+
16
+ s.rubyforge_project = "npm2rpm"
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.files.reject! { |fn| fn == '.gitignore' }
20
+ s.extra_rdoc_files = Dir['README.md', 'LICENSE']
21
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
+ s.require_paths = ["lib"]
23
+ end
@@ -0,0 +1,140 @@
1
+ #
2
+ # spec file for package <%= spec.name %>
3
+ #
4
+ # *** Generated with https://github.com/kkaempf/npm2rpm ***
5
+ #
6
+ # Copyright (c) <%= Time.now.year %> SUSE LINUX Products GmbH, Nuernberg, Germany.
7
+ #
8
+ # All modifications and additions to the file contributed by third parties
9
+ # remain the property of their copyright owners, unless otherwise agreed
10
+ # upon. The license for this file, and modifications and additions to the
11
+ # file, is the same license as for the pristine package itself (unless the
12
+ # license for the pristine package is not an Open Source License, in which
13
+ # case the license is the MIT License). An "Open Source License" is a
14
+ # license that conforms to the Open Source Definition (Version 1.9)
15
+ # published by the Open Source Initiative.
16
+
17
+ # Please submit bugfixes or comments via http://bugs.opensuse.org/
18
+ #
19
+
20
+ %global npmname <%= spec.npmname %>
21
+
22
+ %global _use_internal_dependency_generator 0
23
+ %global __find_provides /bin/sh -c 'sed -n "s,.*/\\.npm/\\([^\\/]*\\)\\/\\([^/]*\\.[^/]*\\)/.*,nodejs(\\1) = \\2,p" |sort |uniq'
24
+ %global __find_requires /bin/sh -c 'sed -n "s,.*/dependson/\\([^@\\/]*\\)@\\([^@/]\\.[^@/]*\\)\$,nodejs(\\1) = \\2,p" |sort |uniq'
25
+
26
+ Name: <%= spec.name %>
27
+ Version: <%= spec.version %>
28
+ Release: 0
29
+
30
+ %if 0%{?suse_version}
31
+ Group: Development/Libraries/Other
32
+ %else
33
+ Group: Development/Libraries
34
+ %endif
35
+
36
+ <% unless spec.homepage.nil? || spec.homepage.empty? -%>
37
+ Url: <%= spec.homepage %>
38
+ <% end -%>
39
+ Source0: <%= spec.source %>
40
+ Summary: <%= spec.summary %>
41
+ <% unless spec.licenses.empty? -%>
42
+ License: <%= spec.licenses.join(" and ") %>
43
+ <% else -%>
44
+ License: CHECK(Nodejs)
45
+ <% end -%>
46
+
47
+ BuildRoot: %{_tmppath}/%{name}-%{version}-build
48
+
49
+ <% spec.provides.each do |d| -%>
50
+ Provides: <%= d %>
51
+ <% end -%>
52
+
53
+ BuildRequires: nodejs-npm
54
+ BuildRequires: gcc
55
+ BuildRequires: gcc-c++
56
+
57
+ Requires: nodejs-npm
58
+
59
+ %if 0%{?suse_version} > 1110
60
+ BuildRequires: fdupes
61
+ %endif
62
+
63
+ <% spec.build_requires.uniq.sort.each do |d| -%>
64
+ # cyclic? BuildRequires: <%= d %>
65
+ <% end -%>
66
+
67
+ <% spec.requires.uniq.sort.each do |d| -%>
68
+ BuildRequires: <%= d %>
69
+ <% end -%>
70
+
71
+ <% spec.requires.uniq.sort.each do |d| -%>
72
+ Requires: <%= d %>
73
+ <% end -%>
74
+
75
+ %description
76
+ <%= spec.description %>
77
+
78
+ %prep
79
+ %setup -q -n <%= spec.dir %>
80
+
81
+ %build
82
+ %if 0%{?suse_version} == 0
83
+ mkdir -p .%{_prefix}/lib/node/.npm
84
+ cp -a %{_prefix}/lib/node/.npm/* \
85
+ .%{_prefix}/lib/node/.npm
86
+
87
+ npm_config_root=.%{_prefix}/lib/node \
88
+ npm_config_binroot=.%{_bindir} \
89
+ npm_config_manroot=.%{_mandir} \
90
+ npm install %{SOURCE0}
91
+ %endif
92
+
93
+ %install
94
+ rm -rf $RPM_BUILD_ROOT
95
+
96
+ %if 0%{?suse_version}
97
+ mkdir -p %{buildroot}%{_libdir}/node_modules
98
+ npm_config_prefix=%{buildroot}%{_prefix} \
99
+ npm_config_binroot=%{buildroot}%{_bindir} \
100
+ npm_config_manroot=%{buildroot}%{_mandir} \
101
+ npm install --global --production %{S:0}
102
+
103
+ %if %{_lib} != lib
104
+ mv %{buildroot}%{_prefix}/lib/node_modules/%{npmname} %{buildroot}%{_libdir}/node_modules
105
+ %endif
106
+ rm -rf %{buildroot}%{_prefix}/lib
107
+
108
+ <% (spec.binfiles||{}).each do |name, target| -%>
109
+ rm -f %{buildroot}%{_bindir}/<%= name %>
110
+ ln -sf %{_libdir}/node_modules/%{npmname}/<%= target -%> %{buildroot}%{_bindir}/<%= name %>
111
+ <% end -%>
112
+ %else
113
+ mkdir -p $RPM_BUILD_ROOT%{_prefix}/lib/node/.npm/%{npmname}
114
+ cp -a $PWD%{_prefix}/lib/node/%{npmname}{,@%{version}} \
115
+ $RPM_BUILD_ROOT%{_prefix}/lib/node
116
+ cp -a $PWD%{_prefix}/lib/node/.npm/%{npmname}/{%{version},active} \
117
+ $RPM_BUILD_ROOT%{_prefix}/lib/node/.npm/%{npmname}
118
+ %endif
119
+
120
+ %if 0%{?suse_version} > 1110
121
+ %fdupes %{buildroot}
122
+ %endif
123
+
124
+ %clean
125
+ rm -rf $RPM_BUILD_ROOT
126
+
127
+
128
+ %files
129
+ %defattr(-,root,root,-)
130
+ %if 0%{?suse_version}
131
+ %{_libdir}/node_modules/%{npmname}
132
+ %else
133
+ %{_prefix}/lib/node/%{npmname}
134
+ %{_prefix}/lib/node/%{npmname}@%{version}
135
+ %{_prefix}/lib/node/.npm/%{npmname}
136
+ %endif
137
+ <% if spec.binfiles -%>
138
+ %{_bindir}/*
139
+ <% end %>
140
+ %changelog
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: npm2rpm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Klaus Kämpf
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-08 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Automatically generates RPM packages for Nodejs modules
14
+ email:
15
+ - kkaempf@suse.de
16
+ executables:
17
+ - npm2rpm
18
+ extensions: []
19
+ extra_rdoc_files:
20
+ - README.md
21
+ - LICENSE
22
+ files:
23
+ - Gemfile
24
+ - LICENSE
25
+ - README.md
26
+ - Rakefile
27
+ - bin/npm2rpm
28
+ - doc/options
29
+ - lib/npm2rpm.rb
30
+ - lib/npm2rpm/changes.rb
31
+ - lib/npm2rpm/download.rb
32
+ - lib/npm2rpm/metadata.rb
33
+ - lib/npm2rpm/options.rb
34
+ - lib/npm2rpm/rpmlintrc.rb
35
+ - lib/npm2rpm/spec.rb
36
+ - lib/npm2rpm/version.rb
37
+ - lib/registry.npmjs.org.crt
38
+ - npm2rpm.gemspec
39
+ - templates/nodejs-opensuse.spec.erb
40
+ homepage: https://github.com/kkaempf/npm2rpm
41
+ licenses: []
42
+ metadata: {}
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubyforge_project: npm2rpm
59
+ rubygems_version: 2.1.3
60
+ signing_key:
61
+ specification_version: 4
62
+ summary: Generate RPM packages for Nodejs modules
63
+ test_files: []
64
+ has_rdoc: