svn_record 1.2.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 (50) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +72 -0
  3. data/Rakefile +7 -0
  4. data/app/assets/images/svn_record/file_icon/bullet_add.png +0 -0
  5. data/app/assets/images/svn_record/file_icon/bullet_black.png +0 -0
  6. data/app/assets/images/svn_record/file_icon/bullet_blue.png +0 -0
  7. data/app/assets/images/svn_record/file_icon/bullet_delete.png +0 -0
  8. data/app/assets/images/svn_record/file_icon/bullet_diamond.png +0 -0
  9. data/app/assets/images/svn_record/file_icon/bullet_end.png +0 -0
  10. data/app/assets/images/svn_record/file_icon/bullet_go.png +0 -0
  11. data/app/assets/images/svn_record/file_icon/bullet_orange.png +0 -0
  12. data/app/assets/images/svn_record/file_icon/bullet_purple.png +0 -0
  13. data/app/assets/images/svn_record/file_icon/bullet_toggle_minus.png +0 -0
  14. data/app/assets/images/svn_record/file_icon/bullet_toggle_plus.png +0 -0
  15. data/app/assets/images/svn_record/file_icon/dir.png +0 -0
  16. data/app/assets/images/svn_record/file_icon/file.png +0 -0
  17. data/app/assets/images/svn_record/file_icon/folder.png +0 -0
  18. data/app/assets/images/svn_record/file_icon/folder_open.png +0 -0
  19. data/app/assets/images/svn_record/file_icon/folder_open_add.png +0 -0
  20. data/app/assets/images/svn_record/file_icon/folder_open_orange.png +0 -0
  21. data/app/assets/javascripts/svn_record/application.js +16 -0
  22. data/app/assets/javascripts/svn_record/change.js.coffee +4 -0
  23. data/app/assets/stylesheets/svn_record/application.css +14 -0
  24. data/app/assets/stylesheets/svn_record/site.css +396 -0
  25. data/app/controllers/svn_record/application_controller.rb +3 -0
  26. data/app/controllers/svn_record/repository/application_controller.rb +3 -0
  27. data/app/controllers/svn_record/repository/changes_controller.rb +38 -0
  28. data/app/models/svn_record/repository/change.rb +39 -0
  29. data/app/models/svn_record/repository/file.rb +20 -0
  30. data/app/models/svn_record/repository/user.rb +14 -0
  31. data/app/views/layouts/svn_record/subversion.html.slim +22 -0
  32. data/app/views/svn_record/repository/changes/_changesets_list.slim +29 -0
  33. data/app/views/svn_record/repository/changes/diff.html.slim +30 -0
  34. data/app/views/svn_record/repository/changes/entry.html.slim +18 -0
  35. data/app/views/svn_record/repository/changes/index.html.slim +34 -0
  36. data/app/views/svn_record/repository/changes/list.html.slim +2 -0
  37. data/app/views/svn_record/repository/changes/revisions.html.slim +18 -0
  38. data/config/configuration.yml +5 -0
  39. data/config/routes.rb +17 -0
  40. data/lib/Svn/helper.rb +108 -0
  41. data/lib/Svn/mime_type.rb +492 -0
  42. data/lib/Svn/scm/adapters/subversion.rb +303 -0
  43. data/lib/generators/svn_record/install_generator.rb +16 -0
  44. data/lib/generators/svn_record/templates/create_repository_changes.rb +17 -0
  45. data/lib/generators/svn_record/templates/create_repository_files.rb +21 -0
  46. data/lib/generators/svn_record/templates/create_repository_user.rb +8 -0
  47. data/lib/svn_record/engine.rb +11 -0
  48. data/lib/svn_record/version.rb +3 -0
  49. data/lib/svn_record.rb +4 -0
  50. metadata +161 -0
@@ -0,0 +1,14 @@
1
+ ##
2
+ # = 版本 修订 表
3
+ #
4
+ # == Fields
5
+ #
6
+ # id :: 用户ID
7
+ #
8
+ # == Indexes
9
+ #
10
+ class SvnRecord::Repository::User < ActiveRecord::Base
11
+ self.table_name = 'repository_users'
12
+ attr_accessible :name
13
+ has_many :changes
14
+ end
@@ -0,0 +1,22 @@
1
+ doctype html
2
+ html
3
+ head
4
+ title SVN版本管理
5
+ meta name="key_words" content="template languagea"
6
+ = stylesheet_link_tag "application", media: "all"
7
+ = javascript_include_tag 'application'
8
+ = csrf_meta_tags
9
+ body.controller-projects.action-show
10
+ #wrapper
11
+ #wrapper2
12
+ #wrapper3
13
+ #header
14
+ h1 SVN版本管理
15
+ #main-menu
16
+ ul
17
+ li = link_to '版本库', repository_changes_path, class: 'overview seelected'
18
+ = yield
19
+ #footer
20
+ #bgl
21
+ .bgr
22
+ Powered by <a href="" target="_blank"> 北京胖子很忙 &copy; 2013-2026
@@ -0,0 +1,29 @@
1
+ h2 最近的修订版本#{link_to ' (查看更多)', list_repository_changes_path(path: @path), id: 'changes_more' if action_name == 'index' && changesets.size > 10 }
2
+ = form_tag(diff_repository_changes_path, method: :get) do
3
+ table.list.entries#browser
4
+ thead
5
+ tr id="root"
6
+ th 用户ID
7
+ th
8
+ th 修订
9
+ th 提交时间
10
+ th 提交人
11
+ th 注释
12
+ tbody
13
+ - line_num = 1
14
+ - changesets.each_with_index do |ele, index|
15
+ tr
16
+ td = ele.user_id
17
+ td class="radio_span"
18
+ -if index < changesets.size - 1
19
+ span class="float-left"
20
+ = radio_button_tag 'rev', ele.revision, (line_num==1), id: "cb-#{line_num}"
21
+ - if index >= 1
22
+ span class="float_right"
23
+ = radio_button_tag 'rev_to', ele.revision, (line_num==2), id: "cbto-#{line_num}"
24
+ td class="revision" = link_to ele.revision, revisions_repository_change_path(ele.revision)
25
+ td class="age" = ele.committed_at
26
+ td class="author" = ele.committer
27
+ td class="comments" = ele.comment
28
+ - line_num +=1
29
+ = submit_tag('查看差别') if changesets.length > 1
@@ -0,0 +1,30 @@
1
+ - diff = Svn::UnifiedDiff.new(@diff, type: 'inline', max_lines: 3000, style: "")
2
+ h3 修订: "#{params[:rev]}:#{params[:rev_to]}"
3
+ h2 = menu_node(params[:path])
4
+ - if diff.blank?
5
+ p style="text-indet: 2em"
6
+ | 空
7
+ - diff.each do |table_file|
8
+ .autoscroll
9
+ table.filecontent
10
+ thead
11
+ tr
12
+ th.filename colspan="4"
13
+ = table_file.file_name
14
+ tbody
15
+ - table_file.each_line do |spacing, line|
16
+ - if spacing
17
+ tr
18
+ th.line-num
19
+ td
20
+ th.line-num
21
+ td
22
+ tr
23
+ th.line-num
24
+ = line.nb_line_left
25
+ td class="line-code #{line.type_diff_left}"
26
+ pre = line.html_line_left.html_safe
27
+ th.line-num
28
+ = line.nb_line_left
29
+ td class="line-code #{line.type_diff_right}"
30
+ pre = line.html_line_right.html_safe
@@ -0,0 +1,18 @@
1
+ div.nosidebar#main
2
+ div#content
3
+ div.contextual
4
+ h2 = menu_node(params[:path])
5
+ p
6
+ = link_to '显示/隐藏代码', "", class: 'toggle_code'
7
+ div.autoscroll
8
+ table.filecontent.syntaxhl
9
+ tbody
10
+ - line_num = 1
11
+ - syntax_highlight_lines(params[:path], Svn::CodesetUtil.to_utf8_by_setting(@content)).each do |line|
12
+ tr
13
+ th.line-num id="L#{line_num}"
14
+ a href="#L#{line_num}" = line_num
15
+ td.line-code
16
+ pre = line.html_safe
17
+ - line_num += 1
18
+ = render(partial: "/svn_record/repository/changes/changesets_list", locals: {changesets: @changesets, path:@path })
@@ -0,0 +1,34 @@
1
+ div#main.nosidebar
2
+ div#content
3
+ h2 = menu_node(@path)
4
+ table.list.entries#browser
5
+ thead
6
+ tr#root
7
+ th 名称
8
+ th 大小
9
+ th 修订
10
+ th 提交时间
11
+ th 作者
12
+ th 注释
13
+ tbody
14
+ - @entries.each do |element|
15
+ tr.entry.dir
16
+ td.filename style="padding-left: 0px;width:400px"
17
+ span.expander
18
+ | &nbsp;&nbsp;&nbsp;
19
+ = image_tag("svn_record/file_icon/#{element.kind}.png")
20
+ - if element.kind.present? && 'dir' == element.kind.to_s.strip
21
+ = link_to element.name, repository_changes_path(path: element.path)
22
+ - else
23
+ = link_to element.name, entry_repository_changes_path(path: element.path, rev: element.lastrev.name)
24
+ td.size style="width: 100px"
25
+ = element.size ? number_to_human_size(element.size) : ""
26
+ td.revision
27
+ = link_to element.lastrev.name, revisions_repository_change_path(element.lastrev.name), title: element.name
28
+ td.age style="width: 100px"
29
+ = distance_of_date_in_words(element.lastrev.time, Time.now)
30
+ td.author
31
+ = element.lastrev.author
32
+ td.comments
33
+ = element.lastrev.message
34
+ = render partial: '/svn_record/repository/changes/changesets_list', locals: { changesets: @changesets, path: @path }
@@ -0,0 +1,2 @@
1
+ h2 = menu_node(@path)
2
+ = render partial: '/svn_record/repository/changes/changesets_list', locals: { changesets: @changesets, path: @path }
@@ -0,0 +1,18 @@
1
+ div.nosidebar#main
2
+ div#content
3
+ h2 = "修订#{@changeset.revision}"
4
+ p
5
+ span.author
6
+ = "由#{@changeset.committer} 在 #{distance_of_date_in_words(@changeset.committed_at, Time.now)} 之前添加"
7
+ p = "#{@changeset.comment}"
8
+ div#related-issues
9
+ h3 相关的文件
10
+ ul#changes-legend
11
+ li.change.change-A 已添加
12
+ li.change.change-M 已修改
13
+ li.change.change-C 已复制
14
+ li.change.change-R 已重命名
15
+ li.change.change-D 已删除
16
+ div.changeset-changes
17
+ = render_changeset_changes
18
+ div style="clear:both;"
@@ -0,0 +1,5 @@
1
+ repository:
2
+ url: 'svn://localhost/project'
3
+ root_url: 'svn://localhost'
4
+ login: abc
5
+ password: 'abc'
data/config/routes.rb ADDED
@@ -0,0 +1,17 @@
1
+ SvnRecord::Engine.routes.draw do
2
+ namespace :repository do
3
+ resources :changes, only: [:index] do
4
+ collection do
5
+ get :diff
6
+ get :list
7
+ get :entry
8
+ end
9
+ member do
10
+ get :revisions
11
+ end
12
+ end
13
+ end
14
+ end
15
+ Rails.application.routes.draw do
16
+ mount SvnRecord::Engine => ""
17
+ end
data/lib/Svn/helper.rb ADDED
@@ -0,0 +1,108 @@
1
+ module ActionView
2
+ module Helpers
3
+ module DateHelper
4
+ def distance_of_date_in_words(from_date, to_date = 0, options = {})
5
+ from_date = from_date.to_date if from_date.respond_to?(:to_date)
6
+ to_date = to_date.to_date if to_date.respond_to?(:to_date)
7
+ distance_in_days = (to_date - from_date).abs
8
+
9
+ I18n.with_options :locale => options[:locale], :scope => :'datetime.distance_in_words' do |locale|
10
+ case distance_in_days
11
+ when 0..60 then locale.t :x_days, :count => distance_in_days.round
12
+ when 61..720 then locale.t :about_x_months, :count => (distance_in_days / 30).round
13
+ else locale.t :over_x_years, :count => (distance_in_days / 365).floor
14
+ end
15
+ end
16
+ end
17
+
18
+ def to_path_param(path)
19
+ str = path.to_s.split(%r{[/\\]}).select{|p| p.present?} #.join("/")
20
+ str.shift if str.length > 1
21
+ str = str.compact.join("/")
22
+ str.blank? ? nil : str
23
+ end
24
+
25
+ def render_changeset_changes
26
+ changes = @changeset.files.limit(1000).reorder('path').all.collect do |change|
27
+ case change.action
28
+ when 'A'
29
+ # Detects moved/copied files
30
+ if !change.from_path.blank?
31
+ change.action =
32
+ @changeset.files.detect {|c| c.action == 'D' && c.path == change.from_path} ? 'R' : 'C'
33
+ end
34
+ change
35
+ when 'D'
36
+ @changeset.files.detect {|c| c.from_path == change.path} ? nil : change
37
+ else
38
+ change
39
+ end
40
+ end.compact
41
+
42
+ tree = {}
43
+ changes.each do |change|
44
+ p = tree
45
+ dirs = change.path.to_s.split('/').select {|d| !d.blank?}
46
+ path = ''
47
+ dirs.each do |dir|
48
+ path += '/' + dir
49
+ p[:s] ||= {}
50
+ p = p[:s]
51
+ p[path] ||= {}
52
+ p = p[path]
53
+ end
54
+ p[:c] = change
55
+ end
56
+ render_changes_tree(tree[:s])
57
+ end
58
+
59
+ def render_changes_tree(tree)
60
+ return '' if tree.nil?
61
+ output = ''
62
+ output << '<ul>'
63
+ tree.keys.sort.each do |file|
64
+ style = 'change'
65
+ text = File.basename(h(file))
66
+ if s = tree[file][:s]
67
+ style << ' folder'
68
+ path_param = to_path_param(file)
69
+ text = link_to(h(text), repository_changes_path(path: path_param))
70
+ output << "<li class='#{style}'>#{text}"
71
+ output << render_changes_tree(s)
72
+ output << "</li>"
73
+ elsif c = tree[file][:c]
74
+ style << " change-#{c.action}"
75
+ path_param = to_path_param(c.path)
76
+ text = link_to(h(text), entry_repository_changes_path(path: path_param)) unless c.action == 'D'
77
+ text << " - #{h(c.revision)}" unless c.revision.blank?
78
+ text << ' '.html_safe + content_tag('span', h(c.from_path), :class => 'copied-from') unless c.from_path.blank?
79
+ output << "<li class='#{style}'>#{text}</li>"
80
+ end
81
+ end
82
+ output << '</ul>'
83
+ output.html_safe
84
+ end
85
+
86
+ def syntax_highlight_lines(name, content)
87
+ lines = []
88
+ syntax_highlight(name, content).each_line { |line| lines << line }
89
+ lines
90
+ end
91
+
92
+ def syntax_highlight(name, content)
93
+ Svn::SyntaxHighlighting.highlight_by_filename(content, name)
94
+ end
95
+
96
+ def menu_node(path,array = [])
97
+ link_root = link_to @root_name, repository_changes_path
98
+ return raw(link_root) unless path.present?
99
+ paths = path.split('/').map do |p|
100
+ array << p
101
+ p == path.split('/').last ? p : link_to(p, repository_changes_path(path: array.join('/')))
102
+ end
103
+ paths.unshift(link_root)
104
+ raw paths.join("/")
105
+ end
106
+ end
107
+ end
108
+ end