gitdocs 0.5.0.pre7 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZTBiOGM2MTgxYWMwYTBlZTkzMTRhNTAxYTMyMTgyYTM1NjdmNjgyMQ==
4
+ NDc4ZmI3MTc1YjRjZjE4ZmNmNDFmNjgwMDEzY2YzZTkwY2Q5MWI4Yw==
5
5
  data.tar.gz: !binary |-
6
- ZTc1ZTFiNWVjZjVlYjk0MDgyYmE4NGNiNzJjZTQzNzdjY2Q2YTgwMg==
6
+ YmRjMzViNzc0MzgwMDVkMDgxOGNmMDI3MDZmYjhlMTU3OGUxMDg2ZQ==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- Yzk2NDFmMmJkYmM4MDllOTVmOWZhYjM0NDM3MzFjNzY1NzUyNGE3Mzk5ZGE5
10
- MWNhODBjN2U5YTA5YjkzZjIwZDI5YzAyNzIyM2RiZTYwYTMzYjIwYjhkYTY0
11
- MmExYjFlNzFlN2VkOWUyNGYwNTg1MjUyYjU2ZmM5YTk1MTU0MzE=
9
+ MjMzNzJlNGY3YmMzMWY2YWY2ZTE1ZjBjYTJmZDYwMWZmM2NjMTYyOTM0YzUw
10
+ ODkwZmFmY2NkYmVkZTI3MjYxNmZhNjUwZDliYjJmODAzOGY2YTc3M2UwZjRk
11
+ MTZiNGYwNmVmMjU5ZDkyM2U1MjcwODdlZmQ1ODJhODJjZjA4ODQ=
12
12
  data.tar.gz: !binary |-
13
- OWZiZjNkOGZiYjc4NzcwNjAxYmRmNmExOTQwMTAzODYzYjBhNzRlYzI5ZjMy
14
- MjczNTJlMDcwYjQwZGM0Y2NlMTg4N2MyYzlhMGIyOWY0N2M3MTQ2NDJhODJi
15
- MDNhMzEyZDcxYjlhNTRhZDU2NGQxOTQwNDA2NGZiNDYwNjdjYWM=
13
+ MWM2Yjk4ZGE1ODIzMTg4YTEyYTg1YTNhZTc1MWI1NWFlMTczMWFlMjg5Y2Jh
14
+ NmRhYTAzYWNmMzI4MTZhNTdjN2QwMzA3MzZhMTI5ZDRmMGFhZWE3YTdhMWVk
15
+ ZTAwODA3OWZkMDdkMDEwZThlZDQyM2ZjZDMzMzA1ZjJiNDZhOTg=
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ 0.5.0 (May 2nd 2015)
2
+ * upgrade gems activerecord, minitest, haml-lint, redcarpet (@acant)
3
+ * convert web interface to use Sinatra instead of renee (@acant)
4
+ * add rake task to run the web interface standalone using the shotgun gem (@acant)
5
+ * add fenced code (and syntax highlighting) into Markdown parsing (@acant)
6
+
1
7
  0.5.0.pre7 (August 3rd 2014)
2
8
 
3
9
  * UI improvements to repo browser (@acant)
data/README.md CHANGED
@@ -59,6 +59,7 @@ gem install gitdocs
59
59
  If you have Growl installed on Max OSX, you'll probably want to run:
60
60
 
61
61
  ```
62
+ brew install caskroom/cask/brew-cask
62
63
  brew install growlnotify
63
64
  ```
64
65
 
data/Rakefile CHANGED
@@ -26,4 +26,22 @@ Rake::TestTask.new do |t|
26
26
  t.verbose = true
27
27
  end
28
28
 
29
+ desc 'Start the web interface for development'
30
+ task server: 'server:start'
31
+
32
+ namespace :server do
33
+ task :start do
34
+ sh('shotgun config.ru')
35
+ end
36
+
37
+ desc 'Copy the current configuration for use with the development web interface'
38
+ task :copy_config do
39
+ FileUtils.mkdir_p('./tmp/web')
40
+ FileUtils.copy(
41
+ File.expand_path('.gitdocs/config.db', ENV['HOME']),
42
+ './tmp/web/config.db'
43
+ )
44
+ end
45
+ end
46
+
29
47
  task default: 'test:integration'
data/config.ru ADDED
@@ -0,0 +1,21 @@
1
+ require './lib/gitdocs'
2
+ require './lib/gitdocs/manager'
3
+ require './lib/gitdocs/settings_app'
4
+ require './lib/gitdocs/browser_app'
5
+ require './lib/gitdocs/repository'
6
+ require './lib/gitdocs/configuration'
7
+
8
+ use Rack::Static,
9
+ urls: %w(/css /js /img /doc),
10
+ root: './lib/gitdocs/public'
11
+ use Rack::MethodOverride
12
+
13
+ config_root = './tmp/web'
14
+ FileUtils.mkdir_p(config_root)
15
+ Gitdocs::SettingsApp.set :manager, Gitdocs::Manager.new(config_root, true)
16
+ Gitdocs::SettingsApp.set :logging, true
17
+ map('/settings') { run Gitdocs::SettingsApp }
18
+
19
+ Gitdocs::BrowserApp.set :repositories, Gitdocs::Configuration.new(config_root).shares.map { |x| Gitdocs::Repository.new(x) }
20
+ Gitdocs::BrowserApp.set :logging, true
21
+ map('/') { run Gitdocs::BrowserApp }
data/gitdocs.gemspec CHANGED
@@ -7,7 +7,8 @@ Gem::Specification.new do |s|
7
7
  s.version = Gitdocs::VERSION
8
8
  s.authors = ['Josh Hull', 'Nathan Esquenazi']
9
9
  s.email = ['joshbuddy@gmail.com', 'nesquena@gmail.com']
10
- s.homepage = 'http://engineering.gomiso.com/2011/11/30/collaborate-and-track-tasks-with-ease-using-gitdocs/'
10
+ s.homepage = 'https://github.com/nesquena/gitdocs'
11
+
11
12
  s.summary = 'Open-source Dropbox using Ruby and Git.'
12
13
  s.description = 'Open-source Dropbox using Ruby and Git.'
13
14
  s.license = 'MIT'
@@ -23,15 +24,15 @@ Gem::Specification.new do |s|
23
24
 
24
25
  s.add_dependency 'joshbuddy-guard', '~> 0.10.0'
25
26
  s.add_dependency 'thin', '~> 1.6.2'
26
- s.add_dependency 'renee', '~> 0.3.11'
27
- s.add_dependency 'redcarpet', '~> 3.1.1'
27
+ s.add_dependency 'sinatra', '~> 1.4.5'
28
+ s.add_dependency 'redcarpet', '~> 3.2.2'
28
29
  s.add_dependency 'thor', '~> 0.14.6'
29
30
  s.add_dependency 'coderay', '~> 1.1.0'
30
31
  s.add_dependency 'dante', '~> 0.1.2'
31
32
  s.add_dependency 'growl', '~> 1.0.3'
32
33
  s.add_dependency 'haml', '~> 4.0.5'
33
34
  s.add_dependency 'sqlite3', '~> 1.3.4'
34
- s.add_dependency 'activerecord', '~> 4.1.4'
35
+ s.add_dependency 'activerecord', '~> 4.2.0'
35
36
  s.add_dependency 'grit', '~> 2.5.0'
36
37
  s.add_dependency 'shell_tools', '~> 0.1.0'
37
38
  s.add_dependency 'mimetype-fu', '~> 0.1.2'
@@ -40,7 +41,7 @@ Gem::Specification.new do |s|
40
41
  s.add_dependency 'rugged', '~> 0.19.0'
41
42
  s.add_dependency 'table_print', '~> 1.5.1'
42
43
 
43
- s.add_development_dependency 'minitest', '~> 5.4.0'
44
+ s.add_development_dependency 'minitest', '~> 5.5.0'
44
45
  s.add_development_dependency 'capybara_minitest_spec', '~> 1.0.2'
45
46
  s.add_development_dependency 'poltergeist', '~> 1.5.1'
46
47
  s.add_development_dependency 'rake'
@@ -49,7 +50,8 @@ Gem::Specification.new do |s|
49
50
  s.add_development_dependency 'metric_fu'
50
51
  s.add_development_dependency 'aruba'
51
52
  s.add_development_dependency 'rubocop'
52
- s.add_development_dependency 'haml-lint', '~> 0.6.0'
53
+ s.add_development_dependency 'haml-lint', '~> 0.10.0'
53
54
  s.add_development_dependency 'jslint_on_rails', '~> 1.1.1'
54
- s.add_development_dependency 'coveralls', '~> 0.7.0'
55
+ s.add_development_dependency 'coveralls'
56
+ s.add_development_dependency 'shotgun'
55
57
  end
@@ -0,0 +1,150 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'sinatra/base'
4
+ require 'uri'
5
+ require 'haml'
6
+ require 'mimetype_fu'
7
+ require 'gitdocs/rendering_helper'
8
+
9
+ module Gitdocs
10
+ class BrowserApp < Sinatra::Base
11
+ set :haml, format: :html5
12
+
13
+ helpers Gitdocs::RenderingHelper
14
+
15
+ get('/') do
16
+ if settings.repositories.size == 1
17
+ redirect to('/0/')
18
+ else
19
+ haml(
20
+ :home,
21
+ locals: {
22
+ shares: settings.repositories,
23
+ nav_state: 'home'
24
+ }
25
+ )
26
+ end
27
+ end
28
+
29
+ get('/search') do
30
+ haml(
31
+ :search,
32
+ locals: {
33
+ results: Gitdocs::Search.new(settings.repositories).search(params[:q]),
34
+ nav_state: nil
35
+ }
36
+ )
37
+ end
38
+
39
+ helpers do
40
+ # @return [Integer]
41
+ def id
42
+ @id ||= params[:id].to_i
43
+ end
44
+
45
+ # @return [Gitdocs::Repository::Path]
46
+ def path
47
+ halt(404) unless settings.repositories[id]
48
+ @path ||= Gitdocs::Repository::Path.new(
49
+ settings.repositories[id], URI.unescape(params[:splat].first)
50
+ )
51
+ end
52
+ end
53
+
54
+ get('/:id*') do
55
+ default_locals = {
56
+ idx: id,
57
+ root: settings.repositories[id].root,
58
+ nav_state: nil
59
+ }
60
+
61
+ case params[:mode]
62
+ when 'meta'
63
+ begin
64
+ content_type :json
65
+ path.meta.to_json
66
+ rescue
67
+ halt(404)
68
+ end
69
+ when 'edit'
70
+ halt(404) unless path.text?
71
+ haml(
72
+ :edit,
73
+ locals: default_locals.merge(contents: path.content)
74
+ )
75
+ when 'revisions'
76
+ haml(
77
+ :revisions,
78
+ locals: default_locals.merge(revisions: path.revisions)
79
+ )
80
+ when 'raw'
81
+ send_file(path.absolute_path)
82
+ else
83
+ if path.directory?
84
+ haml(
85
+ :dir,
86
+ locals: default_locals.merge(
87
+ contents: path.file_listing,
88
+ rendered_readme: file_content_render(path.readme_path)
89
+ )
90
+ )
91
+ else
92
+ haml(
93
+ :file,
94
+ locals: default_locals.merge(
95
+ contents: file_content_render(
96
+ path.absolute_path(params[:revision])
97
+ )
98
+ )
99
+ )
100
+ end
101
+ end
102
+ end
103
+
104
+ post('/:id*') do
105
+ redirect_path =
106
+ if params[:file] # upload
107
+ path.join(params[:file][:filename])
108
+ FileUtils.mv(params[:file][:tempfile].path, path.absolute_path)
109
+ "/#{id}/#{path.relative_path}"
110
+ elsif params[:filename] # add file/directory
111
+ path.join(params[:filename])
112
+ if params[:new_file]
113
+ path.touch
114
+ "/#{id}/#{path.relative_path}?mode=edit"
115
+ elsif params[:new_directory]
116
+ path.mkdir
117
+ "/#{id}/#{path.relative_path}"
118
+ else
119
+ halt(400)
120
+ end
121
+ else
122
+ halt(400)
123
+ end
124
+ redirect to(redirect_path)
125
+ end
126
+
127
+ put('/:id*') do
128
+ redirect_path =
129
+ if params[:revision] # revert
130
+ path.revert(params[:revision])
131
+ "/#{id}/#{path.relative_path}"
132
+ elsif params[:data] && params[:message] # save
133
+ path.write(params[:data], params[:message])
134
+ "/#{id}/#{path.relative_path}"
135
+ else
136
+ # No valid inputs, do nothing and redirect.
137
+ "/#{id}/#{path.relative_path}"
138
+ end
139
+ redirect to(redirect_path)
140
+ end
141
+
142
+ delete('/:id*') do
143
+ path.remove
144
+ parent = File.dirname(path.relative_path)
145
+ parent = '' if parent == '/'
146
+ parent = nil if parent == '.'
147
+ redirect to("/#{id}#{parent}")
148
+ end
149
+ end
150
+ end
@@ -8,7 +8,7 @@ GitDocs = {
8
8
  var paths = fullPath.split("/");
9
9
  $(paths).each(function(idx, subpath) {
10
10
  var relPath = paths.slice(0, idx+1).join("/");
11
- var link = "<a href='/" + docIdx[1] + relPath + "'>" + subpath + "/</a>";
11
+ var link = "<a href='" + relPath + "'>" + subpath + "/</a>";
12
12
  fullPath = fullPath.replace(subpath + "/", link);
13
13
  });
14
14
  $('span.path').html(fullPath);
@@ -74,29 +74,6 @@ $(document).ready(function() {
74
74
  StringFormatter.autoLink();
75
75
  });
76
76
 
77
- // Redirect to edit page for new file when new file form is submitted
78
- $('form.add').live('submit', function(e){
79
- return false;
80
- });
81
-
82
- $('form.add input.file').live('click', function(e) {
83
- var docIdx = window.location.pathname.match(/\/(\d+)/);
84
- if (!docIdx) { return false; }
85
- var fullPath = $('span.path').text();
86
- var newPath = "/" + docIdx[1] + (fullPath == "/" ? "/" : fullPath + "/") + $(this).parents('form').find('input.edit').val();
87
- window.location = newPath;
88
- e.preventDefault(); return false;
89
- });
90
-
91
- $('form.add input.directory').live('click', function(e) {
92
- var docIdx = window.location.pathname.match(/\/(\d+)/);
93
- if (!docIdx) { return false; }
94
- var fullPath = $('span.path').text();
95
- var newPath = "/" + docIdx[1] + (fullPath == "/" ? "/" : fullPath + "/") + $(this).parents('form').find('input.edit').val() + '?dir=true';
96
- window.location = newPath;
97
- e.preventDefault(); return false;
98
- });
99
-
100
77
  // Link method redirection
101
78
  $('a[data-method]').live('click', function(e) {
102
79
  e.preventDefault();
@@ -111,12 +88,7 @@ $('a[data-method]').live('click', function(e) {
111
88
  form.submit();
112
89
  });
113
90
 
114
- // Deletion tab
115
- $('ul.tabs a.delete').live('click', function(e) {
116
- return confirm('Are you sure?')
117
- });
118
-
119
- // Revert a revision from the revision table
120
- $('#revisions td.revert a').live('click', function(e) {
121
- return confirm('Are you sure?')
91
+ // Confirm form submission when specified by data attribute.
92
+ $('form[data-confirm-submit]').live('submit', function(e) {
93
+ return confirm($(this).attr('data-confirm-submit'));
122
94
  });
@@ -0,0 +1,48 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'redcarpet'
4
+ require 'coderay'
5
+ require 'tilt'
6
+
7
+ module Gitdocs
8
+ module RenderingHelper
9
+ # @param [String, nil] pathname
10
+ #
11
+ # @return [nil] if the pathname is nil
12
+ # @return [String]
13
+ def file_content_render(pathname)
14
+ return unless pathname
15
+
16
+ tilt = Tilt.new(
17
+ pathname,
18
+ 1, # line number
19
+ fenced_code_blocks: true,
20
+ renderer: CodeRayify.new(filter_html: true, hard_wrap: true)
21
+ )
22
+ %(<div class="tilt">#{tilt.render}</div>)
23
+ rescue LoadError, RuntimeError # No tilt support
24
+ if path.text?
25
+ code_ray = CodeRay.scan_file(pathname)
26
+ %(<pre class="CodeRay">#{code_ray.encode(:html)}</pre>)
27
+ else
28
+ %(<embed class="inline-file" src="#{request.path_info}?mode=raw"></embed>)
29
+ end
30
+ end
31
+
32
+ class CodeRayify < ::Redcarpet::Render::Safe
33
+ # Override the safe #block_code with CodeRay, if a language is present.
34
+ #
35
+ # @param [String] code
36
+ # @param [String] langauge
37
+ #
38
+ # @return [String]
39
+ def block_code(code, language)
40
+ if language
41
+ CodeRay.scan(code, language).div
42
+ else
43
+ super(code, language)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -15,6 +15,11 @@ class Gitdocs::Repository::Path
15
15
  )
16
16
  end
17
17
 
18
+ def join(path_fragment)
19
+ @relative_path = File.join(@relative_path, path_fragment)
20
+ @absolute_path = File.join(@absolute_path, path_fragment)
21
+ end
22
+
18
23
  # Write the content to the path and create any necessary directories.
19
24
  #
20
25
  # @param [String] content
@@ -19,7 +19,7 @@ class Gitdocs::Search
19
19
  private
20
20
 
21
21
  def search_repository(repository, term)
22
- return [] if term.empty?
22
+ return [] if term.nil? || term.empty?
23
23
 
24
24
  results = []
25
25
  repository.grep(term) do |file, context|
@@ -1,18 +1,8 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
- # Disable style checks that are invalid for Renee
4
- # rubocop:disable Blocks, MultilineBlockChain
5
- #
6
- # TODO: extract the WebApp into its own class but until then...
7
- # rubocop:disable LineLength, ClassLength, CyclomaticComplexity, BlockNesting
8
-
9
3
  require 'thin'
10
- require 'renee'
11
- require 'coderay'
12
- require 'uri'
13
- require 'haml'
14
- require 'mimetype_fu'
15
- require 'launchy'
4
+ require 'gitdocs/browser_app'
5
+ require 'gitdocs/settings_app'
16
6
 
17
7
  module Gitdocs
18
8
  class Server
@@ -34,152 +24,18 @@ module Gitdocs
34
24
  end
35
25
 
36
26
  def start
37
- repositories = @repositories
38
- manager = @manager
27
+ Gitdocs::SettingsApp.set :manager, @manager
28
+ Gitdocs::BrowserApp.set :repositories, @repositories
29
+
39
30
  Thin::Logging.debug = @manager.debug
40
31
  Thin::Server.start('127.0.0.1', @port) do
41
- use Rack::Static, urls: %w(/css /js /img /doc), root: File.expand_path('../public', __FILE__)
32
+ use Rack::Static,
33
+ urls: %w(/css /js /img /doc),
34
+ root: File.expand_path('../public', __FILE__)
42
35
  use Rack::MethodOverride
43
- run Renee {
44
- if request.path_info == '/'
45
- if manager.shares.size == 1
46
- redirect! '/0'
47
- else
48
- render!(
49
- 'home',
50
- layout: 'app',
51
- locals: { shares: manager.shares, nav_state: 'home' }
52
- )
53
- end
54
- else
55
- path 'settings' do
56
- get.render!(
57
- 'settings',
58
- layout: 'app',
59
- locals: { conf: manager, nav_state: 'settings' }
60
- )
61
- post do
62
- manager.update_all(request.POST)
63
- redirect! '/settings'
64
- end
65
- end
66
-
67
- path('search').get do
68
- render!(
69
- 'search',
70
- layout: 'app',
71
- locals: { results: @search.search(request.GET['q']), nav_state: nil }
72
- )
73
- end
74
36
 
75
- path('shares') do
76
- var(:int) do |id|
77
- delete do
78
- halt(404) unless manager.remove_by_id(id)
79
- redirect!('/settings')
80
- end
81
- end
82
- end
83
-
84
- var :int do |idx|
85
- halt(404) unless repositories[idx]
86
- path = Gitdocs::Repository::Path.new(
87
- repositories[idx], URI.unescape(request.path_info)
88
- )
89
-
90
- mode = request.params['mode']
91
- default_locals = {
92
- idx: idx,
93
- root: repositories[idx].root,
94
- nav_state: nil
95
- }
96
-
97
- if mode == 'meta' # Meta
98
- halt 200, { 'Content-Type' => 'application/json' }, [path.meta.to_json]
99
- elsif mode == 'save' # Saving
100
- path.write(request.params['data'], request.params['message'])
101
- redirect!("/#{idx}/#{path.relative_path}")
102
- elsif mode == 'upload' # Uploading
103
- file = request.params['file']
104
- halt 404 unless file
105
- tempfile = file[:tempfile]
106
- filename = file[:filename]
107
- FileUtils.mv(tempfile.path, path.absolute_path)
108
- redirect!("/#{idx}/#{path.relative_path}/#{filename}")
109
- elsif !path.exist? && !request.params['dir'] # edit for non-existent file
110
- path.touch
111
- redirect!("/#{idx}/#{path.relative_path}?mode=edit")
112
- elsif !path.exist? && request.params['dir'] # create directory
113
- path.mkdir
114
- redirect!("/#{idx}/#{path.relative_path}")
115
- elsif path.directory? # list directory
116
- rendered_readme =
117
- if path.readme_path
118
- <<-EOS.gusb(/^\s+/, '')
119
- <h3>#{File.basename(path.readme_path)}</h3>
120
- <div class="tilt">#{render(path.readme_path)}</div>
121
- EOS
122
- else
123
- nil
124
- end
125
- render!(
126
- 'dir',
127
- layout: 'app',
128
- locals: default_locals.merge(
129
- contents: path.file_listing,
130
- rendered_readme: rendered_readme
131
- )
132
- )
133
- elsif mode == 'revisions' # list revisions
134
- render!(
135
- 'revisions',
136
- layout: 'app',
137
- locals: default_locals.merge(revisions: path.revisions)
138
- )
139
- elsif mode == 'revert' # revert file
140
- path.revert(request.params['revision'])
141
- redirect!("/#{idx}/#{path.relative_path}")
142
- elsif mode == 'delete' # delete file
143
- path.remove
144
- parent = File.dirname(path.relative_path)
145
- parent = '' if parent == '/'
146
- parent = nil if parent == '.'
147
- redirect!("/#{idx}#{parent}")
148
- elsif mode == 'edit' && path.text? # edit file
149
- render!(
150
- 'edit',
151
- layout: 'app',
152
- locals: default_locals.merge(contents: path.content)
153
- )
154
- elsif mode != 'raw' # render file
155
- revision_path = path.absolute_path(request.params['revision'])
156
- contents =
157
- begin # attempting to render file
158
- %(<div class="tilt">#{render(revision_path)}</div>)
159
- rescue RuntimeError # not tilt supported
160
- if path.text?
161
- <<-EOS.gsub(/^\s+/, '')
162
- <pre class="CodeRay">
163
- #{CodeRay.scan_file(revision_path).encode(:html)}
164
- </pre>
165
- EOS
166
- else
167
- %(<embed class="inline-file" src="/#{idx}#{request.path_info}?mode=raw"></embed>)
168
- end
169
- end
170
- render!(
171
- 'file',
172
- layout: 'app',
173
- locals: default_locals.merge(contents: contents)
174
- )
175
- else # other file
176
- run! Rack::File.new(repositories[idx].root)
177
- end
178
- end
179
- end
180
- }.setup {
181
- views_path(File.expand_path('../views', __FILE__))
182
- }
37
+ map('/settings') { run Gitdocs::SettingsApp }
38
+ map('/') { run Gitdocs::BrowserApp }
183
39
  end
184
40
  end
185
41
 
@@ -0,0 +1,28 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'sinatra/base'
4
+ require 'haml'
5
+ require 'yaml'
6
+ require 'mimetype_fu'
7
+
8
+ module Gitdocs
9
+ class SettingsApp < Sinatra::Base
10
+ get('/') do
11
+ haml(
12
+ :settings,
13
+ locals: { conf: settings.manager, nav_state: 'settings' }
14
+ )
15
+ end
16
+
17
+ post('/') do
18
+ settings.manager.update_all(request.POST)
19
+ redirect to('/')
20
+ end
21
+
22
+ delete('/:id') do
23
+ id = params[:id].to_i
24
+ halt(404) unless settings.manager.remove_by_id(id)
25
+ redirect to('/')
26
+ end
27
+ end
28
+ end
@@ -1,3 +1,3 @@
1
1
  module Gitdocs
2
- VERSION = '0.5.0.pre7'
2
+ VERSION = '0.5.0'
3
3
  end
@@ -11,4 +11,6 @@
11
11
  %li
12
12
  %a{ href: '?mode=revisions' } Revisions
13
13
  %li
14
- %a.delete{ href: '?mode=delete' } Delete
14
+ %form{ method: 'POST', :'data-confirm-submit' => 'Are you sure?' }
15
+ %input{ name: '_method', type: 'hidden', value: 'delete' }
16
+ %input.btn.danger{ type: 'submit', value: 'Delete' }
@@ -1,6 +1,6 @@
1
1
  - @title = root
2
2
 
3
- = partial('header', locals: { file: false, idx: idx })
3
+ = haml(:_header, locals: { file: false, idx: idx })
4
4
 
5
5
  - if contents && contents.any?
6
6
  %table#fileListing.condensed-table.zebra-striped
@@ -16,7 +16,7 @@
16
16
  %tr
17
17
  %td
18
18
  %img{ src: "/img/#{f.is_directory ? 'folder' : 'file'}.png", width: 16, height: 16 }
19
- %a{ href: "/#{idx}#{request.path_info}/#{f.name}" }
19
+ %a{ href: "#{request.path_info}/#{f.name}" }
20
20
  = f.name
21
21
  %td.author
22
22
  %td.modified
@@ -27,16 +27,16 @@
27
27
 
28
28
  .row
29
29
  .span6
30
- %form.upload{ method: 'POST', enctype: 'multipart/form-data', action: "/#{idx}#{request.path_info}?mode=upload" }
30
+ %form.upload{ method: 'POST', enctype: 'multipart/form-data' }
31
31
  %p Upload file to this directory
32
- %input.uploader{ type: 'file', value: 'Select a file', name: 'file', size: 12 }
32
+ %input.uploader{ type: 'file', value: 'Select a file', name: 'file', size: 12 }
33
33
  %input.btn.secondary{ type: 'submit', value: 'Upload file' }
34
34
  .span8
35
- %form.add
35
+ %form.add{ method: 'POST' }
36
36
  %p Add new file or directory
37
- %input.edit{ type: 'text', name: 'path', placeholder: 'somefile.md or somedir' }
38
- %input.btn.secodary.file{ type: 'submit', value: 'New file' }
39
- %input.btn.secondary.directory{ type: 'submit', value: 'New directory' }
37
+ %input{ type: 'text', name: 'filename', placeholder: 'somefile.md or somedir' }
38
+ %input.btn.secondary{ type: 'submit', name: 'new_file', value: 'New file' }
39
+ %input.btn.secondary{ type: 'submit', name: 'new_directory', value: 'New directory' }
40
40
 
41
41
  - if rendered_readme
42
42
  .contents
@@ -1,14 +1,15 @@
1
1
  - @title = root
2
2
 
3
- = partial('header', locals: { file: true, idx: idx })
3
+ = haml(:_header, locals: { file: true, idx: idx })
4
4
 
5
- %form.edit{ action: "/#{idx}#{request.path_info}?mode=save", method: 'POST', style: 'display:none;' }
5
+ %form.edit{ method: 'POST', style: 'display:none;' }
6
6
  #editor
7
7
  %textarea#data{ name: 'data' }= preserve contents
8
8
  .clearfix
9
9
  %textarea.span16#message{ name: 'message', placeholder: 'Optional commit message.' }
10
+ %input{ name: '_method', type: 'hidden', value: 'put' }
10
11
  %input.btn.primary{ type: 'submit', value: 'Save' }
11
- %a.btn.secondary{ href: "/#{idx}#{request.path_info}" } Cancel
12
+ %a.btn.secondary{ href: request.path_info } Cancel
12
13
  %input.filename{ type: 'hidden', value: request.path_info }
13
14
 
14
- = partial('ace_scripts')
15
+ = erb(:_ace_scripts)
@@ -1,6 +1,6 @@
1
1
  - @title = root
2
2
 
3
- = partial('header', locals: { file: true, idx: idx })
3
+ = haml(:_header, locals: { file: true, idx: idx })
4
4
 
5
5
  .contents
6
6
  = preserve contents
@@ -7,4 +7,4 @@
7
7
  %tr
8
8
  %td
9
9
  %a{ href: "/#{idx}" }
10
- = share.path
10
+ = share.root
File without changes
@@ -1,6 +1,6 @@
1
1
  - @title = root
2
2
 
3
- = partial('header', locals: { file: true, idx: idx })
3
+ = haml(:_header, locals: { file: true, idx: idx })
4
4
 
5
5
  - if revisions && revisions.any?
6
6
  %table#revisions.condensed-table.zebra-striped
@@ -22,7 +22,8 @@
22
22
  %td.author= r[:author]
23
23
  %td.date.reldate= r[:date].iso8601
24
24
  %td.revert
25
- %a{ href: "?mode=revert&revision=#{r[:commit]}" }
26
- = r[:commit]
25
+ %form{ method: 'POST', :'data-confirm-submit' => 'Are you sure?' }
26
+ %input{ name: '_method', type: 'hidden', value: 'put' }
27
+ %input.btn{ type: 'submit', name: 'revision', value: r[:commit] }
27
28
  - if revisions.empty?
28
29
  %p No revisions for this file could be found.
@@ -1,4 +1,4 @@
1
- - @title = "Matches for #{request.params['q'].inspect}"
1
+ - @title = "Matches for &quot;#{request.params['q']}&quot;"
2
2
  %script{ src: '/js/search.js', type: 'text/javascript', charset: 'utf-8' }
3
3
 
4
4
  .results{ 'data-query' => request.params['q'] }
@@ -1,7 +1,7 @@
1
1
  - @title = 'Settings'
2
2
  %script{ src: '/js/settings.js', type: 'text/javascript', charset: 'utf-8' }
3
3
 
4
- %form#settings{ method: 'POST', action: '/settings' }
4
+ %form#settings{ method: 'POST', action: url('/') }
5
5
  %h2 Gitdocs
6
6
  #config.field.config
7
7
  %dl
@@ -51,7 +51,7 @@
51
51
  %input{ type: 'checkbox', value: '1', name: "share[#{idx}][notification]", checked: share.notification ? 'checked' : nil }
52
52
  %span Notifications?
53
53
  .delete
54
- %a.remote_share.btn.danger{ href: "/shares/#{share.id}", :'data-method' => 'delete' }
54
+ %a.remote_share.btn.danger{ href: url("/#{share.id}"), :'data-method' => 'delete' }
55
55
  Delete
56
56
 
57
57
  %input.btn.primary{ value: 'Save', type: 'submit' }
data/lib/gitdocs.rb CHANGED
@@ -15,7 +15,6 @@ require 'gitdocs/runner'
15
15
  require 'gitdocs/server'
16
16
  require 'gitdocs/cli'
17
17
  require 'gitdocs/manager'
18
- require 'gitdocs/rendering'
19
18
  require 'gitdocs/notifier'
20
19
  require 'gitdocs/repository'
21
20
  require 'gitdocs/repository/path'
@@ -20,6 +20,8 @@ describe 'browse and edit repository file through the UI' do
20
20
  repository.commit
21
21
  write_file('local/file2', 'A5A5A5A5')
22
22
  repository.commit
23
+ write_file('local/README.md', 'hello i am a README')
24
+ repository.commit
23
25
 
24
26
  start_daemon
25
27
 
@@ -32,10 +34,14 @@ describe 'browse and edit repository file through the UI' do
32
34
  end
33
35
  end
34
36
 
37
+ it 'should show the README' do
38
+ page.must_have_content('hello i am a README')
39
+ end
40
+
35
41
  it 'should browse text files' do
36
42
  within('table#fileListing') do
37
43
  within('tbody') do
38
- page.must_have_css('tr', count: 2)
44
+ page.must_have_css('tr', count: 3)
39
45
  click_link('file1')
40
46
  end
41
47
  end
@@ -80,7 +86,7 @@ describe 'browse and edit repository file through the UI' do
80
86
  page.must_have_css('tr', count: 2)
81
87
  within(:xpath, '//tr[2]') do
82
88
  within('td.revert') do
83
- find('a').click
89
+ find('input.btn').click
84
90
  end
85
91
  end
86
92
  end
@@ -107,7 +113,7 @@ describe 'browse and edit repository file through the UI' do
107
113
  describe 'creation' do
108
114
  it 'should allow directory creation' do
109
115
  within('form.add') do
110
- fill_in('path', with: 'new_directory')
116
+ fill_in('filename', with: 'new_directory')
111
117
  click_button('directory')
112
118
  end
113
119
  within('h2') { page.must_have_content('/new_directory') }
@@ -116,7 +122,7 @@ describe 'browse and edit repository file through the UI' do
116
122
 
117
123
  it 'should allow file creation' do
118
124
  within('form.add') do
119
- fill_in('path', with: 'new_file')
125
+ fill_in('filename', with: 'new_file')
120
126
  click_button('file')
121
127
  end
122
128
 
@@ -137,10 +143,10 @@ describe 'browse and edit repository file through the UI' do
137
143
 
138
144
  it 'should allow file deletion' do
139
145
  within('table#fileListing') { within('tbody') { click_link('file1') } }
140
- click_link('Delete')
146
+ click_on('Delete')
141
147
  within('table#fileListing') do
142
148
  within('tbody') do
143
- page.must_have_css('tr', count: 1)
149
+ page.must_have_css('tr', count: 2)
144
150
  page.wont_have_content('file1')
145
151
  page.must_have_content('file2')
146
152
  end
@@ -12,6 +12,13 @@ describe Gitdocs::Repository::Path do
12
12
  FileUtils.rm_rf('tmp/unit')
13
13
  end
14
14
 
15
+ describe '#join' do
16
+ subject { path.join('new_file') }
17
+ before { subject }
18
+ it { path.relative_path.must_equal('directory/file/new_file') }
19
+ it { path.absolute_path.must_equal(absolute_local_path('new_file')) }
20
+ end
21
+
15
22
  describe '#write' do
16
23
  subject { path.write('foobar', :message) }
17
24
  before { repository.expects(:write_commit_message).with(:message) }
@@ -18,6 +18,11 @@ describe Gitdocs::Search do
18
18
  repository2.stubs(:root).returns('root')
19
19
  end
20
20
 
21
+ describe 'term is missing' do
22
+ let(:term) { nil }
23
+ it { subject.must_equal({}) }
24
+ end
25
+
21
26
  describe 'term is empty' do
22
27
  let(:term) { '' }
23
28
  it { subject.must_equal({}) }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitdocs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0.pre7
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Hull
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-08-04 00:00:00.000000000 Z
12
+ date: 2015-05-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: joshbuddy-guard
@@ -40,33 +40,33 @@ dependencies:
40
40
  - !ruby/object:Gem::Version
41
41
  version: 1.6.2
42
42
  - !ruby/object:Gem::Dependency
43
- name: renee
43
+ name: sinatra
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
46
  - - ~>
47
47
  - !ruby/object:Gem::Version
48
- version: 0.3.11
48
+ version: 1.4.5
49
49
  type: :runtime
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
53
  - - ~>
54
54
  - !ruby/object:Gem::Version
55
- version: 0.3.11
55
+ version: 1.4.5
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: redcarpet
58
58
  requirement: !ruby/object:Gem::Requirement
59
59
  requirements:
60
60
  - - ~>
61
61
  - !ruby/object:Gem::Version
62
- version: 3.1.1
62
+ version: 3.2.2
63
63
  type: :runtime
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
67
  - - ~>
68
68
  - !ruby/object:Gem::Version
69
- version: 3.1.1
69
+ version: 3.2.2
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: thor
72
72
  requirement: !ruby/object:Gem::Requirement
@@ -157,14 +157,14 @@ dependencies:
157
157
  requirements:
158
158
  - - ~>
159
159
  - !ruby/object:Gem::Version
160
- version: 4.1.4
160
+ version: 4.2.0
161
161
  type: :runtime
162
162
  prerelease: false
163
163
  version_requirements: !ruby/object:Gem::Requirement
164
164
  requirements:
165
165
  - - ~>
166
166
  - !ruby/object:Gem::Version
167
- version: 4.1.4
167
+ version: 4.2.0
168
168
  - !ruby/object:Gem::Dependency
169
169
  name: grit
170
170
  requirement: !ruby/object:Gem::Requirement
@@ -269,14 +269,14 @@ dependencies:
269
269
  requirements:
270
270
  - - ~>
271
271
  - !ruby/object:Gem::Version
272
- version: 5.4.0
272
+ version: 5.5.0
273
273
  type: :development
274
274
  prerelease: false
275
275
  version_requirements: !ruby/object:Gem::Requirement
276
276
  requirements:
277
277
  - - ~>
278
278
  - !ruby/object:Gem::Version
279
- version: 5.4.0
279
+ version: 5.5.0
280
280
  - !ruby/object:Gem::Dependency
281
281
  name: capybara_minitest_spec
282
282
  requirement: !ruby/object:Gem::Requirement
@@ -395,14 +395,14 @@ dependencies:
395
395
  requirements:
396
396
  - - ~>
397
397
  - !ruby/object:Gem::Version
398
- version: 0.6.0
398
+ version: 0.10.0
399
399
  type: :development
400
400
  prerelease: false
401
401
  version_requirements: !ruby/object:Gem::Requirement
402
402
  requirements:
403
403
  - - ~>
404
404
  - !ruby/object:Gem::Version
405
- version: 0.6.0
405
+ version: 0.10.0
406
406
  - !ruby/object:Gem::Dependency
407
407
  name: jslint_on_rails
408
408
  requirement: !ruby/object:Gem::Requirement
@@ -421,16 +421,30 @@ dependencies:
421
421
  name: coveralls
422
422
  requirement: !ruby/object:Gem::Requirement
423
423
  requirements:
424
- - - ~>
424
+ - - ! '>='
425
425
  - !ruby/object:Gem::Version
426
- version: 0.7.0
426
+ version: '0'
427
427
  type: :development
428
428
  prerelease: false
429
429
  version_requirements: !ruby/object:Gem::Requirement
430
430
  requirements:
431
- - - ~>
431
+ - - ! '>='
432
+ - !ruby/object:Gem::Version
433
+ version: '0'
434
+ - !ruby/object:Gem::Dependency
435
+ name: shotgun
436
+ requirement: !ruby/object:Gem::Requirement
437
+ requirements:
438
+ - - ! '>='
432
439
  - !ruby/object:Gem::Version
433
- version: 0.7.0
440
+ version: '0'
441
+ type: :development
442
+ prerelease: false
443
+ version_requirements: !ruby/object:Gem::Requirement
444
+ requirements:
445
+ - - ! '>='
446
+ - !ruby/object:Gem::Version
447
+ version: '0'
434
448
  description: Open-source Dropbox using Ruby and Git.
435
449
  email:
436
450
  - joshbuddy@gmail.com
@@ -451,8 +465,10 @@ files:
451
465
  - README.md
452
466
  - Rakefile
453
467
  - bin/gitdocs
468
+ - config.ru
454
469
  - gitdocs.gemspec
455
470
  - lib/gitdocs.rb
471
+ - lib/gitdocs/browser_app.rb
456
472
  - lib/gitdocs/cli.rb
457
473
  - lib/gitdocs/configuration.rb
458
474
  - lib/gitdocs/manager.rb
@@ -512,20 +528,21 @@ files:
512
528
  - lib/gitdocs/public/js/search.js
513
529
  - lib/gitdocs/public/js/settings.js
514
530
  - lib/gitdocs/public/js/util.js
515
- - lib/gitdocs/rendering.rb
531
+ - lib/gitdocs/rendering_helper.rb
516
532
  - lib/gitdocs/repository.rb
517
533
  - lib/gitdocs/repository/path.rb
518
534
  - lib/gitdocs/runner.rb
519
535
  - lib/gitdocs/search.rb
520
536
  - lib/gitdocs/server.rb
537
+ - lib/gitdocs/settings_app.rb
521
538
  - lib/gitdocs/version.rb
522
539
  - lib/gitdocs/views/_ace_scripts.erb
523
540
  - lib/gitdocs/views/_header.haml
524
- - lib/gitdocs/views/app.haml
525
541
  - lib/gitdocs/views/dir.haml
526
542
  - lib/gitdocs/views/edit.haml
527
543
  - lib/gitdocs/views/file.haml
528
544
  - lib/gitdocs/views/home.haml
545
+ - lib/gitdocs/views/layout.haml
529
546
  - lib/gitdocs/views/revisions.haml
530
547
  - lib/gitdocs/views/search.haml
531
548
  - lib/gitdocs/views/settings.haml
@@ -543,7 +560,7 @@ files:
543
560
  - test/unit/runner_test.rb
544
561
  - test/unit/search_test.rb
545
562
  - test/unit/test_helper.rb
546
- homepage: http://engineering.gomiso.com/2011/11/30/collaborate-and-track-tasks-with-ease-using-gitdocs/
563
+ homepage: https://github.com/nesquena/gitdocs
547
564
  licenses:
548
565
  - MIT
549
566
  metadata: {}
@@ -558,9 +575,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
558
575
  version: '1.9'
559
576
  required_rubygems_version: !ruby/object:Gem::Requirement
560
577
  requirements:
561
- - - ! '>'
578
+ - - ! '>='
562
579
  - !ruby/object:Gem::Version
563
- version: 1.3.1
580
+ version: '0'
564
581
  requirements: []
565
582
  rubyforge_project: gitdocs
566
583
  rubygems_version: 2.0.7
@@ -1,28 +0,0 @@
1
- # -*- encoding : utf-8 -*-
2
-
3
- # rubocop:disable LineLength
4
-
5
- # This should not exist but I cannot find any other way to prevent redcarpet
6
- # from complaining
7
- # > WARN: tilt autoloading 'redcarpet' in a non thread-safe way; explicit require'redcarpet' suggested.
8
- # > !! Unexpected error while processing request: Input must be UTF-8 or US-ASCII, ASCII-8BIT given
9
- # > Input must be UTF-8 or US-ASCII, ASCII-8BIT given
10
- # > gems/redcarpet-2.0.1/lib/redcarpet.rb:70:in `render'
11
- # > gems/redcarpet-2.0.1/lib/redcarpet.rb:70:in `to_html'
12
- # > gems/tilt-1.3.3/lib/tilt/markdown.rb:38:in `evaluate'
13
- # > gems/tilt-1.3.3/lib/tilt/markdown.rb:61:in `evaluate'
14
- # > gems/tilt-1.3.3/lib/tilt/template.rb:76:in `render'
15
-
16
- require 'redcarpet'
17
-
18
- # Compatibility class;
19
- # Creates a instance of Redcarpet with the RedCloth
20
- # API. This instance has no extensions enabled whatsoever,
21
- # and no accessors to change this. 100% pure, standard
22
- # Markdown.
23
- class RedcarpetCompat
24
- def to_html(*_dummy)
25
- @text = @text.force_encoding('utf-8') if @text.respond_to?(:force_encoding)
26
- @markdown.render(@text)
27
- end
28
- end