This commit is contained in:
Mark Tareshawty 2018-11-12 18:21:38 -05:00
Родитель 62128942d0 accb04438f
Коммит d10fcb3c25
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 28DD1C473BF9D1AE
140 изменённых файлов: 898 добавлений и 730 удалений

10
.rubocop.yml Normal file
Просмотреть файл

@ -0,0 +1,10 @@
inherit_gem:
rubocop-github:
- config/default.yml
- config/rails.yml
AllCops:
TargetRubyVersion: 2.4
Performance:
enabled: true

Просмотреть файл

@ -12,3 +12,7 @@ cache:
notifications:
email: false
script:
- bundle exec rubocop -P
- bundle exec rspec

69
Gemfile
Просмотреть файл

@ -1,28 +1,30 @@
source 'https://rubygems.org'
# frozen_string_literal: true
source "https://rubygems.org"
ruby "2.4.2"
gem 'rails', '4.2.10'
gem "rails", "4.2.10"
gem 'asciidoctor', '>=1.5.4'
gem 'faraday'
gem 'faraday_middleware'
gem 'octokit'
gem 'puma'
gem 'tilt'
gem 'tire'
gem 'iso8601'
gem "asciidoctor", ">=1.5.4"
gem "faraday"
gem "faraday_middleware"
gem "iso8601"
gem "octokit"
gem "pg", "0.21.0"
gem "puma"
gem "tilt"
gem "tire"
gem 'json'
gem 'yajl-ruby'
gem 'netrc'
gem 'launchy'
gem 'diff-lcs'
gem 'redcarpet'
gem 'nokogiri'
gem "diff-lcs"
gem "json"
gem "launchy"
gem "netrc"
gem "nokogiri"
gem "redcarpet"
gem "yajl-ruby"
# Assets
gem 'webpacker'
gem 'pg', '0.21.0'
gem "webpacker"
group :development do
gem "awesome_print"
@ -32,25 +34,26 @@ group :development do
end
group :development, :test do
gem 'dotenv-rails'
gem "bullet"
gem "dotenv-rails"
gem "pry-byebug"
gem "rubocop-github"
gem "ruby-prof"
gem "sqlite3"
gem 'pry-byebug'
gem 'ruby-prof'
gem 'bullet'
end
group :test do
gem 'database_cleaner'
gem 'fabrication'
gem 'rspec-rails'
gem 'shoulda-matchers'
gem 'webmock'
gem 'vcr'
gem 'rails-perftest'
gem "database_cleaner"
gem "fabrication"
gem "rails-perftest"
gem "rspec-rails"
gem "shoulda-matchers"
gem "vcr"
gem "webmock"
end
group :production do
gem 'rack-timeout'
gem 'rails_12factor'
gem 'redis-rails'
gem "rack-timeout"
gem "rails_12factor"
gem "redis-rails"
end

Просмотреть файл

@ -40,6 +40,7 @@ GEM
ansi (1.5.0)
arel (6.0.4)
asciidoctor (1.5.6.1)
ast (2.4.0)
awesome_print (1.8.0)
better_errors (2.4.0)
coderay (>= 1.0.0)
@ -84,10 +85,11 @@ GEM
i18n (0.9.5)
concurrent-ruby (~> 1.0)
iso8601 (0.10.1)
jaro_winkler (1.5.1)
json (2.1.0)
launchy (2.4.3)
addressable (~> 2.3)
loofah (2.2.2)
loofah (2.2.3)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.0)
@ -104,7 +106,11 @@ GEM
mini_portile2 (~> 2.3.0)
octokit (4.8.0)
sawyer (~> 0.8.0, >= 0.5.3)
parallel (1.12.1)
parser (2.5.1.2)
ast (~> 2.4.0)
pg (0.21.0)
powerpack (0.1.2)
pry (0.11.3)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
@ -149,6 +155,7 @@ GEM
activesupport (= 4.2.10)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (3.0.0)
rake (12.3.1)
redcarpet (3.4.0)
redis (4.0.1)
@ -189,7 +196,18 @@ GEM
rspec-mocks (~> 3.7.0)
rspec-support (~> 3.7.0)
rspec-support (3.7.1)
rubocop (0.60.0)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10)
parser (>= 2.5, != 2.5.1.1)
powerpack (~> 0.1)
rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.4.0)
rubocop-github (0.12.0)
rubocop (~> 0.59)
ruby-prof (0.17.0)
ruby-progressbar (1.10.0)
safe_yaml (1.0.4)
sawyer (0.8.1)
addressable (>= 2.3.5, < 2.6)
@ -220,6 +238,7 @@ GEM
unf (0.1.4)
unf_ext
unf_ext (0.0.7.5)
unicode-display_width (1.4.0)
uniform_notifier (1.11.0)
vcr (4.0.0)
webmock (3.3.0)
@ -264,6 +283,7 @@ DEPENDENCIES
redcarpet
redis-rails
rspec-rails
rubocop-github
ruby-prof
shoulda-matchers
sqlite3

Просмотреть файл

@ -1,10 +1,11 @@
#!/usr/bin/env rake
# frozen_string_literal: true
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require File.expand_path('../config/application', __FILE__)
require File.expand_path("../config/application", __FILE__)
Rake.application.options.trace = true
Gitscm::Application.load_tasks

Просмотреть файл

@ -1,13 +1,15 @@
# frozen_string_literal: true
class AboutController < ApplicationController
def index
@section = "about"
set_title "About"
return render 'about/index' unless params.key?(:section)
return render "about/index" unless params.key?(:section)
begin
render "about/#{params[:section].to_s.underscore}"
render "about/#{params[:section].to_s.underscore}" # rubocop:disable GitHub/RailsControllerRenderLiteral
rescue ActionView::MissingTemplate
raise PageNotFound
end

Просмотреть файл

@ -1,14 +1,16 @@
# frozen_string_literal: true
PageNotFound = Class.new(Exception)
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :determine_os
rescue_from PageNotFound, :with => :page_not_found
rescue_from PageNotFound, with: :page_not_found
# Mac, Windows, Linux are valid
def determine_os
@os = 'linux'
@os = "linux"
end
def set_title(title)
@ -18,7 +20,7 @@ class ApplicationController < ActionController::Base
private
def page_not_found
render :file => not_found_template, :layout => false
render file: not_found_template, layout: false
end
def not_found_template

Просмотреть файл

@ -1,2 +1,4 @@
# frozen_string_literal: true
class BlogController < ApplicationController
end

Просмотреть файл

@ -1,12 +1,14 @@
# frozen_string_literal: true
class BooksController < ApplicationController
before_filter :book_resource, only: [:section, :chapter]
def show
lang = params[:lang] || "en"
if edition = params[:edition]
@book = Book.where(:code => lang, :edition => edition).first
@book = Book.where(code: lang, edition: edition).first
else
@book = Book.where(:code => lang).order("percent_complete DESC, edition DESC").first
@book = Book.where(code: lang).order("percent_complete DESC, edition DESC").first
raise PageNotFound unless @book
redirect_to "/book/#{lang}/v#{@book.edition}"
end
@ -15,18 +17,18 @@ class BooksController < ApplicationController
def link
link = params[:link]
@book = Book.where(:code => params[:lang], :edition => params[:edition]).first
@book = Book.where(code: params[:lang], edition: params[:edition]).first
raise PageNotFound unless @book
xref = @book.xrefs.where(:name => link).first
xref = @book.xrefs.where(name: link).first
raise PageNotFound unless xref
return redirect_to "/book/#{@book.code}/v#{@book.edition}/#{ERB::Util.url_encode(xref.section.slug)}##{xref.name}" unless @content
end
def section
@content = @book.sections.where(:slug => params[:slug]).first
@content = @book.sections.where(slug: params[:slug]).first
if !@content
@book = Book.where(:code => @book.code, :edition => 1).first
if @content = @book.sections.where(:slug => params[:slug]).first
@book = Book.where(code: @book.code, edition: 1).first
if @content = @book.sections.where(slug: params[:slug]).first
return redirect_to "/book/#{@book.code}/v#{@book.edition}/#{params[:slug]}"
else
return redirect_to "/book/#{@book.code}"
@ -45,8 +47,8 @@ class BooksController < ApplicationController
chapter = params[:chapter].to_i
section = params[:section].to_i
lang = params[:lang] || "en"
chapter = @book.chapters.where(:number => chapter).first
@content = chapter.sections.where(:number => section).first
chapter = @book.chapters.where(number: chapter).first
@content = chapter.sections.where(number: section).first
raise PageNotFound unless @content
return redirect_to "/book/#{lang}/v2/#{@content.slug}"
end
@ -63,10 +65,10 @@ class BooksController < ApplicationController
def book_resource
if edition = params[:edition]
@book ||= Book.where(:code => (params[:lang] || "en"), :edition => edition).first
@book ||= Book.where(code: (params[:lang] || "en"), edition: edition).first
else
@no_edition = true
@book ||= Book.where(:code => (params[:lang] || "en")).order("percent_complete DESC, edition DESC").first
@book ||= Book.where(code: (params[:lang] || "en")).order("percent_complete DESC, edition DESC").first
end
raise PageNotFound unless @book
@book

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
class CommunityController < ApplicationController
def index

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
class DocController < ApplicationController
before_filter :set_caching
@ -30,7 +32,7 @@ class DocController < ApplicationController
def watch
slug = params[:id]
@video = Gitscm::VIDEOS.select{|a| a[4] == slug}.first
@video = Gitscm::VIDEOS.select { |a| a[4] == slug }.first
if !@video
redirect_to :videos
end
@ -42,11 +44,11 @@ class DocController < ApplicationController
private
def set_caching
expires_in 10.minutes, :public => true
expires_in 10.minutes, public: true
end
def set_book
@book ||= Book.where(:code => (params[:lang] || "en")).order("percent_complete, edition DESC").first
@book ||= Book.where(code: (params[:lang] || "en")).order("percent_complete, edition DESC").first
raise PageNotFound unless @book
end

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
class DownloadsController < ApplicationController
def index
@ -5,13 +7,13 @@ class DownloadsController < ApplicationController
def latest
latest = Version.latest_version.name
render :text => latest
render text: latest
end
def guis
guis_info = GuiPresenter.instance.guis_info
render "downloads/guis/index", :locals => {:guis_info => guis_info}
render "downloads/guis/index", locals: {guis_info: guis_info}
end
def logos
@ -20,17 +22,17 @@ class DownloadsController < ApplicationController
def gui
@platform = params[:platform]
@platform = 'windows' if @platform == 'win'
@platform = "windows" if @platform == "win"
guis_info = GuiPresenter.instance.guis_info
render "downloads/guis/index", :locals => {:guis_info => guis_info}
render "downloads/guis/index", locals: {guis_info: guis_info}
end
def download
@platform = params[:platform]
@platform = 'windows' if @platform == 'win'
if @platform == 'mac'
@platform = "windows" if @platform == "win"
if @platform == "mac"
@project_url = "https://sourceforge.net/projects/git-osx-installer/"
@source_url = "https://github.com/git/git/"
@ -38,7 +40,7 @@ class DownloadsController < ApplicationController
@latest = Version.latest_version
render "downloads/downloading"
elsif @platform == 'windows'
elsif @platform == "windows"
@project_url = "https://git-for-windows.github.io/"
@source_url = "https://github.com/git-for-windows/git"
@ -57,12 +59,12 @@ class DownloadsController < ApplicationController
end
render "downloads/download_windows"
elsif @platform == 'linux'
elsif @platform == "linux"
render "downloads/download_linux"
else
redirect_to '/downloads'
redirect_to "/downloads"
end
rescue
redirect_to '/downloads'
redirect_to "/downloads"
end
end

