npm2rpm 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: