gitdocs 0.5.0.pre7 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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