kcar 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -18,3 +18,5 @@ pkg/
18
18
  /man
19
19
  tags
20
20
  TAGS
21
+ /tmp
22
+ /LATEST
@@ -0,0 +1,4 @@
1
+ ---
2
+ cgit_url: http://bogomips.org/kcar.git
3
+ git_url: git://bogomips.org/kcar.git
4
+ rdoc_url: http://bogomips.org/kcar/
@@ -1,7 +1,7 @@
1
1
  #!/bin/sh
2
2
 
3
3
  GVF=GIT-VERSION-FILE
4
- DEF_VER=v0.1.2.GIT
4
+ DEF_VER=v0.2.0.GIT
5
5
 
6
6
  LF='
7
7
  '
@@ -1,198 +1,17 @@
1
- # use GNU Make to run tests in parallel, and without depending on RubyGems
2
1
  all::
3
- RUBY = ruby
4
- RAKE = rake
2
+ RSYNC_DEST := bogomips.org:/srv/bogomips/kcar
5
3
  RAGEL = ragel
6
- GIT_URL = git://git.bogomips.org/kcar.git
7
4
  RLFLAGS = -G2
8
- RSYNC = rsync
9
-
10
- GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
11
- @./GIT-VERSION-GEN
12
- -include GIT-VERSION-FILE
13
- -include local.mk
14
- ifeq ($(DLEXT),) # "so" for Linux
15
- DLEXT := $(shell $(RUBY) -rrbconfig -e 'puts Config::CONFIG["DLEXT"]')
16
- endif
17
- ifeq ($(RUBY_VERSION),)
18
- RUBY_VERSION := $(shell $(RUBY) -e 'puts RUBY_VERSION')
19
- endif
20
-
21
- install: $(bins)
22
- $(prep_setup_rb)
23
- $(RM) -r .install-tmp
24
- mkdir .install-tmp
25
- cp -p bin/* .install-tmp
26
- $(RUBY) setup.rb all
27
- $(RM) $^
28
- mv .install-tmp/* bin/
29
- $(RM) -r .install-tmp
30
- $(prep_setup_rb)
31
-
32
- setup_rb_files := .config InstalledFiles
33
- prep_setup_rb := @-$(RM) $(setup_rb_files);$(MAKE) -C $(ext) clean
34
-
35
- clean:
36
- -$(MAKE) -C ext/kcar clean
37
- $(RM) $(setup_rb_files) ext/kcar/Makefile
38
-
39
- pkg_extra := GIT-VERSION-FILE NEWS ChangeLog ext/kcar/kcar.c
40
- manifest: $(pkg_extra)
41
- $(RM) .manifest
42
- $(MAKE) .manifest
43
-
44
- .manifest:
45
- (git ls-files && \
46
- for i in $@ $(pkg_extra) $(man1_paths); \
47
- do echo $$i; done) | LC_ALL=C sort > $@+
48
- cmp $@+ $@ || mv $@+ $@
49
- $(RM) $@+
50
-
51
- NEWS: GIT-VERSION-FILE
52
- $(RAKE) -s news_rdoc > $@+
53
- mv $@+ $@
54
-
55
- latest: NEWS
56
- @awk 'BEGIN{RS="=== ";ORS=""}NR==2{sub(/\n$$/,"");print RS""$$0 }' $<
57
-
58
- SINCE = 0.1.0
59
- ChangeLog: LOG_VERSION = \
60
- $(shell git rev-parse -q "$(GIT_VERSION)" >/dev/null 2>&1 && \
61
- echo $(GIT_VERSION) || git describe)
62
- ifneq ($(SINCE),)
63
- ChangeLog: log_range = v$(SINCE)..$(LOG_VERSION)
64
- endif
65
- ChangeLog: GIT-VERSION-FILE
66
- @echo "ChangeLog from $(GIT_URL) ($(log_range))" > $@+
67
- @echo >> $@+
68
- git log $(log_range) | sed -e 's/^/ /' >> $@+
69
- mv $@+ $@
70
-
71
- news_atom := http://bogomips.org/kcar/NEWS.atom.xml
72
- cgit_atom := http://git.bogomips.org/cgit/kcar.git/atom/?h=master
73
- atom = <link rel="alternate" title="Atom feed" href="$(1)" \
74
- type="application/atom+xml"/>
75
-
76
- # using rdoc 2.5.x
77
- doc: .document NEWS ChangeLog
78
- rdoc -a -t "$(shell sed -ne '1s/^= //p' README)"
79
- install -m644 COPYING doc/COPYING
80
- install -m644 $(shell grep '^[A-Z]' .document) doc/
81
- $(RUBY) -i -p -e \
82
- '$$_.gsub!("</title>",%q{\&$(call atom,$(cgit_atom))})' \
83
- doc/ChangeLog.html
84
- $(RUBY) -i -p -e \
85
- '$$_.gsub!("</title>",%q{\&$(call atom,$(news_atom))})' \
86
- doc/NEWS.html doc/README.html
87
- $(RAKE) -s news_atom > doc/NEWS.atom.xml
88
- cd doc && ln README.html tmp && mv tmp index.html
89
-
90
- ifneq ($(VERSION),)
91
5
  rfproject := rainbows
92
6
  rfpackage := kcar
93
- pkggem := pkg/$(rfpackage)-$(VERSION).gem
94
- pkgtgz := pkg/$(rfpackage)-$(VERSION).tgz
95
- release_notes := release_notes-$(VERSION)
96
- release_changes := release_changes-$(VERSION)
97
-
98
- release-notes: $(release_notes)
99
- release-changes: $(release_changes)
100
- $(release_changes):
101
- $(RAKE) -s release_changes > $@+
102
- $(VISUAL) $@+ && test -s $@+ && mv $@+ $@
103
- $(release_notes):
104
- GIT_URL=$(GIT_URL) $(RAKE) -s release_notes > $@+
105
- $(VISUAL) $@+ && test -s $@+ && mv $@+ $@
106
-
107
- # ensures we're actually on the tagged $(VERSION), only used for release
108
- verify:
109
- test x"$(shell umask)" = x0022
110
- git rev-parse --verify refs/tags/v$(VERSION)^{}
111
- git diff-index --quiet HEAD^0
112
- test `git rev-parse --verify HEAD^0` = \
113
- `git rev-parse --verify refs/tags/v$(VERSION)^{}`
114
-
115
- fix-perms:
116
- -git ls-tree -r HEAD | awk '/^100644 / {print $$NF}' | xargs chmod 644
117
- -git ls-tree -r HEAD | awk '/^100755 / {print $$NF}' | xargs chmod 755
118
-
119
- gem: $(pkggem)
120
-
121
- install-gem: $(pkggem)
122
- gem install $(CURDIR)/$<
123
-
124
- $(pkggem): manifest fix-perms
125
- gem build $(rfpackage).gemspec
126
- mkdir -p pkg
127
- mv $(@F) $@
128
-
129
- $(pkgtgz): distdir = $(basename $@)
130
- $(pkgtgz): HEAD = v$(VERSION)
131
- $(pkgtgz): manifest fix-perms
132
- @test -n "$(distdir)"
133
- $(RM) -r $(distdir)
134
- mkdir -p $(distdir)
135
- tar c `cat .manifest` | (cd $(distdir) && tar x)
136
- cd pkg && tar c $(basename $(@F)) | gzip -9 > $(@F)+
137
- mv $@+ $@
138
-
139
- package: $(pkgtgz) $(pkggem)
140
-
141
- test-release: verify package $(release_notes) $(release_changes)
142
- release: verify package $(release_notes) $(release_changes)
143
- # make tgz release on RubyForge
144
- rubyforge add_release -f -n $(release_notes) -a $(release_changes) \
145
- $(rfproject) $(rfpackage) $(VERSION) $(pkgtgz)
146
- # push gem to Gemcutter
147
- gem push $(pkggem)
148
- # in case of gem downloads from RubyForge releases page
149
- -rubyforge add_file \
150
- $(rfproject) $(rfpackage) $(VERSION) $(pkggem)
151
- else
152
- gem install-gem: GIT-VERSION-FILE
153
- $(MAKE) $@ VERSION=$(GIT_VERSION)
154
- endif
155
-
156
- ext := ext/kcar/kcar_ext.$(DLEXT)
157
- hdr := $(wildcard $(addprefix ext/kcar/,*.h))
158
- ragel: $(ext)
159
- ext/kcar/Makefile: ext/kcar/extconf.rb
160
- cd $(@D) && $(RUBY) extconf.rb
161
-
7
+ pkg_extra += ext/kcar/kcar.c
162
8
  ext/kcar/kcar.c: ext/kcar/kcar.rl ext/kcar/kcar_http_common.rl
163
9
  cd $(@D) && $(RAGEL) kcar.rl -C $(RLFLAGS) -o $(@F)
164
-
165
- $(ext): ext/kcar/kcar.c $(hdr) ext/kcar/Makefile
166
- $(MAKE) -C $(@D)
167
-
168
- all:: test
169
-
170
- build: $(ext)
171
- test_units := $(wildcard test/test_*.rb)
172
- test: test-unit
173
- test-unit: $(test_units)
174
- $(test_units): build
175
- $(RUBY) -w -I lib:ext/kcar $@
176
-
177
- # this requires GNU coreutils variants
178
- publish_doc:
179
- -git set-file-times
180
- $(RM) -r doc ChangeLog NEWS
181
- $(MAKE) doc LOG_VERSION=$(shell git tag -l | tail -1)
182
- $(MAKE) -s latest > doc/LATEST
183
- find doc/images doc/js -type f | \
184
- TZ=UTC xargs touch -d '1970-01-01 00:00:00' doc/rdoc.css
185
- $(MAKE) doc_gz
186
- chmod 644 $$(find doc -type f)
187
- $(RSYNC) -av doc/ dcvr:/srv/bogomips/kcar/
188
- git ls-files | xargs touch
189
-
190
- # Create gzip variants of the same timestamp as the original so nginx
191
- # "gzip_static on" can serve the gzipped versions directly.
192
- doc_gz: docs = $(shell find doc -type f ! -regex '^.*\.\(gif\|jpg\|png\|gz\)$$')
193
- doc_gz:
194
- touch doc/NEWS.atom.xml -d "$$(awk 'NR==1{print $$4,$$5,$$6}' NEWS)"
195
- for i in $(docs); do \
196
- gzip --rsyncable -9 < $$i > $$i.gz; touch -r $$i $$i.gz; done
197
-
198
- .PHONY: .FORCE-GIT-VERSION-FILE doc manifest man test $(test_units)
10
+ include pkg.mk
11
+ $(ext_pfx)/$(ext)/kcar.c: ext/kcar/kcar.c
12
+ $(ext_pfx)/$(ext)/Makefile: ext/kcar/kcar.c
13
+ ifneq ($(VERSION),)
14
+ release::
15
+ $(RAKE) raa_update VERSION=$(VERSION)
16
+ $(RAKE) publish_news VERSION=$(VERSION)
17
+ endif
data/README CHANGED
@@ -5,8 +5,6 @@ kcar features an HTTP parser that will convert a bytestream into a
5
5
  agnostic, so it may be used with HTTP streams over Unix domain sockets,
6
6
  regular files, FIFOs, StringIOs as well as traditional TCP sockets.
7
7
 
8
- A drop-in, Net::HTTP-compatible interface is planned.
9
-
10
8
  == Features
11
9
 
12
10
  * RFC2616-compliant Ragel+C parser adapted from Unicorn and Mongrel
@@ -64,13 +62,13 @@ through the body with body.each.
64
62
 
65
63
  You can get the latest source via git from the following locations:
66
64
 
67
- git://git.bogomips.org/kcar.git
65
+ git://bogomips.org/kcar.git
68
66
  git://repo.or.cz/kcar.git (mirror)
69
67
 
70
68
  You may browse the code from the web and download the latest snapshot
71
69
  tarballs here:
72
70
 
73
- * http://git.bogomips.org/cgit/kcar.git (cgit)
71
+ * http://bogomips.org/cgit/kcar.git (cgit)
74
72
  * http://repo.or.cz/w/kcar.git (gitweb)
75
73
 
76
74
  Inline patches (from "git format-patch") to the mailing list are
data/Rakefile CHANGED
@@ -1,8 +1,26 @@
1
- desc "read news article from STDIN and post to rubyforge"
1
+ # -*- encoding: binary -*-
2
+ require 'wrongdoc'
3
+ cgit_url = Wrongdoc.config[:cgit_url]
4
+ git_url = Wrongdoc.config[:git_url]
5
+
6
+ desc "post news article to rubyforge"
2
7
  task :publish_news do
3
8
  require 'rubyforge'
4
- IO.select([STDIN], nil, nil, 1) or abort "E: news must be read from stdin"
5
- msg = STDIN.readlines
9
+ spec = Gem::Specification.load('kcar.gemspec')
10
+ tmp = Tempfile.new('rf-news')
11
+ _, subject, body = `git cat-file tag v#{spec.version}`.split(/\n\n/, 3)
12
+ tmp.puts subject
13
+ tmp.puts
14
+ tmp.puts spec.description.strip
15
+ tmp.puts ""
16
+ tmp.puts "* #{spec.homepage}"
17
+ tmp.puts "* #{spec.email}"
18
+ tmp.puts "* #{git_url}"
19
+ tmp.print "\nChanges:\n\n"
20
+ tmp.puts body
21
+ tmp.flush
22
+ system(ENV["VISUAL"], tmp.path) or abort "#{ENV["VISUAL"]} failed: #$?"
23
+ msg = File.readlines(tmp.path)
6
24
  subject = msg.shift
7
25
  blank = msg.shift
8
26
  blank == "\n" or abort "no newline after subject!"
@@ -14,105 +32,8 @@ task :publish_news do
14
32
  rf.post_news('rainbows', subject, body)
15
33
  end
16
34
 
17
- def tags
18
- timefmt = '%Y-%m-%dT%H:%M:%SZ'
19
- @tags ||= `git tag -l`.split(/\n/).map do |tag|
20
- next if tag == "v0.0.0"
21
- if %r{\Av[\d\.]+\z} =~ tag
22
- header, subject, body = `git cat-file tag #{tag}`.split(/\n\n/, 3)
23
- header = header.split(/\n/)
24
- tagger = header.grep(/\Atagger /).first
25
- body ||= "initial"
26
- {
27
- :time => Time.at(tagger.split(/ /)[-2].to_i).utc.strftime(timefmt),
28
- :tagger_name => %r{^tagger ([^<]+)}.match(tagger)[1],
29
- :tagger_email => %r{<([^>]+)>}.match(tagger)[1],
30
- :id => `git rev-parse refs/tags/#{tag}`.chomp!,
31
- :tag => tag,
32
- :subject => subject,
33
- :body => body,
34
- }
35
- end
36
- end.compact.sort { |a,b| b[:time] <=> a[:time] }
37
- end
38
-
39
- cgit_url = "http://git.bogomips.org/cgit/kcar.git"
40
- git_url = ENV['GIT_URL'] || 'git://git.bogomips.org/kcar.git'
41
-
42
- desc 'prints news as an Atom feed'
43
- task :news_atom do
44
- require 'nokogiri'
45
- new_tags = tags[0,10]
46
- puts(Nokogiri::XML::Builder.new do
47
- feed :xmlns => "http://www.w3.org/2005/Atom" do
48
- id! "http://kcar.rubyforge.org/NEWS.atom.xml"
49
- title "Kcar news"
50
- subtitle File.readlines("README").first
51
- link! :rel => 'alternate', :type => 'text/html',
52
- :href => 'http://bogomips.org/kcar/'
53
- updated( (new_tags.first[:time] rescue nil) || Time.now )
54
- new_tags.each do |tag|
55
- entry do
56
- title tag[:subject]
57
- updated tag[:time]
58
- published tag[:time]
59
- author {
60
- name tag[:tagger_name]
61
- email tag[:tagger_email]
62
- }
63
- url = "#{cgit_url}/tag/?id=#{tag[:tag]}"
64
- link! :rel => "alternate", :type => "text/html", :href =>url
65
- id! url
66
- content(:type => 'text') { tag[:body] }
67
- end
68
- end
69
- end
70
- end.to_xml)
71
- end
72
-
73
- desc 'prints RDoc-formatted news'
74
- task :news_rdoc do
75
- tags.each do |tag|
76
- time = tag[:time].tr!('T', ' ').gsub!(/:\d\dZ/, ' UTC')
77
- puts "=== #{tag[:tag].sub(/^v/, '')} / #{time}"
78
- puts ""
79
-
80
- body = tag[:body]
81
- puts tag[:body].gsub(/^/sm, " ").gsub(/[ \t]+$/sm, "")
82
- puts ""
83
- end
84
- end
85
-
86
- desc "print release changelog for Rubyforge"
87
- task :release_changes do
88
- version = ENV['VERSION'] or abort "VERSION= needed"
89
- version = "v#{version}"
90
- vtags = tags.map { |tag| tag[:tag] =~ /\Av/ and tag[:tag] }.sort
91
- prev = vtags[vtags.index(version) - 1]
92
- system('git', 'diff', '--stat', prev, version) or abort $?
93
- puts ""
94
- system('git', 'log', "#{prev}..#{version}") or abort $?
95
- end
96
-
97
- desc "print release notes for Rubyforge"
98
- task :release_notes do
99
- require 'rubygems'
100
-
101
- spec = Gem::Specification.load('kcar.gemspec')
102
- puts spec.description.strip
103
- puts ""
104
- puts "* #{spec.homepage}"
105
- puts "* #{spec.email}"
106
- puts "* #{git_url}"
107
-
108
- _, _, body = `git cat-file tag v#{spec.version}`.split(/\n\n/, 3)
109
- print "\nChanges:\n\n"
110
- puts body
111
- end
112
-
113
35
  desc "post to RAA"
114
36
  task :raa_update do
115
- require 'rubygems'
116
37
  require 'net/http'
117
38
  require 'net/netrc'
118
39
  rc = Net::Netrc.locate('kcar-raa') or abort "~/.netrc not found"
data/TODO CHANGED
@@ -1,6 +1,2 @@
1
1
  Patches to kcar@librelist.com (via git format-patch + git send-email) for
2
2
  these would be greatly appreciated
3
-
4
- * optional drop-in monkey patch for Net::HTTP
5
- * optional EventMachine support
6
- * optional Rev support
@@ -8,24 +8,17 @@
8
8
  #define RSTRING_LEN(s) (RSTRING(s)->len)
9
9
  #endif /* !defined(RSTRING_LEN) */
10
10
 
11
- #ifndef RUBINIUS
12
- # define rb_str_update(x) do {} while (0)
13
- # define rb_str_flush(x) do {} while (0)
14
- #endif /* !RUBINIUS */
15
-
16
11
  #ifndef HAVE_RB_STR_SET_LEN
17
12
  # ifdef RUBINIUS
18
- # define rb_str_set_len(str,len) rb_str_resize(str,len)
19
- # else /* 1.8.6 optimized version */
13
+ # error we should never get here with current Rubinius (1.x)
14
+ # endif
20
15
  /* this is taken from Ruby 1.8.7, 1.8.6 may not have it */
21
16
  static void rb_18_str_set_len(VALUE str, long len)
22
17
  {
23
18
  RSTRING(str)->len = len;
24
19
  RSTRING(str)->ptr[len] = '\0';
25
- rb_str_flush(str);
26
20
  }
27
- # define rb_str_set_len(str,len) rb_18_str_set_len(str,len)
28
- # endif /* ! RUBINIUS */
21
+ # define rb_str_set_len(str,len) rb_18_str_set_len(str,len)
29
22
  #endif /* !defined(HAVE_RB_STR_SET_LEN) */
30
23
 
31
24
  /* not all Ruby implementations support frozen objects (Rubinius does not) */
@@ -175,9 +175,9 @@ static void write_value(VALUE hdr, struct http_parser *hp,
175
175
  VALUE f, v;
176
176
  VALUE hclass;
177
177
  const char *fptr = PTR_TO(start.field);
178
- long flen = hp->s.field_len;
178
+ size_t flen = hp->s.field_len;
179
179
  const char *vptr;
180
- long vlen;
180
+ size_t vlen;
181
181
 
182
182
  HP_FL_SET(hp, HASHEADER);
183
183
 
@@ -191,8 +191,8 @@ static void write_value(VALUE hdr, struct http_parser *hp,
191
191
  vlen = LEN(mark, p);
192
192
  VALIDATE_MAX_LENGTH(vlen, FIELD_VALUE);
193
193
  VALIDATE_MAX_LENGTH(flen, FIELD_NAME);
194
- f = rb_str_new(fptr, flen);
195
- v = rb_str_new(vptr, vlen);
194
+ f = rb_str_new(fptr, (long)flen);
195
+ v = rb_str_new(vptr, (long)vlen);
196
196
 
197
197
  /* needs more tests for error-checking here */
198
198
  /*
@@ -500,8 +500,6 @@ static VALUE headers(VALUE self, VALUE hdr, VALUE data)
500
500
  {
501
501
  struct http_parser *hp = data_get(self);
502
502
 
503
- rb_str_update(data);
504
-
505
503
  http_parser_execute(hp, hdr, RSTRING_PTR(data), RSTRING_LEN(data));
506
504
  VALIDATE_MAX_LENGTH(hp->offset, HEADER);
507
505
 
@@ -600,7 +598,6 @@ static VALUE filter_body(VALUE self, VALUE buf, VALUE data)
600
598
  char *dptr;
601
599
  long dlen;
602
600
 
603
- rb_str_update(data);
604
601
  dptr = RSTRING_PTR(data);
605
602
  dlen = RSTRING_LEN(data);
606
603
 
@@ -1,40 +1,25 @@
1
1
  ENV["VERSION"] or abort "VERSION= must be specified"
2
2
  manifest = File.readlines('.manifest').map! { |x| x.chomp! }
3
- summary = File.readlines("README")[0].gsub(/\A=\s+\S+[^\w]+/, '').strip
4
- description = File.read("README").split(/\n\n/)[1].strip
3
+ require 'wrongdoc'
4
+ extend Wrongdoc::Gemspec
5
+ name, summary, title = readme_metadata
5
6
 
6
7
  Gem::Specification.new do |s|
7
8
  s.name = %q{kcar}
8
- s.version = ENV["VERSION"]
9
-
10
- s.homepage = 'http://bogomips.org/kcar/'
9
+ s.version = ENV["VERSION"].dup
10
+ s.homepage = Wrongdoc.config[:rdoc_url]
11
11
  s.authors = ["kcar hackers"]
12
12
  s.date = Time.now.utc.strftime('%Y-%m-%d')
13
- s.description = description
14
- s.email = %q{kcar@librelist.com}
15
-
16
- s.extra_rdoc_files = File.readlines('.document').map! do |x|
17
- x.chomp!
18
- if File.directory?(x)
19
- manifest.grep(%r{\A#{x}/})
20
- elsif File.file?(x)
21
- x
22
- else
23
- nil
24
- end
25
- end.flatten.compact
26
-
13
+ s.description = readme_description
14
+ s.email = %q{kcar@librelist.org}
15
+ s.extra_rdoc_files = extra_rdoc_files(manifest)
27
16
  s.files = manifest
28
- s.rdoc_options = [
29
- "-a",
30
- "-t",
31
- summary
32
- ]
33
- s.require_paths = %w(lib ext)
17
+ s.rdoc_options = rdoc_options
34
18
  s.rubyforge_project = %q{rainbows}
35
19
  s.summary = summary
36
20
  s.test_files = Dir['test/test_*.rb']
37
21
  s.extensions = %w(ext/kcar/extconf.rb)
22
+ s.add_development_dependency('wrongdoc', '~> 1.5')
38
23
 
39
24
  # s.license = %w(GPL Ruby) # disabled for compatibility with older RubyGems
40
25
  end
@@ -1,8 +1,10 @@
1
1
  # -*- encoding: binary -*-
2
2
  module Kcar
3
3
 
4
- # current version, currently 0.1.2
5
- VERSION = '0.1.2'
4
+ # current version of Kcar, currently 0.2.0
5
+ # This constant is deprecated and will be removed in the next
6
+ # release. Use +respond_to?+ or +defined?+ instead to test for features.
7
+ VERSION = "0.2.0"
6
8
 
7
9
  autoload :Response, 'kcar/response'
8
10
  end
@@ -1,6 +1,5 @@
1
1
  # -*- encoding: binary -*-
2
- module Kcar
3
- class Parser
2
+ class Kcar::Parser
4
3
 
5
4
  # extract trailers that were set in the header object as
6
5
  # an array of arrays
@@ -34,6 +33,4 @@ class Parser
34
33
 
35
34
  trailers
36
35
  end
37
-
38
- end # class Parser
39
36
  end # module Kcar
@@ -1,14 +1,15 @@
1
1
  # -*- encoding: binary -*-
2
2
 
3
- module Kcar
4
3
 
5
4
  # This may be used to generate a Rack response
6
5
  #
7
- class Response < Struct.new(:sock, :hdr, :unchunk, :buf, :parser)
6
+ class Kcar::Response
7
+ attr_accessor :sock, :hdr, :unchunk, :buf, :parser
8
8
 
9
9
  # :stopdoc:
10
10
  LAST_CHUNK = "0\r\n"
11
11
  CRLF = "\r\n"
12
+ Parser = Kcar::Parser
12
13
  # :startdoc:
13
14
 
14
15
  # By default we readpartial at most 16K off a socket at once
@@ -18,7 +19,7 @@ class Response < Struct.new(:sock, :hdr, :unchunk, :buf, :parser)
18
19
  # method. +unchunk+ may be set to disable transparent unchunking
19
20
  # +hdr+ may be a Hash, Array, or Rack::Utils::HeaderHash
20
21
  def initialize(sock, hdr = {}, unchunk = true)
21
- super(sock, hdr, unchunk, "", Parser.new)
22
+ @sock, @hdr, @unchunk, @buf, @parser = sock, hdr, unchunk, "", Parser.new
22
23
  end
23
24
 
24
25
  # returns a 3-element array that resembles a Rack response, but is
@@ -33,9 +34,9 @@ class Response < Struct.new(:sock, :hdr, :unchunk, :buf, :parser)
33
34
  # +unchunk+ must be true to guarantee trailers will be stored in the
34
35
  # returned +header+ object
35
36
  def read
36
- buf << sock.readpartial(READ_SIZE) if buf.empty?
37
- while (response = parser.headers(hdr, buf)).nil?
38
- buf << sock.readpartial(READ_SIZE)
37
+ @buf << @sock.readpartial(READ_SIZE) if @buf.empty?
38
+ until response = @parser.headers(@hdr, @buf)
39
+ @buf << @sock.readpartial(READ_SIZE)
39
40
  end
40
41
  response << self
41
42
  end
@@ -47,7 +48,7 @@ class Response < Struct.new(:sock, :hdr, :unchunk, :buf, :parser)
47
48
  # but the body returned will be this Kcar::Response handler itself.
48
49
  # It is not guaranteed that trailers will be stored in the returned +header+
49
50
  def rack
50
- self.unchunk = false
51
+ @unchunk = false
51
52
  read
52
53
  end
53
54
 
@@ -55,23 +56,25 @@ class Response < Struct.new(:sock, :hdr, :unchunk, :buf, :parser)
55
56
  # our given +sock+ object if keepalive is not used otherwise it
56
57
  # will just reset the parser and clear the header object
57
58
  def close
58
- parser.keepalive? ? reset : sock.close
59
+ @parser.keepalive? ? reset : @sock.close
59
60
  end
60
61
 
61
62
  # this method allows our Kcar::Response object to be used as a Rack response
62
63
  # body. It may only be called once (usually by a Rack server) as it streams
63
64
  # the response body off the our socket object.
64
- def each(&block)
65
- if parser.body_eof?
65
+ def each
66
+ if @parser.body_eof?
66
67
  return
67
68
  end
68
- if unchunk
69
- parser.chunked? ? each_unchunk(&block) : each_identity(&block)
69
+ if @unchunk
70
+ @parser.chunked? ? each_unchunk { |x| yield x } :
71
+ each_identity { |x| yield x }
70
72
  else
71
- if parser.keepalive?
72
- parser.chunked? ? each_rechunk(&block) : each_identity(&block)
73
+ if @parser.keepalive?
74
+ @parser.chunked? ? each_rechunk { |x| yield x } :
75
+ each_identity { |x| yield x }
73
76
  else
74
- each_until_eof(&block) # fastest path
77
+ each_until_eof { |x| yield x } # fastest path
75
78
  end
76
79
  end
77
80
  rescue EOFError
@@ -79,11 +82,11 @@ class Response < Struct.new(:sock, :hdr, :unchunk, :buf, :parser)
79
82
 
80
83
  # :stopdoc:
81
84
  def reset
82
- parser.reset
83
- hdr.clear
85
+ @parser.reset
86
+ @hdr.clear
84
87
  end
85
88
 
86
- def each_rechunk(&block)
89
+ def each_rechunk
87
90
  # We have to filter_body to keep track of parser state
88
91
  # (which sucks). Also, as a benefit to clients we'll rechunk
89
92
  # to increase the likelyhood of network transfers being on
@@ -91,43 +94,43 @@ class Response < Struct.new(:sock, :hdr, :unchunk, :buf, :parser)
91
94
  # other people's code :)
92
95
  dst = ""
93
96
  begin
94
- parser.filter_body(dst, buf) and break
97
+ @parser.filter_body(dst, @buf) and break
95
98
  size = dst.size
96
99
  if size > 0
97
100
  yield("#{size.to_s(16)}\r\n")
98
101
  yield(dst << CRLF)
99
102
  end
100
- break if parser.body_eof?
101
- end while buf << sock.readpartial(READ_SIZE, dst)
103
+ break if @parser.body_eof?
104
+ end while @buf << @sock.readpartial(READ_SIZE, dst)
102
105
 
103
106
  yield LAST_CHUNK
104
107
 
105
- while parser.trailers(hdr, buf).nil?
106
- buf << sock.readpartial(READ_SIZE, dst)
108
+ until @parser.trailers(@hdr, @buf)
109
+ @buf << @sock.readpartial(READ_SIZE, dst)
107
110
  end
108
111
 
109
112
  # since Rack does not provide a way to explicitly send trailers
110
113
  # in the response, we'll just yield a stringified version to our
111
114
  # server and pretend it's part of the body.
112
- trailers = parser.extract_trailers(hdr)
115
+ trailers = @parser.extract_trailers(@hdr)
113
116
  yield(trailers.map! { |k,v| "#{k}: #{v}\r\n" }.join("") << CRLF)
114
117
  end
115
118
 
116
- def each_until_eof(&block)
117
- yield buf unless buf.empty?
119
+ def each_until_eof
120
+ yield @buf unless @buf.empty?
118
121
  # easy, just read and write everything until EOFError
119
- dst = sock.readpartial(READ_SIZE)
122
+ dst = @sock.readpartial(READ_SIZE)
120
123
  begin
121
124
  yield dst
122
- end while sock.readpartial(READ_SIZE, dst)
125
+ end while @sock.readpartial(READ_SIZE, dst)
123
126
  end
124
127
 
125
- def each_identity(&block)
126
- len = parser.body_bytes_left
127
- if len.nil?
128
- each_until_eof(&block)
128
+ def each_identity
129
+ len = @parser.body_bytes_left
130
+ if len == nil
131
+ each_until_eof { |x| yield x }
129
132
  else
130
- dst = buf
133
+ dst = @buf
131
134
  if dst.size > 0
132
135
  # in case of keepalive we need to read the second response,
133
136
  # so modify buf so that the second response is at the front
@@ -135,7 +138,7 @@ class Response < Struct.new(:sock, :hdr, :unchunk, :buf, :parser)
135
138
  if dst.size >= len
136
139
  tmp = dst[len, dst.size]
137
140
  dst = dst[0, len]
138
- buf.replace(tmp)
141
+ @buf.replace(tmp)
139
142
  end
140
143
 
141
144
  len -= dst.size
@@ -144,30 +147,28 @@ class Response < Struct.new(:sock, :hdr, :unchunk, :buf, :parser)
144
147
 
145
148
  if len > 0
146
149
  begin
147
- len -= sock.readpartial(len > READ_SIZE ? READ_SIZE : len, dst).size
150
+ len -= @sock.readpartial(len > READ_SIZE ? READ_SIZE : len, dst).size
148
151
  yield dst
149
152
  end while len > 0
150
- dst.respond_to?(:clear) ? dst.clear : self.buf = ''
153
+ dst.respond_to?(:clear) ? dst.clear : @buf = ""
151
154
  end
152
155
  end
153
156
  end
154
157
 
155
- def each_unchunk(&block)
158
+ def each_unchunk
156
159
  dst = ""
157
160
  begin
158
- parser.filter_body(dst, buf) and break
161
+ @parser.filter_body(dst, @buf) and break
159
162
  yield dst if dst.size > 0
160
- parser.body_eof? and break
161
- end while buf << sock.readpartial(READ_SIZE, dst)
163
+ @parser.body_eof? and break
164
+ end while @buf << @sock.readpartial(READ_SIZE, dst)
162
165
 
163
166
  # we can't pass trailers to the client since we unchunk
164
167
  # the response, so just read them off the socket and
165
168
  # stash them in hdr just in case...
166
- while parser.headers(hdr, buf).nil?
167
- buf << sock.readpartial(READ_SIZE, dst)
169
+ until @parser.headers(@hdr, @buf)
170
+ @buf << @sock.readpartial(READ_SIZE, dst)
168
171
  end
169
172
  end
170
173
  # :startdoc:
171
-
172
- end # class Response
173
- end # module Kcar
174
+ end
data/pkg.mk ADDED
@@ -0,0 +1,171 @@
1
+ RUBY = ruby
2
+ RAKE = rake
3
+ RSYNC = rsync
4
+ WRONGDOC = wrongdoc
5
+
6
+ GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
7
+ @./GIT-VERSION-GEN
8
+ -include GIT-VERSION-FILE
9
+ -include local.mk
10
+ DLEXT := $(shell $(RUBY) -rrbconfig -e 'puts RbConfig::CONFIG["DLEXT"]')
11
+ RUBY_VERSION := $(shell $(RUBY) -e 'puts RUBY_VERSION')
12
+ RUBY_ENGINE := $(shell $(RUBY) -e 'puts((RUBY_ENGINE rescue "ruby"))')
13
+ lib := lib
14
+
15
+ ifeq ($(shell test -f script/isolate_for_tests && echo t),t)
16
+ isolate_libs := tmp/isolate/$(RUBY_ENGINE)-$(RUBY_VERSION)/isolate.mk
17
+ $(isolate_libs): script/isolate_for_tests
18
+ @$(RUBY) script/isolate_for_tests
19
+ -include $(isolate_libs)
20
+ lib := $(lib):$(ISOLATE_LIBS)
21
+ endif
22
+
23
+ ext := $(firstword $(wildcard ext/*))
24
+ ifneq ($(ext),)
25
+ ext_pfx := tmp/ext/$(RUBY_ENGINE)-$(RUBY_VERSION)
26
+ ext_h := $(wildcard $(ext)/*/*.h $(ext)/*.h)
27
+ ext_src := $(wildcard $(ext)/*.c $(ext_h))
28
+ ext_pfx_src := $(addprefix $(ext_pfx)/,$(ext_src))
29
+ ext_d := $(ext_pfx)/$(ext)/.d
30
+ $(ext)/extconf.rb: $(wildcard $(ext)/*.h)
31
+ @>> $@
32
+ $(ext_d):
33
+ @mkdir -p $(@D)
34
+ @> $@
35
+ $(ext_pfx)/$(ext)/%: $(ext)/% $(ext_d)
36
+ install -m 644 $< $@
37
+ $(ext_pfx)/$(ext)/Makefile: $(ext)/extconf.rb $(ext_d) $(ext_h)
38
+ $(RM) -f $(@D)/*.o
39
+ cd $(@D) && $(RUBY) $(CURDIR)/$(ext)/extconf.rb
40
+ ext_sfx := _ext.$(DLEXT)
41
+ ext_dl := $(ext_pfx)/$(ext)/$(notdir $(ext)_ext.$(DLEXT))
42
+ $(ext_dl): $(ext_src) $(ext_pfx_src) $(ext_pfx)/$(ext)/Makefile
43
+ @echo $^ == $@
44
+ $(MAKE) -C $(@D)
45
+ lib := $(lib):$(ext_pfx)/$(ext)
46
+ build: $(ext_dl)
47
+ else
48
+ build:
49
+ endif
50
+
51
+ pkg_extra += GIT-VERSION-FILE NEWS ChangeLog LATEST
52
+ ChangeLog: GIT-VERSION-FILE .wrongdoc.yml
53
+ $(WRONGDOC) prepare
54
+ NEWS LATEST: ChangeLog
55
+
56
+ manifest:
57
+ $(RM) .manifest
58
+ $(MAKE) .manifest
59
+
60
+ .manifest: $(pkg_extra)
61
+ (git ls-files && for i in $@ $(pkg_extra); do echo $$i; done) | \
62
+ LC_ALL=C sort > $@+
63
+ cmp $@+ $@ || mv $@+ $@
64
+ $(RM) $@+
65
+
66
+ doc:: .document .wrongdoc.yml $(pkg_extra)
67
+ -find lib -type f -name '*.rbc' -exec rm -f '{}' ';'
68
+ -find ext -type f -name '*.rbc' -exec rm -f '{}' ';'
69
+ $(RM) -r doc
70
+ $(WRONGDOC) all
71
+ install -m644 COPYING doc/COPYING
72
+ install -m644 $(shell grep '^[A-Z]' .document) doc/
73
+
74
+ ifneq ($(VERSION),)
75
+ pkggem := pkg/$(rfpackage)-$(VERSION).gem
76
+ pkgtgz := pkg/$(rfpackage)-$(VERSION).tgz
77
+ release_notes := release_notes-$(VERSION)
78
+ release_changes := release_changes-$(VERSION)
79
+
80
+ release-notes: $(release_notes)
81
+ release-changes: $(release_changes)
82
+ $(release_changes):
83
+ $(WRONGDOC) release_changes > $@+
84
+ $(VISUAL) $@+ && test -s $@+ && mv $@+ $@
85
+ $(release_notes):
86
+ $(WRONGDOC) release_notes > $@+
87
+ $(VISUAL) $@+ && test -s $@+ && mv $@+ $@
88
+
89
+ # ensures we're actually on the tagged $(VERSION), only used for release
90
+ verify:
91
+ test x"$(shell umask)" = x0022
92
+ git rev-parse --verify refs/tags/v$(VERSION)^{}
93
+ git diff-index --quiet HEAD^0
94
+ test $$(git rev-parse --verify HEAD^0) = \
95
+ $$(git rev-parse --verify refs/tags/v$(VERSION)^{})
96
+
97
+ fix-perms:
98
+ -git ls-tree -r HEAD | awk '/^100644 / {print $$NF}' | xargs chmod 644
99
+ -git ls-tree -r HEAD | awk '/^100755 / {print $$NF}' | xargs chmod 755
100
+
101
+ gem: $(pkggem)
102
+
103
+ install-gem: $(pkggem)
104
+ gem install $(CURDIR)/$<
105
+
106
+ $(pkggem): manifest fix-perms
107
+ gem build $(rfpackage).gemspec
108
+ mkdir -p pkg
109
+ mv $(@F) $@
110
+
111
+ $(pkgtgz): distdir = $(basename $@)
112
+ $(pkgtgz): HEAD = v$(VERSION)
113
+ $(pkgtgz): manifest fix-perms
114
+ @test -n "$(distdir)"
115
+ $(RM) -r $(distdir)
116
+ mkdir -p $(distdir)
117
+ tar cf - $$(cat .manifest) | (cd $(distdir) && tar xf -)
118
+ cd pkg && tar cf - $(basename $(@F)) | gzip -9 > $(@F)+
119
+ mv $@+ $@
120
+
121
+ package: $(pkgtgz) $(pkggem)
122
+
123
+ test-release:: verify package $(release_notes) $(release_changes)
124
+ # make tgz release on RubyForge
125
+ @echo rubyforge add_release -f \
126
+ -n $(release_notes) -a $(release_changes) \
127
+ $(rfproject) $(rfpackage) $(VERSION) $(pkgtgz)
128
+ @echo gem push $(pkggem)
129
+ @echo rubyforge add_file \
130
+ $(rfproject) $(rfpackage) $(VERSION) $(pkggem)
131
+ release:: verify package $(release_notes) $(release_changes)
132
+ # make tgz release on RubyForge
133
+ rubyforge add_release -f -n $(release_notes) -a $(release_changes) \
134
+ $(rfproject) $(rfpackage) $(VERSION) $(pkgtgz)
135
+ # push gem to RubyGems.org
136
+ gem push $(pkggem)
137
+ # in case of gem downloads from RubyForge releases page
138
+ rubyforge add_file \
139
+ $(rfproject) $(rfpackage) $(VERSION) $(pkggem)
140
+ else
141
+ gem install-gem: GIT-VERSION-FILE
142
+ $(MAKE) $@ VERSION=$(GIT_VERSION)
143
+ endif
144
+
145
+ all:: test
146
+ test_units := $(wildcard test/test_*.rb)
147
+ test: test-unit
148
+ test-unit: $(test_units)
149
+ $(test_units): build
150
+ $(RUBY) -I $(lib) $@ $(RUBY_TEST_OPTS)
151
+
152
+ # this requires GNU coreutils variants
153
+ ifneq ($(RSYNC_DEST),)
154
+ publish_doc:
155
+ -git set-file-times
156
+ $(MAKE) doc
157
+ find doc/images -type f | \
158
+ TZ=UTC xargs touch -d '1970-01-01 00:00:06' doc/rdoc.css
159
+ $(MAKE) doc_gz
160
+ $(RSYNC) -av doc/ $(RSYNC_DEST)/
161
+ git ls-files | xargs touch
162
+ endif
163
+
164
+ # Create gzip variants of the same timestamp as the original so nginx
165
+ # "gzip_static on" can serve the gzipped versions directly.
166
+ doc_gz: docs = $(shell find doc -type f ! -regex '^.*\.\(gif\|jpg\|png\|gz\)$$')
167
+ doc_gz:
168
+ for i in $(docs); do \
169
+ gzip --rsyncable -9 < $$i > $$i.gz; touch -r $$i $$i.gz; done
170
+
171
+ .PHONY: all .FORCE-GIT-VERSION-FILE doc test $(test_units) manifest
@@ -496,6 +496,7 @@ class TestSession < Test::Unit::TestCase
496
496
  @s.close
497
497
  @response = Kcar::Response.new(@c, [])
498
498
  status, headers, body = @response.rack
499
+ assert_kind_of Array, headers
499
500
  assert_equal status, "200 OK"
500
501
  tmp = []
501
502
  assert ! body.parser.keepalive?
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kcar
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
5
- prerelease: false
4
+ hash: 23
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
- - 1
9
8
  - 2
10
- version: 0.1.2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - kcar hackers
@@ -15,16 +15,30 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-11-30 00:00:00 +00:00
18
+ date: 2011-02-24 00:00:00 +00:00
19
19
  default_executable:
20
- dependencies: []
21
-
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: wrongdoc
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 5
30
+ segments:
31
+ - 1
32
+ - 5
33
+ version: "1.5"
34
+ type: :development
35
+ version_requirements: *id001
22
36
  description: |-
23
37
  kcar features an HTTP parser that will convert a bytestream into a
24
38
  3-element array suitable for use as a Rack response. It is IO interface
25
39
  agnostic, so it may be used with HTTP streams over Unix domain sockets,
26
40
  regular files, FIFOs, StringIOs as well as traditional TCP sockets.
27
- email: kcar@librelist.com
41
+ email: kcar@librelist.org
28
42
  executables: []
29
43
 
30
44
  extensions:
@@ -43,11 +57,13 @@ files:
43
57
  - .document
44
58
  - .gitignore
45
59
  - .manifest
60
+ - .wrongdoc.yml
46
61
  - COPYING
47
62
  - ChangeLog
48
63
  - GIT-VERSION-FILE
49
64
  - GIT-VERSION-GEN
50
65
  - GNUmakefile
66
+ - LATEST
51
67
  - LICENSE
52
68
  - NEWS
53
69
  - README
@@ -63,6 +79,7 @@ files:
63
79
  - lib/kcar.rb
64
80
  - lib/kcar/parser.rb
65
81
  - lib/kcar/response.rb
82
+ - pkg.mk
66
83
  - setup.rb
67
84
  - test/test_parser.rb
68
85
  - test/test_response.rb
@@ -72,12 +89,12 @@ licenses: []
72
89
 
73
90
  post_install_message:
74
91
  rdoc_options:
75
- - -a
76
92
  - -t
77
- - bytestream to Rack response converter
93
+ - kcar - bytestream to Rack response converter
94
+ - -W
95
+ - http://bogomips.org/kcar.git/tree/%s
78
96
  require_paths:
79
97
  - lib
80
- - ext
81
98
  required_ruby_version: !ruby/object:Gem::Requirement
82
99
  none: false
83
100
  requirements:
@@ -99,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
99
116
  requirements: []
100
117
 
101
118
  rubyforge_project: rainbows
102
- rubygems_version: 1.3.7
119
+ rubygems_version: 1.5.2
103
120
  signing_key:
104
121
  specification_version: 3
105
122
  summary: bytestream to Rack response converter