gitoe 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.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.gitmodules +3 -0
  4. data/Gemfile +7 -0
  5. data/Gemfile.lock +91 -0
  6. data/Guardfile +8 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +30 -0
  9. data/Rakefile +35 -0
  10. data/Rules +47 -0
  11. data/bin/gitoe +36 -0
  12. data/content/gitoe-draw.coffee +342 -0
  13. data/content/gitoe-repo.coffee +546 -0
  14. data/content/gitoe.coffee +182 -0
  15. data/content/index.haml +71 -0
  16. data/content/jquery/jquery-1.9.1.min.js +5 -0
  17. data/content/jquery/jquery.scrollTo.min.js +7 -0
  18. data/content/raphael-min.js +10 -0
  19. data/content/reset.sass +46 -0
  20. data/content/style.sass +109 -0
  21. data/gitoe.gemspec +34 -0
  22. data/lib/gitoe.rb +16 -0
  23. data/lib/gitoe/httpserver/public/gitoe-draw.js +399 -0
  24. data/lib/gitoe/httpserver/public/gitoe-repo.js +618 -0
  25. data/lib/gitoe/httpserver/public/gitoe.js +249 -0
  26. data/lib/gitoe/httpserver/public/index.html +49 -0
  27. data/lib/gitoe/httpserver/public/jquery/jquery-1.9.1.min.js +5 -0
  28. data/lib/gitoe/httpserver/public/jquery/jquery.scrollTo.min.js +7 -0
  29. data/lib/gitoe/httpserver/public/raphael-min.js +10 -0
  30. data/lib/gitoe/httpserver/public/reset.css +45 -0
  31. data/lib/gitoe/httpserver/public/style.css +106 -0
  32. data/lib/gitoe/httpserver/repos.rb +71 -0
  33. data/lib/gitoe/httpserver/static.rb +17 -0
  34. data/lib/gitoe/repo/repo.rb +174 -0
  35. data/lib/gitoe/repo/rugged.rb +121 -0
  36. data/lib/gitoe/version.rb +3 -0
  37. data/nanoc.yaml +77 -0
  38. data/test/test.rb +9 -0
  39. data/todo.markdown +16 -0
  40. data/vendor/jquery-1.9.1.min.js +5 -0
  41. data/vendor/raphael-min.js +10 -0
  42. metadata +239 -0
@@ -0,0 +1,71 @@
1
+ # rack app for repos
2
+ require "gitoe"
3
+ require "gitoe/repo/rugged"
4
+ require "sinatra"
5
+ require "active_support"
6
+
7
+ module Gitoe::HTTPServer
8
+ class Repos < ::Sinatra::Base
9
+
10
+ Repo = ::Gitoe::Repo::RestfulRugged
11
+
12
+ set :environment, :production
13
+
14
+ def json reply
15
+ content_type 'application/json'
16
+ ::ActiveSupport::JSON.encode(reply)
17
+ end
18
+
19
+ error do
20
+ json \
21
+ :error_message => env['sinatra.error'],
22
+ :backtrace => env['sinatra.error'].backtrace
23
+ end
24
+
25
+ # index
26
+ get "/" do
27
+ json Repo.instances[:by_arg]
28
+ end
29
+
30
+ # create
31
+ post "/new" do
32
+ # create instance if not existing
33
+ # and return id
34
+ path = params["path"] or raise "path not specified"
35
+ repo_id = Repo.id_for(path)
36
+ repo = Repo.find repo_id
37
+ json \
38
+ :id => repo_id ,
39
+ :path => repo.path
40
+ end
41
+
42
+ # show
43
+ get "/:repo_id/?" do
44
+ repo = Repo.find params["repo_id"]
45
+ json repo.status
46
+ end
47
+
48
+ # namespace under /:repo_id/:resource
49
+ Resources = Set[ 'commits', 'commit' ].freeze
50
+ get "/:repo_id/**" do
51
+
52
+ repo = Repo.find( params["repo_id"] )
53
+
54
+ sub_str = params[:splat].last # "**" part
55
+
56
+ resource, url = sub_str.split('/',2)
57
+ raise "invalid resource '#{resource}'" unless Resources.include? resource
58
+ query_hash = env['rack.request.query_hash']
59
+ # /1/commits/aaaaaaa/b/c/d ? a=1 & b=1
60
+ # => {
61
+ # repo_id: "1",
62
+ # resource: "commits"
63
+ # arg: "aaaaaaa/b/c/d"
64
+ # query_hash:
65
+ # }
66
+ # json resource => repo.send(resource.to_sym, arg, env[])
67
+ json repo.send(resource, url, query_hash )
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,17 @@
1
+ # rack app for static files
2
+ require "gitoe"
3
+ require "sinatra"
4
+
5
+ module Gitoe::HTTPServer
6
+ class Static < ::Sinatra::Base
7
+
8
+ set :app_file, __FILE__
9
+ set :environment, :production
10
+ set :static_cache_control, [:public, max_age: 3600]
11
+
12
+ get "/" do
13
+ send_file File.join( settings.public_folder, "index.html" )
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,174 @@
1
+ require "gitoe"
2
+
3
+ module Gitoe::Repo
4
+
5
+ # instance methods, enable querying of instances
6
+ module Query
7
+
8
+ def instances
9
+ @instances ||= {
10
+ :by_arg => {}, # arg => id
11
+ :by_id => {}, # id => instance
12
+ }
13
+ end
14
+
15
+ def create arg
16
+ id = instances[:by_id].size
17
+ instances[:by_id][id] = self.new arg
18
+ instances[:by_arg][arg] = id
19
+ end
20
+
21
+ def destroy id
22
+ raise NotImplementedError # TODO
23
+ end
24
+
25
+ def find id
26
+ id = Integer(id) unless id.is_a? Integer
27
+ instances[:by_id][id] or raise "repo not found"
28
+ end
29
+
30
+ def id_for arg
31
+ existing = instances[:by_arg][arg]
32
+ if existing
33
+ existing
34
+ else
35
+ create arg
36
+ end
37
+ end
38
+ end
39
+
40
+ module RestfulRepo
41
+ # public methods( 'resources' ):
42
+ # #status
43
+ # #commits
44
+
45
+ def status
46
+ {
47
+ :refs => refs ,
48
+ :path => path ,
49
+ :cached_commits => size_of_cache,
50
+ }
51
+ end
52
+
53
+ def commits start, options={}
54
+ # start :
55
+ # commits to start at,
56
+ # possible multiple, ','
57
+ # options :
58
+ # limit
59
+ limit = (options['limit'] || 1000).to_i
60
+
61
+ to_query = start.split ','
62
+ queried = {}
63
+
64
+ while to_query.size > 0 and queried.size < limit
65
+
66
+ another = to_query.shift
67
+ next if queried.has_key?(another)
68
+
69
+ parent = commit another
70
+ queried[ parent[:sha1] ] ||= parent
71
+ parent[:parents].each do |p|
72
+ next if queried.has_key? p
73
+ to_query.push p
74
+ end
75
+ end
76
+ $gitoe_log[ "gathered #{queried.size} from #{start}" ]
77
+
78
+ queried
79
+ end
80
+
81
+ end
82
+
83
+ module Cache
84
+ def initialize *args
85
+ init_cache
86
+ super
87
+ end
88
+
89
+ private
90
+
91
+ def ref name
92
+ follow_ref super
93
+ end
94
+
95
+ def follow_ref ref_hash
96
+ ref_hash
97
+ end
98
+
99
+ def commit sha1, options={}
100
+ # if in_cache?
101
+ # just take from cache
102
+ # else
103
+ # add sha1 and all its ancestors to cache, in topological order
104
+ if in_cache? sha1
105
+ return from_cache sha1
106
+ end
107
+ this = super(sha1).freeze
108
+ if not in_cache? this[:sha1]
109
+ add_to_cache this[:sha1], this
110
+ end
111
+ this
112
+ end
113
+
114
+ private
115
+
116
+ def add_to_cache sha1, content
117
+ if $gitoe_debug and in_cache?(sha1)
118
+ raise "#{sha1} already in cache"
119
+ end
120
+ $gitoe_log[ "add #{sha1} to cache" ]
121
+ @cached_commits[sha1] = content
122
+ end
123
+
124
+ def init_cache
125
+ @cached_commits = {} # { sha1:content, order:content }
126
+ end
127
+
128
+ def size_of_cache
129
+ @cached_commits.size
130
+ end
131
+
132
+ def from_cache sha1
133
+ @cached_commits[sha1] or raise "not in cache"
134
+ end
135
+
136
+ def in_cache? key
137
+ @cached_commits.has_key? key
138
+ end
139
+
140
+ def sort_topo queried
141
+
142
+ sorted = []
143
+
144
+ in_degree = Hash.new{|h,k| h[k] = 0 }
145
+ children = Hash.new{|h,k| h[k] = [] }
146
+
147
+ queried.each do |sha1,content|
148
+ in_degree[sha1]
149
+ content[:parents].each do |p|
150
+ in_degree[p]
151
+ in_degree[sha1] += 1
152
+ children[p] << sha1
153
+ end
154
+ end
155
+
156
+ to_remove = in_degree.keys.select{|k| in_degree[k] == 0 }
157
+ while to_remove.size > 0
158
+ # $gitoe_log[ "topo-sorting : remaining #{in_degree.size}" ]
159
+
160
+ n = to_remove.shift
161
+ sorted.push n
162
+ in_degree.delete n
163
+
164
+ children[n].each do |c|
165
+ new_in_degree = in_degree[c] -= 1
166
+ to_remove.push c if new_in_degree == 0
167
+ end
168
+ end
169
+
170
+ $gitoe_log[ "topo-sorting DONE" ]
171
+ return sorted.select{|s| queried.has_key? s }
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,121 @@
1
+ # repo using rugged ( https://github.com/libgit2/rugged )
2
+ require "gitoe/repo/repo"
3
+ require "rugged"
4
+
5
+ module Gitoe::Repo
6
+ class Rugged_backend
7
+
8
+ # implements
9
+ # path :: -> String
10
+ # commit :: sha1::String -> { prop:val }
11
+ # refs :: -> { ref_name : reflogs }
12
+ # ref :: String -> reflogs
13
+
14
+ # private
15
+ # ref_names :: -> [ String ]
16
+ # reflog :: String -> [ {} ]
17
+
18
+ include ::Rugged
19
+
20
+ def initialize path
21
+ @rugged = Repository.new path
22
+ end
23
+
24
+ def path
25
+ @rugged.path
26
+ end
27
+
28
+ def commit sha1
29
+ # $gitoe_log[ "query #{sha1}" ]
30
+ obj = @rugged.lookup(sha1)
31
+ case obj
32
+ when Commit
33
+ commit_to_hash obj
34
+ else
35
+ raise "#{obj} is not commit"
36
+ end
37
+ end
38
+
39
+ def refs
40
+ Hash[
41
+ ref_names.map do |ref_name|
42
+ [ ref_name, ref(ref_name) ]
43
+ end
44
+ ]
45
+ end
46
+
47
+ def ref(name)
48
+ resolved = Reference.lookup(@rugged, name)
49
+ basic = {
50
+ :name => resolved.name ,
51
+ :target => resolved.target ,
52
+ :type => resolved.type ,
53
+ :log => reflog( resolved ),
54
+ }
55
+ case name
56
+ when %r{^refs/remotes/}, %r{^refs/heads/}, 'HEAD'
57
+ extra = {}
58
+ when %r{^refs/tags/}
59
+ extra = deref_tag(resolved)
60
+ else
61
+ raise "error parsing ref <ref>"
62
+ end
63
+ basic.merge(extra).freeze
64
+ end
65
+
66
+ private
67
+
68
+ def ref_names
69
+ @rugged.refs.to_a.each do |ref_name|
70
+ ref_name.sub! %r{^/} , ""
71
+ end << "HEAD"
72
+ end
73
+
74
+ def deref_tag tag
75
+ target = @rugged.lookup(tag.target)
76
+ case target
77
+ when Tag
78
+ {
79
+ tag_type: 'annotated',
80
+ real_target: target.target.oid
81
+ }
82
+ when Commit
83
+ {
84
+ tag_type: 'lightweight'
85
+ }
86
+ else
87
+ raise "don't know #{tag}"
88
+ end
89
+ end
90
+
91
+ def reflog ref
92
+ raise "demand Reference" unless ref.is_a? Reference
93
+ log =
94
+ begin
95
+ ref.log
96
+ rescue
97
+ []
98
+ end
99
+ log.each do |change|
100
+ change[:committer][:time] = change[:committer][:time].to_i # seconds from epoch
101
+ end
102
+ end
103
+
104
+ def commit_to_hash commit_obj
105
+ {
106
+ :sha1 => commit_obj.oid,
107
+ :parents => commit_obj.parents.map(&:oid),
108
+ # :type => :commit,
109
+ :author => commit_obj.author,
110
+ :committer => commit_obj.committer
111
+ }.freeze
112
+ end
113
+ end
114
+
115
+ class RestfulRugged < Rugged_backend
116
+ extend Query
117
+ include Cache
118
+ include RestfulRepo
119
+ # ancestors: [RestfulRugged, RestfulRepo, Cache, Rugged_backend]
120
+ end
121
+ end
@@ -0,0 +1,3 @@
1
+ module Gitoe
2
+ VERSION = "0.1.0"
3
+ end
data/nanoc.yaml ADDED
@@ -0,0 +1,77 @@
1
+ # A list of file extensions that nanoc will consider to be textual rather than
2
+ # binary. If an item with an extension not in this list is found, the file
3
+ # will be considered as binary.
4
+ text_extensions: [ 'coffee', 'haml', 'sass' ]
5
+
6
+ # The path to the directory where all generated files will be written to. This
7
+ # can be an absolute path starting with a slash, but it can also be path
8
+ # relative to the site directory.
9
+ output_dir: lib/gitoe/httpserver/public/
10
+
11
+ # A list of index filenames, i.e. names of files that will be served by a web
12
+ # server when a directory is requested. Usually, index files are named
13
+ # “index.html”, but depending on the web server, this may be something else,
14
+ # such as “default.htm”. This list is used by nanoc to generate pretty URLs.
15
+ index_filenames: [ 'index.html' ]
16
+
17
+ # Whether or not to generate a diff of the compiled content when compiling a
18
+ # site. The diff will contain the differences between the compiled content
19
+ # before and after the last site compilation.
20
+ enable_output_diff: false
21
+
22
+ prune:
23
+ # Whether to automatically remove files not managed by nanoc from the output
24
+ # directory. For safety reasons, this is turned off by default.
25
+ auto_prune: true
26
+
27
+ # Which files and directories you want to exclude from pruning. If you version
28
+ # your output directory, you should probably exclude VCS directories such as
29
+ # .git, .svn etc.
30
+ exclude: [ '.git', '.hg', '.svn', 'CVS' ]
31
+
32
+ # The data sources where nanoc loads its data from. This is an array of
33
+ # hashes; each array element represents a single data source. By default,
34
+ # there is only a single data source that reads data from the “content/” and
35
+ # “layout/” directories in the site directory.
36
+ data_sources:
37
+ -
38
+ # The type is the identifier of the data source. By default, this will be
39
+ # `filesystem_unified`.
40
+ type: filesystem_unified
41
+
42
+ # The path where items should be mounted (comparable to mount points in
43
+ # Unix-like systems). This is “/” by default, meaning that items will have
44
+ # “/” prefixed to their identifiers. If the items root were “/en/”
45
+ # instead, an item at content/about.html would have an identifier of
46
+ # “/en/about/” instead of just “/about/”.
47
+ items_root: /
48
+
49
+ # The path where layouts should be mounted. The layouts root behaves the
50
+ # same as the items root, but applies to layouts rather than items.
51
+ layouts_root: /
52
+
53
+ # Whether to allow periods in identifiers. When turned off, everything
54
+ # past the first period is considered to be the extension, and when
55
+ # turned on, only the characters past the last period are considered to
56
+ # be the extension. For example, a file named “content/about.html.erb”
57
+ # will have the identifier “/about/” when turned off, but when turned on
58
+ # it will become “/about.html/” instead.
59
+ allow_periods_in_identifiers: true
60
+
61
+ # Configuration for the “watch” command, which watches a site for changes and
62
+ # recompiles if necessary.
63
+ watcher:
64
+ # A list of directories to watch for changes. When editing this, make sure
65
+ # that the “output/” and “tmp/” directories are _not_ included in this list,
66
+ # because recompiling the site will cause these directories to change, which
67
+ # will cause the site to be recompiled, which will cause these directories
68
+ # to change, which will cause the site to be recompiled again, and so on.
69
+ dirs_to_watch: [ 'content' ]
70
+
71
+ # A list of single files to watch for changes. As mentioned above, don’t put
72
+ # any files from the “output/” or “tmp/” directories in here.
73
+ files_to_watch: [ 'nanoc.yaml', 'Rules' ]
74
+
75
+ # When to send notifications (using Growl or notify-send).
76
+ notify_on_compilation_success: true
77
+ notify_on_compilation_failure: true