Просмотреть файл

@ -1,20 +1,22 @@
# frozen_string_literal: true
class SiteController < ApplicationController
def index
expires_in 10.minutes, :public => true
expires_in 10.minutes, public: true
@section = "home"
@subsection = ""
end
def search
@term = sname = params['search'].to_s.downcase
@term = sname = params["search"].to_s.downcase
@data = search_term(sname)
render :partial => 'shared/search'
render partial: "shared/search"
end
def search_results
@term = sname = params['search'].to_s.downcase
@term = sname = params["search"].to_s.downcase
data = search_term(sname, true)
@top = []
@rest = []
@ -29,20 +31,20 @@ class SiteController < ApplicationController
end
@top.sort! { |a, b| b[:score] <=> a[:score] }
@rest.sort! { |a, b| b[:score] <=> a[:score] }
render "results"
render "site/results"
end
def search_term(sname, highlight = false)
data = {
:term => sname,
:results => []
term: sname,
results: []
}
if results = Doc.search(sname)
data[:results] << results
end
if results = Section.search(sname, :lang => 'en')
if results = Section.search(sname, lang: "en")
data[:results] << results
end
@ -57,8 +59,8 @@ class SiteController < ApplicationController
end
def redirect_book
current_uri = request.env['PATH_INFO']
if current_uri == '/'
current_uri = request.env["PATH_INFO"]
if current_uri == "/"
redirect_to "https://git-scm.com/book"
else
redirect_to "https://git-scm.com#{current_uri}"

Просмотреть файл

@ -1,4 +1,6 @@
require 'iso8601'
# frozen_string_literal: true
require "iso8601"
module ApplicationHelper
@ -12,12 +14,8 @@ module ApplicationHelper
end
end
def partial(part)
render part
end
def random_tagline
content_tag(:em, '-' * 2) + Gitscm::TAGLINES.sample
content_tag(:em, "-" * 2) + Gitscm::TAGLINES.sample
end
def latest_version
@ -30,19 +28,19 @@ module ApplicationHelper
end
def latest_mac_installer
@mac_installer ||= Download.latest_for 'mac'
@mac_installer ? @mac_installer.version.name : ''
@mac_installer ||= Download.latest_for "mac"
@mac_installer ? @mac_installer.version.name : ""
end
def latest_win_installer
@win_installer ||= Download.latest_for 'windows32'
@win_installer ? @win_installer.version.name : ''
@win_installer ||= Download.latest_for "windows32"
@win_installer ? @win_installer.version.name : ""
end
def latest_release_date
begin
@version ||= Version.latest_version
'(' + @version.committed.strftime("%Y-%m-%d") + ')'
"(" + @version.committed.strftime("%Y-%m-%d") + ")"
rescue
""
end
@ -52,72 +50,24 @@ module ApplicationHelper
"https://raw.github.com/git/git/master/Documentation/RelNotes/#{self.latest_version}.txt"
end
# overriding this because we're not using asset pipeline for images,
# but jason is using image_tag
# Overriding this because we're not using asset pipeline for images,
# but Jason is using image_tag
#
# See https://github.com/rails/rails/blob/6b9a1ac484a4eda1b43aba7ed864952aac743ab9/actionview/lib/action_view/helpers/asset_tag_helper.rb#L180-L219
def image_tag(image, options = {})
out = "<img src='/images/" + image + "'"
out += " width='" + options[:width].to_s + "'" if options[:width]
out += " height='" + options[:height].to_s + "'" if options[:height]
out += " />"
raw out
end
options = options.symbolize_keys
def banner(id, options = {}, &content)
dismissible = options.fetch(:dismissible, false)
duration = options.fetch(:duration, '')
class_name = options.fetch(class_name, '')
src = options[:src] = "/images/#{image}"
if dismissible and not duration.empty?
begin
duration = ISO8601::Duration.new(duration).to_seconds.round * 1000
rescue
duration = ''
end
unless src =~ /^(?:cid|data):/ || src.blank?
options[:alt] = options.fetch(:alt) { image_alt(src) }
end
config = {
:id => "banner-#{id}",
:duration => duration
}
out = "<div class=\"banner-message #{class_name}\" id=\"#{config[:id]}\">"
out += capture(&content)
if dismissible
js = <<-END_JS
<script>
(function(config) {
var banner = document.getElementById(config.id);
var button = banner.querySelector('.dismiss');
var dismissed = parseInt(localStorage.getItem(config.id),10);
var duration = config.duration;
if (dismissed && (!duration || (dismissed > Date.now() - duration))) {
return banner.parentElement.removeChild(banner);
}
button && button.addEventListener('click', function() {
localStorage.setItem(config.id, Date.now());
return banner.parentElement.removeChild(banner);
});
})(#{JSON.generate(config)});
</script>
END_JS
label = "Dismiss this message"
button = <<-END_BUTTON
<button type="button"
class="dismiss"
aria-controls="#{config[:id]}"
aria-label="#{label}">&times;</button>
END_BUTTON
out += button
out += js
end
out += "</div>"
raw out
tag("img", options)
end
def banner_duration(duration)
return "" unless duration.present?
ISO8601::Duration.new(duration).to_seconds.round * 1000
end
end

Просмотреть файл

@ -1,2 +1,4 @@
# frozen_string_literal: true
module BooksHelper
end

Просмотреть файл

@ -1,12 +1,14 @@
# frozen_string_literal: true
module DocHelper
def man(name, options = {})
link_to options[:text] || name.gsub(/^git-/, ''), doc_file_path(:file => name), :class => options[:class]
link_to options[:text] || name.gsub(/^git-/, ""), doc_file_path(file: name), class: options[:class]
end
def linkify(content, section)
next_page = section.next_slug
prev_page = section.prev_slug
content.gsub('[[nav-next]]', next_page).gsub('[[nav-prev]]', prev_page)
content.gsub("[[nav-next]]", next_page).gsub("[[nav-prev]]", prev_page)
end
end

Просмотреть файл

@ -1,9 +1,11 @@
# frozen_string_literal: true
module GuiHelper
@@conv = { "Mac" => "mac", "Windows" => "windows", "Linux" => "linux", "Android" => "android", "iOS" => "ios"}
def platformsToCssClass(platforms)
def platforms_to_css_class(platforms)
platforms.map { |p| @@conv[p] }
end
end
end

Просмотреть файл

@ -1,8 +1,10 @@
# frozen_string_literal: true
module SiteHelper
def highlight_no_html(high)
strip_tags(high.to_s)
.gsub('[highlight]', '<span class="highlight">')
.gsub('[xhighlight]', '</span>')
.gsub("[highlight]", '<span class="highlight">')
.gsub("[xhighlight]", "</span>")
end
def rchart(title, data, extra = nil)
@ -36,11 +38,11 @@ module SiteHelper
def gchart(title, data)
labels = data.map {|v| v[0] }
vals = data.map {|v| v[1] }
v = vals.join(',')
l = labels.join('|')
labels = data.map { |v| v[0] }
vals = data.map { |v| v[1] }
v = vals.join(",")
l = labels.join("|")
scale = vals.max
c = "<img src=\"https://chart.googleapis.com/chart?"

Просмотреть файл

@ -0,0 +1,5 @@
# frozen_string_literal: true
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
end

Просмотреть файл

@ -1,11 +1,13 @@
# frozen_string_literal: true
# t.string :code
# t.timestamps
class Book < ActiveRecord::Base
class Book < ApplicationRecord
has_many :chapters
has_many :sections, :through => :chapters
has_many :sections, through: :chapters
has_many :xrefs
def has_edition(number)
Book.where(:edition => number, :code => self.code).count > 0
Book.where(edition: number, code: self.code).count > 0
end
end

Просмотреть файл

@ -1,24 +1,26 @@
# frozen_string_literal: true
# t.string :title
# t.integer :number
# t.belongs_to :book
# t.timestamps
class Chapter < ActiveRecord::Base
class Chapter < ApplicationRecord
default_scope { order(:number) }
belongs_to :book
has_many :sections
has_many :chapters, :through => :book
has_many :chapters, through: :book
def prev
return false unless self.number
num = self.number - 1
return self.chapters.where(:number => num).first if num > 0
return self.chapters.where(number: num).first if num > 0
false
end
def next
return false unless self.number
num = self.number + 1
return self.chapters.where(:number => num).first if num > 0
return self.chapters.where(number: num).first if num > 0
false
end
@ -31,8 +33,8 @@ class Chapter < ActiveRecord::Base
end
def cs_number
if self.chapter_type == 'appendix'
'A' + self.chapter_number
if self.chapter_type == "appendix"
"A" + self.chapter_number
else
self.chapter_number
end

Просмотреть файл

@ -1,13 +1,15 @@
require 'diff/lcs'
require 'pp'
require 'searchable'
# frozen_string_literal: true
require "diff/lcs"
require "pp"
require "searchable"
# t.text :blob_sha
# t.text :plain
# t.text :html
# t.timestamps
class Doc < ActiveRecord::Base
class Doc < ApplicationRecord
include Searchable
has_many :doc_versions

Просмотреть файл

@ -1,10 +1,12 @@
# frozen_string_literal: true
# t.string :name
# t.timestamps
class DocFile < ActiveRecord::Base
class DocFile < ApplicationRecord
has_many :doc_versions
has_many :versions, through: :doc_versions
scope :with_includes, ->{ includes(:doc_versions => [:doc, :version]) }
scope :with_includes, -> { includes(doc_versions: [:doc, :version]) }
def version_changes(limit_size = 100)
unchanged_versions = []
@ -33,6 +35,6 @@ class DocFile < ActiveRecord::Base
# TODO: parse file for description
def description
''
""
end
end

Просмотреть файл

@ -1,17 +1,19 @@
# frozen_string_literal: true
# t.belongs_to :version
# t.belongs_to :doc
# t.belongs_to :doc_file
# t.timestamps
class DocVersion < ActiveRecord::Base
class DocVersion < ApplicationRecord
belongs_to :doc
belongs_to :version
belongs_to :doc_file
scope :with_includes, -> { includes(:doc) }
scope :for_version, ->(version){ joins(:version).where(versions: {name: version}).limit(1).first }
scope :latest_version, ->{ joins(:version).order("versions.vorder DESC").limit(1).first }
scope :version_changes, ->{ with_includes.joins(:version).order("versions.vorder DESC") }
scope :for_version, ->(version) { joins(:version).where(versions: {name: version}).limit(1).first }
scope :latest_version, -> { joins(:version).order("versions.vorder DESC").limit(1).first }
scope :version_changes, -> { with_includes.joins(:version).order("versions.vorder DESC") }
delegate :name, to: :version
delegate :committed, to: :version
@ -28,7 +30,7 @@ class DocVersion < ActiveRecord::Base
diff.first.each do |change|
adds += 1 if change.action == "+"
mins += 1 if change.action == "-"
total += 1
total += 1
end
if total > 8
min = (8.0 / total)
@ -38,24 +40,24 @@ class DocVersion < ActiveRecord::Base
[adds, mins, (8 - total)]
rescue
[0, 0, 8]
end
end
end
def index
file = self.doc_file
doc = self.doc
data = {
'id' => file.name,
'type' => 'doc',
'name' => file.name,
'blob_sha' => doc.blob_sha,
'text' => doc.plain,
"id" => file.name,
"type" => "doc",
"name" => file.name,
"blob_sha" => doc.blob_sha,
"text" => doc.plain,
}
begin
Tire.index ELASTIC_SEARCH_INDEX do
store data
end
rescue Exception => e
rescue StandardError
nil
end
end

Просмотреть файл

@ -1,13 +1,15 @@
# frozen_string_literal: true
# t.string :url
# t.string :filename
# t.string :platform
# t.references :version
# t.timestamp :release_date
# t.timestamps
class Download < ActiveRecord::Base
class Download < ApplicationRecord
belongs_to :version
def self.latest_for(platform)
includes(:version).where('platform=?', platform).order('versions.vorder DESC').order('downloads.release_date DESC').first
includes(:version).where("platform=?", platform).order("versions.vorder DESC").order("downloads.release_date DESC").first
end
end

Просмотреть файл

@ -1,4 +1,6 @@
require 'searchable'
# frozen_string_literal: true
require "searchable"
# t.string :title
# t.integer :number
@ -8,24 +10,24 @@ require 'searchable'
# t.string :source_url
# t.belongs_to :chapter
# t.timestamps
class Section < ActiveRecord::Base
class Section < ApplicationRecord
include Searchable
default_scope { order(:number) }
belongs_to :chapter
has_one :book, :through => :chapter
has_one :book, through: :chapter
before_save :set_slug
after_save :index
has_many :sections, :through => :chapter
has_many :sections, through: :chapter
has_many :xrefs
def set_slug
if self.title
title = (self.chapter.title + '-' + self.title)
title = (self.chapter.title + "-" + self.title)
title = self.chapter.title if self.title.empty?
title = title.gsub(/\(|\)|\./,'').gsub(/\s+/, '-').gsub('&#39;', "-")
title = title.gsub(/\(|\)|\./, "").gsub(/\s+/, "-").gsub("&#39;", "-")
self.slug = title
end
end
@ -33,7 +35,7 @@ class Section < ActiveRecord::Base
def prev_slug
lang = self.book.code
prev_number = self.number - 1
if section = self.sections.where(:number => prev_number).first
if section = self.sections.where(number: prev_number).first
return "/book/#{lang}/v#{self.book.edition}/#{ERB::Util.url_encode(section.slug)}"
else
# find previous chapter
@ -43,13 +45,13 @@ class Section < ActiveRecord::Base
end
end
end
'/book'
"/book"
end
def next_slug
lang = self.book.code
next_number = self.number + 1
if section = self.sections.where(:number => next_number).first
if section = self.sections.where(number: next_number).first
return "/book/#{lang}/v#{self.book.edition}/#{ERB::Util.url_encode(section.slug)}"
else
if ch = self.chapter.next
@ -63,29 +65,29 @@ class Section < ActiveRecord::Base
end
def cs_number
if self.chapter.chapter_type == 'appendix'
'A' + self.chapter.chapter_number.to_s + '.' + self.number.to_s
if self.chapter.chapter_type == "appendix"
"A" + self.chapter.chapter_number.to_s + "." + self.number.to_s
else
self.chapter.chapter_number.to_s + '.' + self.number.to_s
self.chapter.chapter_number.to_s + "." + self.number.to_s
end
end
def index
code = self.book.code
data = {
'id' => "#{code}---#{self.slug}",
'type' => "book",
'chapter' => self.chapter.title,
'section' => self.title,
'number' => self.cs_number,
'lang' => code,
'html' => self.html,
"id" => "#{code}---#{self.slug}",
"type" => "book",
"chapter" => self.chapter.title,
"section" => self.title,
"number" => self.cs_number,
"lang" => code,
"html" => self.html,
}
begin
Tire.index ELASTIC_SEARCH_INDEX do
store data
end
rescue Exception => e
rescue StandardError
nil
end
end

Просмотреть файл

@ -1,13 +1,15 @@
# frozen_string_literal: true
# t.string :name
# t.string :commit_sha
# t.string :tree_sha
# t.datetime :committed
# t.timestamps
class Version < ActiveRecord::Base
validates :name, :uniqueness => true
class Version < ApplicationRecord
validates :name, uniqueness: true
has_many :doc_versions
has_many :docs, :through => :doc_versions
has_many :docs, through: :doc_versions
has_many :downloads
before_save :save_version_order
@ -17,13 +19,13 @@ class Version < ActiveRecord::Base
end
def self.latest_version
Version.order('versions.vorder DESC').limit(1).first
Version.order("versions.vorder DESC").limit(1).first
end
def self.version_to_num(version)
version_int = 0.0
mult = 1000000
numbers = version.to_s.split('.')
numbers = version.to_s.split(".")
numbers.each do |x|
version_int += x.to_f * mult
mult = mult / 100.0

Просмотреть файл

@ -1,4 +1,6 @@
class Xref < ActiveRecord::Base
# frozen_string_literal: true
class Xref < ApplicationRecord
belongs_to :book
belongs_to :section
end

Просмотреть файл

@ -1,7 +1,9 @@
# frozen_string_literal: true
class GuiPresenter
def read_gui_yaml
yaml = YAML.load_file('resources/guis.yml')
yaml = YAML.load_file("resources/guis.yml")
return yaml["guis"]
end

Просмотреть файл

@ -1,13 +1,15 @@
require 'rss'
# frozen_string_literal: true
require "rss"
class DownloadService
# [OvD] note that Google uses Atom & Sourceforge uses RSS
# however this isn't relevant when parsing the feeds for
# name, version, url & date with Feedzirra
SOURCEFORGE_URL = 'https://sourceforge.net/projects/git-osx-installer/rss?limit=20'.freeze
SOURCEFORGE_URL = "https://sourceforge.net/projects/git-osx-installer/rss?limit=20".freeze
GIT_FOR_WINDOWS_REGEX = /^(Portable|)Git-(\d+\.\d+\.\d+(?:\.\d+)?)-(?:.+-)*(32|64)-bit(?:\..*)?\.exe/
GIT_FOR_WINDOWS_NAME_WITH_OWNER = 'git-for-windows/git'.freeze
GIT_FOR_WINDOWS_NAME_WITH_OWNER = "git-for-windows/git".freeze
class << self
def sourceforge_project_download_url(project, filename)
@ -46,12 +48,12 @@ class DownloadService
def download_mac_versions
files_from_sourceforge(SOURCEFORGE_URL).each do |url, date|
name = url.split('/')[-2]
name = url.split("/")[-2]
match = /git-(.*?)-/.match(name)
next unless match
url = sourceforge_project_download_url('git-osx-installer', name)
url = sourceforge_project_download_url("git-osx-installer", name)
name = match[1]
version = find_version_by_name(name)
@ -59,7 +61,7 @@ class DownloadService
if version
find_or_create_download(
filename: name,
platform: 'mac',
platform: "mac",
release_date: date,
version: version,
url: url
@ -73,7 +75,7 @@ class DownloadService
private
def files_from_github(repository)
@octokit = Octokit::Client.new(:login => ENV['API_USER'], :password => ENV['API_PASS'])
@octokit = Octokit::Client.new(login: ENV["API_USER"], password: ENV["API_PASS"])
downloads = []
releases = @octokit.releases(repository)

Просмотреть файл

@ -32,7 +32,7 @@
<div class="two-column">
<ul class="gui-thumbnails">
<% guis_info.sort_by { |g| g["order"] }.each do |gui| %>
<li class="<%= platformsToCssClass(gui["platforms"]).join(' ') %>">
<li class="<%= platforms_to_css_class(gui["platforms"]).join(' ') %>">
<%= link_to(image_tag("#{gui['image_tag']}", {:width => '294', :height => '166'}), "#{gui['url']}") %>
<h4>
<%= link_to("#{gui['name']}", "#{gui['url']}") %>

Просмотреть файл

@ -32,7 +32,7 @@
</p>
</div>
<div class="column-right">
<%= partial 'shared/monitor' %>
<%= render partial: 'shared/monitor' %>
</div>
</div>
<div class="callout" id="more-downloads">

Просмотреть файл

@ -19,6 +19,11 @@
<body class="sans-serif bg-tan dark-gray mw9 center page-body js-page-body" id="<%= @section %>">
<%= render partial: "shared/header" %>
<%# <%= render layout: "shared/banner", locals: { id: "freedom-conservancy", dismissable: true, duration: 1 } do %>
<!-- Fill in banner content here -->
<%# <% end %>
<div class="page-overlay">
<%= yield %>
<%= render partial: "shared/footer" %>

Просмотреть файл

@ -0,0 +1,26 @@
<div class="banner-message" id="banner-<%= local_assigns[:id] %>">
<%= yield %>
<% if local_assigns[:dismissable] %>
<button type="button" class="dismiss" aria-controls="banner-<%= local_assigns[:id] %>" aria-label="dismiss-this-button">&times;</button>
<%= javascript_tag do %>
(function(config) {
var banner = document.getElementById(config.id);
var button = banner.querySelector('.dismiss');
var dismissed = parseInt(localStorage.getItem(config.id),10);
var duration = config.duration;
if (dismissed && (!duration || (dismissed > Date.now() - duration))) {
return banner.parentElement.removeChild(banner);
}
button && button.addEventListener('click', function() {
localStorage.setItem(config.id, Date.now());
return banner.parentElement.removeChild(banner);
});
})({ "id": "banner-<%= local_assigns[:id].to_s %>", "duration": "<%= banner_duration(local_assigns[:duration]) %>" });
<% end %>
<% end %>
</div>

Просмотреть файл

@ -3,6 +3,7 @@
<li><%= man("gitattributes", :class => "link hover-u blue") %></li>
<li><%= man("giteveryday", :text => "Everyday Git", :class => "link hover-u blue") %></li>
<li><%= man("gitglossary", :text => "Glossary", :class => "link hover-u blue") %></li>
<li><%= man('githooks', :class => "link hover-u blue") %></li>
<li><%= man("gitignore", :class => "link hover-u blue") %></li>
<li><%= man("gitmodules", :class => "link hover-u blue") %></li>
<li><%= man("gitrevisions", :text => "Revisions", :class => "link hover-u blue") %></li>

Просмотреть файл

@ -43,7 +43,7 @@
</div>
</section>
<section id="front-downloads">
<%= partial 'shared/monitor' %>
<%= render partial: 'shared/monitor' %>
<table>
<tr>
<td nowrap="true"><%= link_to "Graphical UIs", "/downloads/guis", class: 'icon gui', id: 'gui-link' %></td>
@ -73,7 +73,7 @@
<li><%= link_to "Linux", "https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git", class: 'linux' %></li>
<li><%= link_to "Ruby on Rails", "https://github.com/rails/rails", class: 'rails' %></li>
<li><%= link_to "Qt", "https://code.qt.io/cgit/", class: 'qt' %></li>
<li><%= link_to "Gnome", "https://git.gnome.org/browse/", class: 'gnome' %></li>
<li><%= link_to "Gnome", "https://gitlab.gnome.org/GNOME", class: 'gnome' %></li>
<li><%= link_to "Eclipse", "https://git.eclipse.org/c/", class: 'eclipse' %></li>
<li><%= link_to "KDE", "https://quickgit.kde.org/", class: 'kde' %></li>
<li><%= link_to "X", "https://cgit.freedesktop.org/xorg/xserver/", class: 'x' %></li>

Просмотреть файл

@ -1,105 +1,5 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
#
# This file was generated by Bundler.
#
# The application 'bundle' is installed as part of a gem, and
# this file is here to facilitate running it.
#
require "rubygems"
m = Module.new do
module_function
def invoked_as_script?
File.expand_path($0) == File.expand_path(__FILE__)
end
def env_var_version
ENV["BUNDLER_VERSION"]
end
def cli_arg_version
return unless invoked_as_script? # don't want to hijack other binstubs
return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
bundler_version = nil
update_index = nil
ARGV.each_with_index do |a, i|
if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
bundler_version = a
end
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
bundler_version = $1 || ">= 0.a"
update_index = i
end
bundler_version
end
def gemfile
gemfile = ENV["BUNDLE_GEMFILE"]
return gemfile if gemfile && !gemfile.empty?
File.expand_path("../../Gemfile", __FILE__)
end
def lockfile
lockfile =
case File.basename(gemfile)
when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
else "#{gemfile}.lock"
end
File.expand_path(lockfile)
end
def lockfile_version
return unless File.file?(lockfile)
lockfile_contents = File.read(lockfile)
return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
Regexp.last_match(1)
end
def bundler_version
@bundler_version ||= begin
env_var_version || cli_arg_version ||
lockfile_version || "#{Gem::Requirement.default}.a"
end
end
def load_bundler!
ENV["BUNDLE_GEMFILE"] ||= gemfile
# must dup string for RG < 1.8 compatibility
activate_bundler(bundler_version.dup)
end
def activate_bundler(bundler_version)
if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0")
bundler_version = "< 2"
end
gem_error = activation_error_handling do
gem "bundler", bundler_version
end
return if gem_error.nil?
require_error = activation_error_handling do
require "bundler/version"
end
return if require_error.nil? && Gem::Requirement.new(bundler_version).satisfied_by?(Gem::Version.new(Bundler::VERSION))
warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`"
exit 42
end
def activation_error_handling
yield
nil
rescue StandardError, LoadError => e
e
end
end
m.load_bundler!
if m.invoked_as_script?
load Gem.bin_path("bundler", "bundle")
end
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
load Gem.bin_path("bundler", "bundle")

Просмотреть файл

@ -1,4 +1,6 @@
#!/usr/bin/env ruby
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
require 'rails/commands'
# frozen_string_literal: true
APP_PATH = File.expand_path("../../config/application", __FILE__)
require_relative "../config/boot"
require "rails/commands"

Просмотреть файл

@ -1,4 +1,6 @@
#!/usr/bin/env ruby
require_relative '../config/boot'
require 'rake'
# frozen_string_literal: true
require_relative "../config/boot"
require "rake"
Rake.application.run

Просмотреть файл

@ -1,4 +1,5 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
ENV["NODE_ENV"] ||= ENV["NODE_ENV"] || "development"

Просмотреть файл

@ -1,4 +1,5 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
ENV["NODE_ENV"] ||= ENV["NODE_ENV"] || "development"

Просмотреть файл

@ -1,4 +1,6 @@
# frozen_string_literal: true
# This file is used by Rack-based servers to start the application.
require ::File.expand_path('../config/environment', __FILE__)
require ::File.expand_path("../config/environment", __FILE__)
run Gitscm::Application

Просмотреть файл

@ -1,6 +1,8 @@
require File.expand_path('../boot', __FILE__)
# frozen_string_literal: true
require 'rails/all'
require File.expand_path("../boot", __FILE__)
require "rails/all"
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.

Просмотреть файл

@ -1,3 +1,5 @@
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
# frozen_string_literal: true
require 'bundler/setup' # Set up gems listed in the Gemfile.
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
require "bundler/setup" # Set up gems listed in the Gemfile.

Просмотреть файл

@ -1,5 +1,7 @@
# frozen_string_literal: true
# Load the Rails application.
require File.expand_path('../application', __FILE__)
require File.expand_path("../application", __FILE__)
# Initialize the Rails application.
Rails.application.initialize!

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
Rails.application.configure do
# Verifies that versions and hashed value of the package contents in the project's package.json
config.webpacker.check_yarn_integrity = true

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
Rails.application.configure do
# Verifies that versions and hashed value of the package contents in the project's package.json
config.webpacker.check_yarn_integrity = false
@ -25,8 +27,8 @@ Rails.application.configure do
# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?
config.static_cache_control = 'public, max-age=31536000'
config.serve_static_files = ENV["RAILS_SERVE_STATIC_FILES"].present?
config.static_cache_control = "public, max-age=31536000"
# Compress JavaScripts and CSS.
config.assets.js_compressor = :uglifier
@ -59,7 +61,7 @@ Rails.application.configure do
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
# Use a different cache store in production.
config.cache_store = :redis_store, ENV['REDIS_URL']
config.cache_store = :redis_store, ENV["REDIS_URL"]
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.action_controller.asset_host = 'http://assets.example.com'

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
@ -14,7 +16,7 @@ Rails.application.configure do
# Configure static file server for tests with Cache-Control for performance.
config.serve_static_files = true
config.static_cache_control = 'public, max-age=3600'
config.static_cache_control = "public, max-age=3600"
# Show full error reports and disable caching.
config.consider_all_requests_local = true

Просмотреть файл

@ -1,7 +1,9 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
# Version of your assets, change this if you want to expire all your assets.
Rails.application.config.assets.version = '1.0'
Rails.application.config.assets.version = "1.0"
# Add additional assets to the asset load path
# Rails.application.config.assets.paths << Emoji.images_path

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
Rails.application.config.action_dispatch.cookies_serializer = :json

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
Tire.configure do
url (ENV["BONSAI_URL"] || "http://0.0.0.0:9200")
end

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
# Configure sensitive parameters which will be filtered from the log file.

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
# Add new inflection rules using the following format. Inflections

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
# Add new mime types for use in respond_to blocks:

Просмотреть файл

@ -1,7 +1,9 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
# Your secret key for verifying the integrity of signed cookies.
# If you change this key, all old signed cookies will become invalid!
# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
Gitscm::Application.config.secret_token = '7578dada6e7d1904ecd87c0ac3ceffd14dbafa72a168be1772c4183db2d197b0f3fa330e8e9ea3288a4f59b08c5b8742984320fdac54a51a0986c59b4af512af'
Gitscm::Application.config.secret_token = "7578dada6e7d1904ecd87c0ac3ceffd14dbafa72a168be1772c4183db2d197b0f3fa330e8e9ea3288a4f59b08c5b8742984320fdac54a51a0986c59b4af512af"

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
Rails.application.config.session_store :cookie_store, key: '_gitscm_session'
Rails.application.config.session_store :cookie_store, key: "_gitscm_session"

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
# This file contains settings for ActionController::ParamsWrapper which

Просмотреть файл

@ -6,16 +6,16 @@
# the maximum value specified for Puma. Default is set to 5 threads for minimum
# and maximum; this matches the default thread size of Active Record.
#
threads_count = Integer(ENV.fetch('RAILS_MAX_THREADS') { 5 })
threads_count = Integer(ENV.fetch("RAILS_MAX_THREADS") { 5 })
threads threads_count, threads_count
# Specifies the `port` that Puma will listen on to receive requests; default is 5000.
#
port ENV.fetch('PORT') { 5000 }
port ENV.fetch("PORT") { 5000 }
# Specifies the `environment` that Puma will run in.
#
environment ENV.fetch('RAILS_ENV') { 'development' }
environment ENV.fetch("RAILS_ENV") { "development" }
# Specifies the number of `workers` to boot in clustered mode.
# Workers are forked webserver processes. If using threads and workers together
@ -23,7 +23,7 @@ environment ENV.fetch('RAILS_ENV') { 'development' }
# Workers do not work on JRuby or Windows (both of which do not support
# processes).
#
workers Integer(ENV.fetch('WEB_CONCURRENCY') { 3 })
workers Integer(ENV.fetch("WEB_CONCURRENCY") { 3 })
# Use the `preload_app!` method when specifying a `workers` number.
# This directive tells Puma to first boot the application and load code

Просмотреть файл

@ -1,115 +1,115 @@
# frozen_string_literal: true
Rails.application.routes.draw do
constraints(host: 'whygitisbetterthanx.com') do
root to: 'site#redirect_wgibtx', as: :whygitisbetterthanx
constraints(host: "whygitisbetterthanx.com") do
root to: "site#redirect_wgibtx", as: :whygitisbetterthanx
end
constraints(host: 'progit.org') do
root to: 'site#redirect_book', as: :progit
get '*path' => 'site#redirect_book'
constraints(host: "progit.org") do
root to: "site#redirect_book", as: :progit
get "*path" => "site#redirect_book"
end
get 'site/index'
get "site/index"
scope :manual, as: :manual do
get '/' => 'doc#index'
get '/ext' => 'doc#ext'
get "/" => "doc#index"
get "/ext" => "doc#ext"
end
scope :manuals do
get '/' => 'doc#ref'
get "/" => "doc#ref"
get '/howto/:file', to: redirect { |path_params, _req|
get "/howto/:file", to: redirect { |path_params, _req|
"https://github.com/git/git/blob/master/Documentation/howto/#{path_params[:file]}.txt"
}
get '/:file.html' => 'doc#man', :as => :doc_file_html, :file => /[\w\-\.]+/
get '/:file' => 'doc#man', :as => :doc_file, :file => /[\w\-\.]+/
get "/:file.html" => "doc#man", :as => :doc_file_html, :file => /[\w\-\.]+/
get "/:file" => "doc#man", :as => :doc_file, :file => /[\w\-\.]+/
get '/:file/:version' => 'doc#man', :version => %r{[^\/]+}
get "/:file/:version" => "doc#man", :version => %r{[^\/]+}
end
scope :doc, as: :doc do
get '/' => redirect('/manual')
get '/ext' => redirect('/manual/ext')
get "/" => redirect("/manual")
get "/ext" => redirect("/manual/ext")
end
scope :docs do
get '/' => redirect('/manuals')
get "/" => redirect("/manuals")
get '/howto/:file', to: redirect { |path_params, _req|
get "/howto/:file", to: redirect { |path_params, _req|
"https://github.com/git/git/blob/master/Documentation/howto/#{path_params[:file]}.txt"
}
get '/:file.html' => redirect('/manuals/%<file>s.html'), :file => /[\w\-\.]+/
get '/:file' => redirect('/manuals/%<file>s'), :file => /[\w\-\.]+/
get "/:file.html" => redirect("/manuals/%<file>s.html"), :file => /[\w\-\.]+/
get "/:file" => redirect("/manuals/%<file>s"), :file => /[\w\-\.]+/
get '/:file/:version' => redirect('/manuals/%<file>s/%<version>s'), :version => %r{[^\/]+}
get "/:file/:version" => redirect("/manuals/%<file>s/%<version>s"), :version => %r{[^\/]+}
end
%w[man ref git].each do |path|
get "/#{path}/:file" => redirect('/docs/%<file>s')
get "/#{path}/:file/:version" => redirect('/docs/%<file>s/%<version>s'), :version => %r{[^\/]+}
get "/#{path}/:file" => redirect("/docs/%<file>s")
get "/#{path}/:file/:version" => redirect("/docs/%<file>s/%<version>s"), :version => %r{[^\/]+}
end
resource :book do
get '/ch:chapter-:section.html' => 'books#chapter'
get '/:lang/ch:chapter-:section.html' => 'books#chapter'
get "/ch:chapter-:section.html" => "books#chapter"
get "/:lang/ch:chapter-:section.html" => "books#chapter"
get '/index' => redirect('/book')
get '/commands' => redirect('/docs')
get "/index" => redirect("/book")
get "/commands" => redirect("/docs")
nested do
scope ':lang' do
get '/v:edition' => 'books#show'
get '/v:edition/:slug' => 'books#section'
get '/v:edition/:chapter/:link' => 'books#link', chapter: /(ch|app)\d+/
scope ":lang" do
get "/v:edition" => "books#show"
get "/v:edition/:slug" => "books#section"
get "/v:edition/:chapter/:link" => "books#link", :chapter => /(ch|app)\d+/
get '/' => 'books#show', as: :lang
get '/:slug' => 'books#section', as: :slug
get "/" => "books#show", :as => :lang
get "/:slug" => "books#section", :as => :slug
end
end
end
scope :download, as: :download do
get '/' => 'downloads#index'
get '/:platform' => 'downloads#download'
get '/gui/:platform' => 'downloads#gui'
get "/" => "downloads#index"
get "/:platform" => "downloads#download"
get "/gui/:platform" => "downloads#gui"
end
resources :downloads, only: [:index] do
collection do
get '/guis' => 'downloads#guis'
get '/installers' => 'downloads#installers'
get '/logos' => 'downloads#logos'
get '/latest' => 'downloads#latest'
get "/guis" => "downloads#guis"
get "/installers" => "downloads#installers"
get "/logos" => "downloads#logos"
get "/latest" => "downloads#latest"
end
end
get '/blog' => 'blog#index'
get '/blog/*post' => redirect('/blog')
get '/:year/:month/:day/:slug' => redirect('/blog'), :year => /\d{4}/, :month => /\d{2}/, :day => /\d{2}/
get "/blog" => "blog#index"
get "/blog/*post" => redirect("/blog")
get "/:year/:month/:day/:slug" => redirect("/blog"), :year => /\d{4}/, :month => /\d{2}/, :day => /\d{2}/
get '/about' => 'about#index'
get '/about/:section' => 'about#index'
get "/about" => "about#index"
get "/about/:section" => "about#index"
get '/videos' => 'doc#videos'
get '/video/:id' => 'doc#watch'
get "/videos" => "doc#videos"
get "/video/:id" => "doc#watch"
get '/community' => 'community#index'
get "/community" => "community#index"
get '/search' => 'site#search'
get '/search/results' => 'site#search_results'
get "/search" => "site#search"
get "/search/results" => "site#search_results"
# historical synonyms
namespace :documentation do
get '/' => redirect('/doc')
get '/reference' => redirect('/docs')
get '/reference/:file.html' => redirect { |path_params, _req| "/docs/#{path_params[:file]}" }
get '/book' => redirect('/book')
get '/videos' => redirect('/videos')
get '/external-links' => redirect('doc/ext')
get "/" => redirect("/doc")
get "/reference" => redirect("/docs")
get "/reference/:file.html" => redirect { |path_params, _req| "/docs/#{path_params[:file]}" }
get "/book" => redirect("/book")
get "/videos" => redirect("/videos")
get "/external-links" => redirect("doc/ext")
end
get "/course/svn" => "site#svn"
@ -117,7 +117,7 @@ Rails.application.routes.draw do
get "/site" => "site#about"
get "/trademark" => redirect("/about/trademark")
get '/contributors' => redirect('https://github.com/git/git/graphs/contributors')
get "/contributors" => redirect("https://github.com/git/git/graphs/contributors")
root to: 'site#index'
root to: "site#index"
end

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
class CreateVersions < ActiveRecord::Migration
def change
create_table :versions do |t|

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
class CreateDocFiles < ActiveRecord::Migration
def change
create_table :doc_files do |t|

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
class CreateDocs < ActiveRecord::Migration
def change
create_table :docs do |t|

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
class CreateDocVersions < ActiveRecord::Migration
def change
create_table :doc_versions do |t|

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
class AddVersionOrder < ActiveRecord::Migration
def up
add_column :versions, :vorder, :float

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
class AddDownloads < ActiveRecord::Migration
def up
create_table :downloads do |t|

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
class ChangeDocShaToString < ActiveRecord::Migration
def up
change_column :docs, :blob_sha, :string

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
class AddBookStuff < ActiveRecord::Migration
def up
create_table :books do |t|

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
class AddBookUrl < ActiveRecord::Migration
def up
add_column :sections, :source_url, :string

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
class AddChapterTitleNumbers < ActiveRecord::Migration
def up
add_column :chapters, :number, :integer

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
class AddReleaseDateToDownloads < ActiveRecord::Migration
def change
add_column :downloads, :release_date, :timestamp
@ -5,7 +7,7 @@ class AddReleaseDateToDownloads < ActiveRecord::Migration
Download.all.each do |d|
time = d.version.committed # best guess
if d.platform == 'windows' # for Windows, take it from the filename
if d.platform == "windows" # for Windows, take it from the filename
d.filename =~ /Git-(.*?)-(.*?)(\d{4})(\d{2})(\d{2})\.exe/
time = Time.utc($3, $4, $5)
end

Просмотреть файл

@ -1,9 +1,11 @@
# frozen_string_literal: true
class AddChapterShas < ActiveRecord::Migration
def up
add_column :chapters, :sha, :string
end
def down
remove_column :chapters, :string
remove_column :chapters, :string
end
end
end

Просмотреть файл

@ -1,6 +1,8 @@
# frozen_string_literal: true
class AddEditionToBooks < ActiveRecord::Migration
def change
add_column :books, :edition, :integer, :default => 1
add_column :books, :edition, :integer, default: 1
add_column :books, :ebook_pdf, :string
add_column :books, :ebook_epub, :string
add_column :books, :ebook_mobi, :string

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
class AddProcessedFlag < ActiveRecord::Migration
def change
add_column :books, :processed, :boolean

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
class AddPercentComplete < ActiveRecord::Migration
def change
add_column :books, :percent_complete, :integer

Просмотреть файл

@ -1,6 +1,8 @@
# frozen_string_literal: true
class AddChapterType < ActiveRecord::Migration
def change
add_column :chapters, :chapter_type, :string, :default => 'chapter'
add_column :chapters, :chapter_type, :string, default: "chapter"
add_column :chapters, :chapter_number, :string
# fill with defaults

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
class AddXrefs < ActiveRecord::Migration
def change
create_table :xrefs do |t|

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
class AddLanguageName < ActiveRecord::Migration
def change
add_column :books, :language, :string

Просмотреть файл

@ -1,4 +1,5 @@
# encoding: UTF-8
# frozen_string_literal: true
#
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
# This file should contain all the record creation needed to seed the database with its default values.
# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
#

Просмотреть файл

@ -1,6 +1,8 @@
require 'faraday'
require 'yajl'
require 'time'
# frozen_string_literal: true
require "faraday"
require "yajl"
require "time"
module ElasticSearch
class JSONResponse < Faraday::Response::Middleware
@ -15,7 +17,7 @@ module ElasticSearch
def self.get_connection(server)
return unless server
Faraday.new(:url => server) do |builder|
Faraday.new(url: server) do |builder|
# TODO: add timeout middleware
builder.request :json
# builder.response :logger
@ -26,7 +28,7 @@ module ElasticSearch
def self.available?
conn = get_connection
resp = conn.get '/'
resp = conn.get "/"
resp.status == 200
end
@ -60,7 +62,7 @@ module ElasticSearch
#
# Returns true if the index exists, false otherwise.
def exists?
get("/#{@name}/_status")['error'].nil?
get("/#{@name}/_status")["error"].nil?
rescue ElasticSearch::Error
false
end
@ -85,7 +87,7 @@ module ElasticSearch
# create_options - a hash of index creation options
#
# Returns a hash, the parsed response body from elasticsearch.
def create(create_options={})
def create(create_options = {})
self.class.create @name, @server, create_options
end
@ -116,7 +118,7 @@ module ElasticSearch
def mget(type, ids)
get do |req|
req.url "#{@name}/#{type}/_mget"
req.body = {'ids' => ids}
req.body = {"ids" => ids}
end
end
@ -127,7 +129,7 @@ module ElasticSearch
# Returns a hash, the parsed response body from elasticsearch
def all(type)
get do |req|
req.url "#{@name}/#{type}/_search", 'q' => '*'
req.url "#{@name}/#{type}/_search", "q" => "*"
end
end
@ -151,8 +153,8 @@ module ElasticSearch
# options - options hash for this search request (optional)
#
# Returns a hash, the parsed response body from elasticsearch
def query(types, query, options={})
query = {'q' => query} if query.is_a?(String)
def query(types, query, options = {})
query = {"q" => query} if query.is_a?(String)
get do |req|
req.url "#{@name}/#{types}/_search", query.merge(options)
@ -167,8 +169,8 @@ module ElasticSearch
# options - options hash for this search request (optional)
#
# Returns a hash, the parsed response body from elasticsearch
def count(types, query={}, options=nil)
query = {'q' => query} if query.is_a?(String)
def count(types, query = {}, options = nil)
query = {"q" => query} if query.is_a?(String)
get do |req|
req.url "#{@name}/#{types}/_count", query
@ -183,7 +185,7 @@ module ElasticSearch
# doc - the document to be indexed
#
# Returns a hash, the parsed response body from elasticsearch
def add(type, id, doc, params={})
def add(type, id, doc, params = {})
doc.each do |key, val|
# make sure dates are in a consistent format for indexing
doc[key] = val.iso8601 if val.respond_to?(:iso8601)
@ -241,12 +243,12 @@ module ElasticSearch
properties_for_body = {}
properties.each do |property|
properties_for_body[property.name] = { 'type' => property.type }
properties_for_body[property.name] = { "type" => property.type }
end
put do |req|
req.url "#{@name}/#{type}/_mapping"
req.body = { type => { 'properties' => properties_for_body } }
req.body = { type => { "properties" => properties_for_body } }
end
end
@ -257,7 +259,7 @@ module ElasticSearch
# create_options - a hash of index creation options
#
# Returns a new ElasticSearch::Index instance
def self.create(name, server, create_options={})
def self.create(name, server, create_options = {})
ElasticSearch.get_connection(server).put do |req|
req.url "/#{name}"
req.body = create_options

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
module Searchable
extend ActiveSupport::Concern
@ -5,7 +7,7 @@ module Searchable
def self.search(keywords, options = {})
class_name = self.name.to_s.downcase
class_name = self.name.to_s.downcase
search_type = (class_name == "section" ? "book" : "doc")
type_name = (search_type == "book" ? "section" : "name")
category_name = (search_type == "book" ? "Book" : "Reference")
@ -28,33 +30,33 @@ module Searchable
query_options["query"]["bool"].merge!(lang_options) if options[:lang].present?
keywords.split(/\s|\-/).each do |keyword|
query_options['query']['bool']['should'] << { "prefix" => { type_name => { "value" => keyword, "boost" => 12.0 } } }
query_options['query']['bool']['should'] << { "term" => { format => keyword } }
query_options["query"]["bool"]["should"] << { "prefix" => { type_name => { "value" => keyword, "boost" => 12.0 } } }
query_options["query"]["bool"]["should"] << { "term" => { format => keyword } }
end
search = Tire::Search::Search.new(ELASTIC_SEARCH_INDEX, :type => search_type, :payload => query_options) rescue nil
search = Tire::Search::Search.new(ELASTIC_SEARCH_INDEX, type: search_type, payload: query_options) rescue nil
if search
ref_hits = []
results = search.results rescue []
results.each do |result|
name = result.section || result.chapter || result.name
slug = result.id.gsub('---','/')
highlight = if search_type == 'book'
slug = result.id.gsub("---", "/")
highlight = if search_type == "book"
result.highlight.html.first rescue nil
else
result.highlight.text.first rescue nil
end
hit = {
:name => name,
:score => result._score,
:highlight => highlight,
:url => (search_type == "book" ? "/book/#{slug}" : "/docs/#{name}")
name: name,
score: result._score,
highlight: highlight,
url: (search_type == "book" ? "/book/#{slug}" : "/docs/#{name}")
}
hit.merge!({:meta => result.meta}) if search_type == "book"
hit[:meta] = result.meta if search_type == "book"
ref_hits << hit
end
if ref_hits.size > 0
return {:category => category_name, :term => keywords, :matches => ref_hits}
return {category: category_name, term: keywords, matches: ref_hits}
end
end

Просмотреть файл

@ -1,16 +1,18 @@
require 'redcarpet'
require 'octokit'
require 'digest/sha1'
# frozen_string_literal: true
require "redcarpet"
require "octokit"
require "digest/sha1"
# export GITBOOK_DIR=../../writing/progit/
# bundle exec rake genbook GENLANG=en
SCRIPT_SHA = Digest::SHA1.hexdigest(File.open('lib/tasks/book.rake', 'r').read)
SCRIPT_SHA = Digest::SHA1.hexdigest(File.open("lib/tasks/book.rake", "r").read)
def generate_pages(lang, chapter, content, sha)
toc = {:title => '', :sections => []}
toc = {title: "", sections: []}
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, :tables => true)
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, tables: true)
content.gsub! /(\n(\n\t([^\t\n]+)\t([^\t\n]+))+\n\n)/ do
first_col=20
@ -46,7 +48,7 @@ def generate_pages(lang, chapter, content, sha)
if subsec = raw.scan(/<h3>(.*?)<\/h3>/)
subsec.each do |sub|
sub = sub.first
id = sub.gsub(' ', '-')
id = sub.gsub(" ", "-")
raw.gsub!(/<h3>#{sub}<\/h3>/, "<h3 id=\"#{id}\"><a href=\"##{id}\">#{sub}</a></h3>")
end
end
@ -54,14 +56,14 @@ def generate_pages(lang, chapter, content, sha)
# add a class to tables
raw.gsub! /<table>/, "<table class='ref'>"
sections = raw.split('<h2')
sections = raw.split("<h2")
section = 0
# create book (if needed)
book = Book.where(:edition => 1, :code => lang).first_or_create
book = Book.where(edition: 1, code: lang).first_or_create
# create chapter (if needed)
schapter = book.chapters.where(:number => chapter).first_or_create
schapter = book.chapters.where(number: chapter).first_or_create
schapter.title = chapter_title.to_s
schapter.sha = sha + SCRIPT_SHA
schapter.save
@ -70,7 +72,7 @@ def generate_pages(lang, chapter, content, sha)
sections.each do |sec|
section_title = ''
section_title = ""
if section_match = sec.match(/>(.*?)<\/h2>/)
section_title = section_match[1]
toc[:sections] << [section, section_title]
@ -80,9 +82,9 @@ def generate_pages(lang, chapter, content, sha)
full_title = section_match ? "#{chapter_title} #{section_title}" : chapter_title
html = ''
html = ""
if section_match
sec = '<h2' + sec
sec = "<h2" + sec
else
html += "<h1>Chapter #{chapter}</h1>"
end
@ -93,7 +95,7 @@ def generate_pages(lang, chapter, content, sha)
html += nav
# create/update section
csection = schapter.sections.where(:number => section).first_or_create
csection = schapter.sections.where(number: section).first_or_create
csection.title = section_title.to_s
csection.html = html.to_s
csection.save
@ -108,8 +110,8 @@ end
namespace :book do
desc "Update slug name"
task :update_slug => :environment do
Book.includes(:chapters => :sections).all.each do |book|
task update_slug: :environment do
Book.includes(chapters: :sections).all.each do |book|
book.sections.each do |section|
section.set_slug
section.save
@ -119,16 +121,16 @@ namespace :book do
end
desc "Generate the book html for the sites (Using Octokit gem)"
task :remote_genbook => :environment do
@octokit = Octokit::Client.new(:login => ENV['API_USER'], :password => ENV['API_PASS'])
repo = 'progit/progit'
task remote_genbook: :environment do
@octokit = Octokit::Client.new(login: ENV["API_USER"], password: ENV["API_PASS"])
repo = "progit/progit"
book = {}
blob_content = Hash.new do |blobs, sha|
content = Base64.decode64( @octokit.blob( repo, sha, :encoding => 'base64' ).content )
blobs[sha] = content.force_encoding('UTF-8')
content = Base64.decode64(@octokit.blob(repo, sha, encoding: "base64").content)
blobs[sha] = content.force_encoding("UTF-8")
end
repo_tree = @octokit.tree(repo, "HEAD", :recursive => true)
trees = repo_tree.tree.map {|tree| tree if tree.path =~ /\.markdown$/}.compact
repo_tree = @octokit.tree(repo, "HEAD", recursive: true)
trees = repo_tree.tree.map { |tree| tree if tree.path =~ /\.markdown$/ }.compact
trees.each do |tree|
#tree = trees.first
lang, section, chapter = tree.path.split("/")
@ -137,15 +139,15 @@ task :remote_genbook => :environment do
skip = false
if book = Book.where(:edition => 1, :code => lang).first
c = book.chapters.where(:number => chapter_number.to_i).first
if book = Book.where(edition: 1, code: lang).first
c = book.chapters.where(number: chapter_number.to_i).first
if c && (c.sha == (tree.sha + SCRIPT_SHA))
skip = true
end
end
skip = true if chapter_number.to_i == 0
skip = false if ENV['REGEN_ALL']
skip = false if ENV["REGEN_ALL"]
puts "*** #{skip} #{tree.sha}- #{lang} - #{section} - #{chapter} - #{section_number}:#{chapter_number}"

Просмотреть файл

@ -1,6 +1,8 @@
require 'nokogiri'
require 'octokit'
require 'pathname'
# frozen_string_literal: true
require "nokogiri"
require "octokit"
require "pathname"
def expand(content, path, &get_content)
content.gsub(/include::(\S+)\[\]/) do |line|
@ -11,7 +13,7 @@ def expand(content, path, &get_content)
end
new_content = get_content.call(new_fname)
if new_content
expand(new_content.gsub("\xEF\xBB\xBF".force_encoding("UTF-8"), ''), new_fname) {|c| get_content.call (c)}
expand(new_content.gsub("\xEF\xBB\xBF".force_encoding("UTF-8"), ""), new_fname) { |c| get_content.call (c) }
else
puts "#{new_fname} could not be resolved for expansion"
""
@ -20,15 +22,15 @@ def expand(content, path, &get_content)
end
desc "Reset book html to trigger re-build"
task :reset_book2 => :environment do
Book.where(:edition => 2).each do |book|
book.ebook_html = '0000000000000000000000000000000000000000'
task reset_book2: :environment do
Book.where(edition: 2).each do |book|
book.ebook_html = "0000000000000000000000000000000000000000"
book.save
end
end
def genbook (code, &get_content)
template_dir = File.join(Rails.root, 'templates')
def genbook(code, &get_content)
template_dir = File.join(Rails.root, "templates")
nav = '<div id="nav"><a href="[[nav-prev]]">prev</a> | <a href="[[nav-next]]">next</a></div>'
@ -45,17 +47,17 @@ def genbook (code, &get_content)
chapter_files = /(book\/[01A-C].*\/1-[^\/]*?\.asc|(?:ch[0-9]{2}|[ABC])-[^\/]*?\.asc)/
chaps = progit.scan(chapter_files).flatten
chaps.each_with_index do |filename, index |
chaps.each_with_index do |filename, index|
# select the chapter files
if filename =~ /(book\/[01].*\/1-[^\/]*\.asc|ch[0-9]{2}-.*\.asc)/
chnumber += 1
chapters ["ch#{secnumber}"] = ['chapter', chnumber, filename]
chapters ["ch#{secnumber}"] = ["chapter", chnumber, filename]
secnumber += 1
end
# detect the appendices
if filename =~ /(book\/[ABC].*\.asc|[ABC].*\.asc)/
appnumber += 1
chapters ["ch#{secnumber}"] = ['appendix', appnumber, filename]
chapters ["ch#{secnumber}"] = ["appendix", appnumber, filename]
secnumber += 1
end
end
@ -73,15 +75,15 @@ def genbook (code, &get_content)
# revert internal links decorations for ebooks
content.gsub!(/<<.*?\#(.*?)>>/, "<<\\1>>")
asciidoc = Asciidoctor::Document.new(content,template_dir: template_dir, attributes: { 'compat-mode' => true})
asciidoc = Asciidoctor::Document.new(content, template_dir: template_dir, attributes: { "compat-mode" => true})
html = asciidoc.render
alldoc = Nokogiri::HTML(html)
number = 1
Book.destroy_all(:edition => 2, :code => code)
book = Book.create(:edition => 2, :code => code)
Book.destroy_all(edition: 2, code: code)
book = Book.create(edition: 2, code: code)
alldoc.xpath("//div[@class='sect1']").each_with_index do |entry, index |
alldoc.xpath("//div[@class='sect1']").each_with_index do |entry, index|
chapter_title = entry.at("h2").content
if !chapters["ch#{index}"]
puts "not including #{chapter_title}\n"
@ -94,14 +96,14 @@ def genbook (code, &get_content)
next if !chapter_number
number = chapter_number
if chapter_type == 'appendix'
if chapter_type == "appendix"
number = 100 + chapter_number
end
pretext = entry.search("div[@class=sectionbody]/div/p").to_html
id_xref = chapter.at("h2").attribute('id').to_s
id_xref = chapter.at("h2").attribute("id").to_s
schapter = book.chapters.where(:number => number).first_or_create
schapter = book.chapters.where(number: number).first_or_create
schapter.title = chapter_title.to_s
schapter.chapter_type = chapter_type
schapter.chapter_number = chapter_number
@ -109,26 +111,26 @@ def genbook (code, &get_content)
schapter.save
# create xref
csection = schapter.sections.where(:number => 1).first_or_create
xref = Xref.where(:book_id => book.id, :name => id_xref).first_or_create
csection = schapter.sections.where(number: 1).first_or_create
xref = Xref.where(book_id: book.id, name: id_xref).first_or_create
xref.section = csection
xref.save
section = 1
chapter.search("div[@class=sect2]").each do |sec|
id_xref = sec.at("h3").attribute('id').to_s
id_xref = sec.at("h3").attribute("id").to_s
section_title = sec.at("h3").content
html = sec.inner_html.to_s + nav
html.gsub!('<h3', '<h2')
html.gsub!(/\/h3>/, '/h2>')
html.gsub!('<h4', '<h3')
html.gsub!(/\/h4>/, '/h3>')
html.gsub!('<h5', '<h4')
html.gsub!(/\/h5>/, '/h4>')
html.gsub!("<h3", "<h2")
html.gsub!(/\/h3>/, "/h2>")
html.gsub!("<h4", "<h3")
html.gsub!(/\/h4>/, "/h3>")
html.gsub!("<h5", "<h4")
html.gsub!(/\/h5>/, "/h4>")
if xlink = html.scan(/href=\"1-.*?\.html\#(.*?)\"/)
xlink.each do |link|
@ -153,19 +155,19 @@ def genbook (code, &get_content)
puts "\t\t#{chapter_type} #{chapter_number}.#{section} : #{chapter_title} . #{section_title} - #{html.size}"
csection = schapter.sections.where(:number => section).first_or_create
csection = schapter.sections.where(number: section).first_or_create
csection.title = section_title.to_s
csection.html = pretext + html
csection.save
xref = Xref.where(:book_id => book.id, :name => id_xref).first_or_create
xref = Xref.where(book_id: book.id, name: id_xref).first_or_create
xref.section = csection
xref.save
# record all the xrefs
(sec.search(".//*[@id]")).each do |id|
id_xref = id.attribute('id').to_s
xref = Xref.where(:book_id => book.id, :name => id_xref).first_or_create
id_xref = id.attribute("id").to_s
xref = Xref.where(book_id: book.id, name: id_xref).first_or_create
xref.section = csection
xref.save
end
@ -181,8 +183,8 @@ def genbook (code, &get_content)
end
desc "Generate book html directly from git repo"
task :remote_genbook2 => :environment do
@octokit = Octokit::Client.new(:login => ENV['API_USER'], :password => ENV['API_PASS'])
task remote_genbook2: :environment do
@octokit = Octokit::Client.new(login: ENV["API_USER"], password: ENV["API_PASS"])
all_books = {
"be" => "progit/progit2-be",
"bg" => "progit/progit2-bg",
@ -212,12 +214,12 @@ task :remote_genbook2 => :environment do
"fa" => "progit2-fa/progit2"
}
if ENV['GENLANG']
books = all_books.select { |code, repo| code == ENV['GENLANG']}
if ENV["GENLANG"]
books = all_books.select { |code, repo| code == ENV["GENLANG"] }
else
books = all_books.select do |code, repo|
repo_head = @octokit.ref(repo, "heads/master").object[:sha]
book = Book.where(:edition => 2, :code => code).first_or_create
book = Book.where(edition: 2, code: code).first_or_create
repo_head != book.ebook_html
end
end
@ -225,10 +227,10 @@ task :remote_genbook2 => :environment do
books.each do |code, repo|
begin
blob_content = Hash.new do |blobs, sha|
content = Base64.decode64( @octokit.blob(repo, sha, :encoding => 'base64' ).content )
blobs[sha] = content.force_encoding('UTF-8')
content = Base64.decode64(@octokit.blob(repo, sha, encoding: "base64").content)
blobs[sha] = content.force_encoding("UTF-8")
end
repo_tree = @octokit.tree(repo, "HEAD", :recursive => true)
repo_tree = @octokit.tree(repo, "HEAD", recursive: true)
Book.transaction do
genbook(code) do |filename|
file_handle = repo_tree.tree.detect { |tree| tree[:path] == filename }
@ -238,13 +240,13 @@ task :remote_genbook2 => :environment do
end
repo_head = @octokit.ref(repo, "heads/master").object[:sha]
book = Book.where(:edition => 2, :code => code).first_or_create
book = Book.where(edition: 2, code: code).first_or_create
book.ebook_html = repo_head
begin
rel = @octokit.latest_release(repo)
get_url = -> content_type do
asset = rel.assets.select { |asset| asset.content_type==content_type}.first
get_url = -> (content_type) do
asset = rel.assets.select { |asset| asset.content_type==content_type }.first
if asset
asset.browser_download_url
else
@ -262,17 +264,17 @@ task :remote_genbook2 => :environment do
book.save
end
rescue Exception => msg
puts msg
rescue StandardError => err
puts err.message
end
end
end
desc "Generate book html directly from git repo"
task :local_genbook2 => :environment do
if (ENV['GENLANG'] && ENV['GENPATH'])
genbook(ENV['GENLANG']) do |filename|
File.open(File.join(ENV['GENPATH'], filename), "r") {|infile| File.read(infile)}
task local_genbook2: :environment do
if (ENV["GENLANG"] && ENV["GENPATH"])
genbook(ENV["GENLANG"]) do |filename|
File.open(File.join(ENV["GENPATH"], filename), "r") { |infile| File.read(infile) }
end
end
end

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
task :copy do
puts "copying images"
`cp -Rf ../scm-mock/source/images/* public/images/`
@ -5,7 +7,7 @@ task :copy do
`cp -Rf ../scm-mock/source/stylesheets/* app/assets/stylesheets/`
puts "copying js"
`cp -Rf ../scm-mock/source/javascripts/* app/assets/javascripts/`
puts 'copying layouts'
puts "copying layouts"
`cp ../scm-mock/source/layout.haml app/views/layouts/layout.html.haml`
`cp ../scm-mock/source/index.html.haml app/views/site/`
`cp ../scm-mock/source/about/index.html.haml app/views/about/`

Просмотреть файл

@ -1,13 +1,15 @@
desc 'find newest mac and windows binary downloads'
# frozen_string_literal: true
desc "find newest mac and windows binary downloads"
task downloads: %i[windows_downloads mac_downloads]
desc 'find latest windows version'
desc "find latest windows version"
task windows_downloads: :environment do
Rails.logger = Logger.new(STDOUT)
DownloadService.download_windows_versions
end
desc 'find latest mac version'
desc "find latest mac version"
task mac_downloads: :environment do
Rails.logger = Logger.new(STDOUT)
DownloadService.download_mac_versions

Просмотреть файл

@ -1,22 +1,24 @@
require 'asciidoctor'
require 'octokit'
require 'time'
require 'digest/sha1'
# frozen_string_literal: true
require "asciidoctor"
require "octokit"
require "time"
require "digest/sha1"
def index_doc(filter_tags, doc_list, get_content)
ActiveRecord::Base.logger.level = Logger::WARN
rebuild = ENV['REBUILD_DOC']
rerun = ENV['RERUN'] || rebuild || false
filter_tags.call(rebuild).sort_by { |tag| Version.version_to_num(tag.first[1..-1])}.each do |tag|
rebuild = ENV["REBUILD_DOC"]
rerun = ENV["RERUN"] || rebuild || false
filter_tags.call(rebuild).sort_by { |tag| Version.version_to_num(tag.first[1..-1]) }.each do |tag|
name, commit_sha, tree_sha, ts = tag
puts "#{name}: #{ts}, #{commit_sha[0, 8]}, #{tree_sha[0, 8]}"
stag = Version.where(:name => name.gsub('v','')).first
stag = Version.where(name: name.gsub("v", "")).first
next if stag && !rerun
stag = Version.where(:name => name.gsub('v','')).first_or_create
stag = Version.where(name: name.gsub("v", "")).first_or_create
stag.commit_sha = commit_sha
stag.tree_sha = tree_sha
stag.committed = ts
@ -39,16 +41,17 @@ def index_doc(filter_tags, doc_list, get_content)
pretty.* |
pull.* |
technical\/.*
)\.txt)/x }
)\.txt)/x
}
puts "Found #{doc_files.size} entries"
doc_limit = ENV['ONLY_BUILD_DOC']
doc_limit = ENV["ONLY_BUILD_DOC"]
# generate command-list content
categories = {}
cmd = tag_files.detect {|f| f.first =~ /command-list\.txt/}
cmd = tag_files.detect { |f| f.first =~ /command-list\.txt/ }
if cmd
cmd_list = get_content.call(cmd.second).match(/(### command list.*|# command name.*)/m)[0].split("\n").reject{|l| l =~ /^#/}.inject({}) do |list, cmd|
cmd_list = get_content.call(cmd.second).match(/(### command list.*|# command name.*)/m)[0].split("\n").reject { |l| l =~ /^#/ }.inject({}) do |list, cmd|
name, kind, attr = cmd.split(/\s+/)
list[kind] ||= []
list[kind] << [name, attr]
@ -65,7 +68,7 @@ def index_doc(filter_tags, doc_list, get_content)
list.merge!("cmds-#{category}.txt" => links.compact.join("\n"))
end
tools = tag_files.select { |ent| ent.first =~/^mergetools\//}.map do |entry|
tools = tag_files.select { |ent| ent.first =~/^mergetools\// }.map do |entry|
path, sha = entry
tool = File.basename path
content = get_content.call sha
@ -74,7 +77,7 @@ def index_doc(filter_tags, doc_list, get_content)
[merge, diff]
end
can_merge, can_diff = tools.transpose.map {|strs| strs.join ""}
can_merge, can_diff = tools.transpose.map { |strs| strs.join "" }
get_content_f = Proc.new do |name|
content_file = tag_files.detect { |ent| ent.first == "Documentation/#{name}" }
@ -92,7 +95,7 @@ def index_doc(filter_tags, doc_list, get_content)
def expand!(content, get_f_content , categories)
content.gsub!(/include::(\S+)\.txt/) do |line|
line.gsub!("include::","")
line.gsub!("include::", "")
if categories[line]
new_content = categories[line]
else
@ -107,19 +110,19 @@ def index_doc(filter_tags, doc_list, get_content)
doc_files.each do |entry|
path, sha = entry
path = File.basename( path, '.txt' )
path = File.basename(path, ".txt")
next if doc_limit && path !~ /#{doc_limit}/
file = DocFile.where(:name => path).first_or_create
file = DocFile.where(name: path).first_or_create
puts " build: #{path}"
content = get_content.call sha
expand!(content, get_content_f, categories)
content.gsub!(/link:technical\/(.*?)\.html\[(.*?)\]/, 'link:\1[\2]')
asciidoc = Asciidoctor::Document.new(content, attributes: {'sectanchors' => ''}, doctype: 'book')
asciidoc_sha = Digest::SHA1.hexdigest( asciidoc.source )
doc = Doc.where( :blob_sha => asciidoc_sha ).first_or_create
asciidoc = Asciidoctor::Document.new(content, attributes: {"sectanchors" => ""}, doctype: "book")
asciidoc_sha = Digest::SHA1.hexdigest(asciidoc.source)
doc = Doc.where(blob_sha: asciidoc_sha).first_or_create
if rerun || !doc.plain || !doc.html
html = asciidoc.render
html.gsub!(/linkgit:(\S+)\[(\d+)\]/) do |line|
@ -128,7 +131,7 @@ def index_doc(filter_tags, doc_list, get_content)
end
#HTML anchor on hdlist1 (i.e. command options)
html.gsub!(/<dt class="hdlist1">(.*?)<\/dt>/) do |m|
text = $1.tr('^A-Za-z0-9-', '')
text = $1.tr("^A-Za-z0-9-", "")
anchor = "#{path}-#{text}"
"<dt class=\"hdlist1\" id=\"#{anchor}\"> <a class=\"anchor\" href=\"##{anchor}\"></a>#{$1} </dt>"
end
@ -136,37 +139,37 @@ def index_doc(filter_tags, doc_list, get_content)
doc.html = html
doc.save
end
dv = DocVersion.where(:version_id => stag.id, :doc_file_id => file.id).first_or_create
dv = DocVersion.where(version_id: stag.id, doc_file_id: file.id).first_or_create
dv.doc_id = doc.id
dv.save
end
end
Rails.cache.write("latest-version", Version.latest_version.name)
end
end
task :preindex => :environment do
task preindex: :environment do
Octokit.auto_paginate = true
@octokit = Octokit::Client.new(:login => ENV['API_USER'], :password => ENV['API_PASS'])
repo = ENV['GIT_REPO'] || 'gitster/git'
@octokit = Octokit::Client.new(login: ENV["API_USER"], password: ENV["API_PASS"])
repo = ENV["GIT_REPO"] || "gitster/git"
blob_content = Hash.new do |blobs, sha|
content = Base64.decode64( @octokit.blob( repo, sha, :encoding => 'base64' ).content )
blobs[sha] = content.encode( 'utf-8', :undef => :replace )
content = Base64.decode64(@octokit.blob(repo, sha, encoding: "base64").content)
blobs[sha] = content.encode("utf-8", undef: :replace)
end
tag_filter = -> (tagname) do
# find all tags
tags = @octokit.tags( repo ).select { |tag| !tag.nil? && tag.name =~ /v\d([\.\d])+$/ } # just get release tags
tags = @octokit.tags(repo).select { |tag| !tag.nil? && tag.name =~ /v\d([\.\d])+$/ } # just get release tags
if tagname
tags = tags.select { |t| t.name == tagname }
end
tags.collect do |tag|
tags.collect do |tag|
# extract metadata
commit_info = @octokit.commit( repo, tag.name )
commit_info = @octokit.commit(repo, tag.name)
commit_sha = commit_info.sha
tree_sha = commit_info.commit.tree.sha
# ts = Time.parse( commit_info.commit.committer.date )
@ -174,21 +177,21 @@ task :preindex => :environment do
[tag.name, commit_sha, tree_sha, ts]
end
end
get_content = -> sha do blob_content[sha] end
get_content = -> (sha) do blob_content[sha] end
get_file_list = -> (tree_sha) do
tree_info = @octokit.tree( repo, tree_sha, :recursive => true )
tree_info = @octokit.tree(repo, tree_sha, recursive: true)
tree_info.tree.collect { |ent| [ent.path, ent.sha] }
end
index_doc(tag_filter, get_file_list, get_content)
end
task :local_index => :environment do
task local_index: :environment do
dir = ENV["GIT_REPO"]
Dir.chdir(dir) do
tag_filter = -> (tagname) do
# find all tags
@ -201,7 +204,7 @@ task :local_index => :environment do
# extract metadata
commit_sha = `git rev-parse #{tag}`.chomp
tree_sha = `git rev-parse #{tag}^{tree}`.chomp
tagger = `git cat-file commit #{tag} | grep committer`.chomp.split(' ')
tagger = `git cat-file commit #{tag} | grep committer`.chomp.split(" ")
tz = tagger.pop
ts = tagger.pop
ts = Time.at(ts.to_i)
@ -209,12 +212,12 @@ task :local_index => :environment do
end
end
get_content = -> sha do `git cat-file blob #{sha}` end
get_content = -> (sha) do `git cat-file blob #{sha}` end
get_file_list = -> (tree_sha) do
entries = `git ls-tree -r #{tree_sha}`.strip.split("\n")
tree = entries. map do |e|
mode, type, sha, path = e.split(' ')
mode, type, sha, path = e.split(" ")
[path, sha]
end
end

Просмотреть файл

@ -1,4 +1,6 @@
task :search_clear => :environment do
# frozen_string_literal: true
task search_clear: :environment do
# BONSAI.clear
Tire.index ELASTIC_SEARCH_INDEX do
delete
@ -6,7 +8,7 @@ task :search_clear => :environment do
end
end
task :search_index => :environment do
task search_index: :environment do
version = Version.latest_version
puts version.name
version.doc_versions.each do |docv|
@ -14,8 +16,8 @@ task :search_index => :environment do
end
end
task :search_index_book => :environment do
book = Book.where(:code => 'en', :edition => 2).first
task search_index_book: :environment do
book = Book.where(code: "en", edition: 2).first
book.sections.each do |sec|
sec.index
end

Просмотреть файл

@ -1,28 +1,29 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'optparse'
require "optparse"
path = File.expand_path '~/.git-credentials' # <1>
path = File.expand_path "~/.git-credentials" # <1>
OptionParser.new do |opts|
opts.banner = 'USAGE: git-credential-read-only [options] <action>'
opts.on('-f', '--file PATH', 'Specify path for backing store') do |argpath|
opts.banner = "USAGE: git-credential-read-only [options] <action>"
opts.on("-f", "--file PATH", "Specify path for backing store") do |argpath|
path = File.expand_path argpath
end
end.parse!
exit(0) unless ARGV[0].downcase == 'get' # <2>
exit(0) unless File.exists? path
exit(0) unless ARGV[0].downcase == "get" # <2>
exit(0) unless File.exist? path
known = {} # <3>
while line = STDIN.gets
break if line.strip == ''
k,v = line.strip.split '=', 2
break if line.strip == ""
k, v = line.strip.split "=", 2
known[k] = v
end
File.readlines(path).each do |fileline| # <4>
prot,user,pass,host = fileline.scan(/^(.*?):\/\/(.*?):(.*?)@(.*)$/).first
if prot == known['protocol'] and host == known['host'] then
prot, user, pass, host = fileline.scan(/^(.*?):\/\/(.*?):(.*?)@(.*)$/).first
if prot == known["protocol"] and host == known["host"]
puts "protocol=#{prot}"
puts "host=#{host}"
puts "username=#{user}"

Просмотреть файл

@ -1,11 +1,13 @@
#!/usr/bin/env ruby
require 'asciidoctor'
require 'pp'
# frozen_string_literal: true
require "asciidoctor"
require "pp"
file_path = File.expand_path("./spec/data/git-diff.txt")
content = File.read(file_path)
content.gsub!(/::(.*)\.txt/,"::\\1")
content.gsub!(/::(.*)\.txt/, "::\\1")
doc = Asciidoctor::Document.new(content)
html = doc.render
html.gsub!(/linkgit:(.*)\[(\d+)\]/) do |line|
@ -16,4 +18,3 @@ end
File.open("./git-diff.html", "w+") do |f|
f.write html
end

Просмотреть файл

@ -1,6 +1,8 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
APP_PATH = File.expand_path('../../config/application', __FILE__)
require File.expand_path('../../config/boot', __FILE__)
require 'rails/commands'
APP_PATH = File.expand_path("../../config/application", __FILE__)
require File.expand_path("../../config/boot", __FILE__)
require "rails/commands"

Просмотреть файл

@ -1,4 +1,5 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
# This script helps to sort the git GUI clients listed on the website.
# We have been using Google Trends to help sorting the clients by popularity,
@ -9,21 +10,21 @@
# on this process until the order is fixed.
# The script also validates no duplicated clients exist in the listing.
require 'yaml'
require 'open-uri'
require "yaml"
require "open-uri"
yaml = YAML.load_file('resources/guis.yml')
yaml = YAML.load_file("resources/guis.yml")
guis_info = yaml["guis"]
# Just checking duplicates because during manual sorting one may commit mistakes
if guis_info.map { |e| e["name"] }.uniq.length != guis_info.length then
if guis_info.map { |e| e["name"] }.uniq.length != guis_info.length
puts "\n======= WARNING: THERE ARE DUPLICATED GUIS ======="
end
# Just checking if there are repeated 'order' values
orders = guis_info.map { |e| e["order"] }
duplicated_order = orders.detect{ |e| orders.count(e) > 1 }
if duplicated_order then
duplicated_order = orders.detect { |e| orders.count(e) > 1 }
if duplicated_order
puts "\n======= WARNING: THERE ARE DUPLICATED ORDERS (value: #{duplicated_order}) ======="
end

Просмотреть файл

@ -1,4 +1,6 @@
require 'rails_helper'
# frozen_string_literal: true
require "rails_helper"
RSpec.describe AboutController, type: :controller do

Просмотреть файл

@ -1,4 +1,6 @@
require 'rails_helper'
# frozen_string_literal: true
require "rails_helper"
RSpec.describe CommunityController, type: :controller do

Просмотреть файл

@ -1,4 +1,6 @@
require 'rails_helper'
# frozen_string_literal: true
require "rails_helper"
RSpec.describe SiteController, type: :controller do

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
Fabricator(:book) do
code "en"
chapters(count: 3)

Просмотреть файл

@ -1,6 +1,8 @@
# frozen_string_literal: true
Fabricator(:chapter) do
title "Git"
number { sequence(:number) {|i| i } }
number { sequence(:number) { |i| i } }
sha { SecureRandom.hex }
sections(count: 3)
end

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
Fabricator(:doc) do
blob_sha { SecureRandom.hex }
plain "git-file"

Просмотреть файл

@ -1,3 +1,5 @@
# frozen_string_literal: true
Fabricator(:doc_file) do
name "git-file"
end

Просмотреть файл

@ -1,2 +1,4 @@
# frozen_string_literal: true
Fabricator(:doc_version) do
end

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше