Patch #234 » git_edge_latest_patch.diff
| app/helpers/repositories_helper.rb (working copy) | ||
|---|---|---|
| 73 | 73 |
content_tag('p', form.text_field(:url, :label => 'Root directory', :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?)))
|
| 74 | 74 |
end |
| 75 | 75 | |
| 76 |
def git_field_tags(form, repository) |
|
| 77 |
content_tag('p', form.text_field(:url, :label => 'Root directory', :size => 60, :required => true, :disabled => (repository && !repository.root_url.blank?)))
|
|
| 78 |
end |
|
| 79 | ||
| 76 | 80 |
def cvs_field_tags(form, repository) |
| 77 | 81 |
content_tag('p', form.text_field(:root_url, :label => 'CVSROOT', :size => 60, :required => true, :disabled => !repository.new_record?)) +
|
| 78 | 82 |
content_tag('p', form.text_field(:url, :label => 'Module', :size => 30, :required => true, :disabled => !repository.new_record?))
|
| app/models/repository/subversion.rb (working copy) | ||
|---|---|---|
| 42 | 42 |
db_revision = latest_changeset ? latest_changeset.revision : 0 |
| 43 | 43 |
# latest revision in the repository |
| 44 | 44 |
scm_revision = scm_info.lastrev.identifier.to_i |
| 45 |
if db_revision < scm_revision |
|
| 45 |
if db_revision.to_i < scm_revision
|
|
| 46 | 46 |
logger.debug "Fetching changesets for repository #{url}" if logger && logger.debug?
|
| 47 | 47 |
identifier_from = db_revision + 1 |
| 48 | 48 |
while (identifier_from <= scm_revision) |
| app/models/repository/git.rb (revision 0) | ||
|---|---|---|
| 1 |
# redMine - project management software |
|
| 2 |
# Copyright (C) 2006-2007 Jean-Philippe Lang |
|
| 3 |
# Copyright (C) 2007 Patrick Aljord patcito@ŋmail.com |
|
| 4 |
# This program is free software; you can redistribute it and/or |
|
| 5 |
# modify it under the terms of the GNU General Public License |
|
| 6 |
# as published by the Free Software Foundation; either version 2 |
|
| 7 |
# of the License, or (at your option) any later version. |
|
| 8 |
# |
|
| 9 |
# This program is distributed in the hope that it will be useful, |
|
| 10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 12 |
# GNU General Public License for more details. |
|
| 13 |
# |
|
| 14 |
# You should have received a copy of the GNU General Public License |
|
| 15 |
# along with this program; if not, write to the Free Software |
|
| 16 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
| 17 | ||
| 18 |
require 'redmine/scm/adapters/git_adapter' |
|
| 19 | ||
| 20 |
class Repository::Git < Repository |
|
| 21 |
attr_protected :root_url |
|
| 22 |
validates_presence_of :url |
|
| 23 | ||
| 24 |
def scm_adapter |
|
| 25 |
Redmine::Scm::Adapters::GitAdapter |
|
| 26 |
end |
|
| 27 |
|
|
| 28 |
def self.scm_name |
|
| 29 |
'Git' |
|
| 30 |
end |
|
| 31 |
|
|
| 32 |
def entries(path=nil, identifier=nil) |
|
| 33 |
entries=scm.entries(path, identifier) |
|
| 34 |
if entries |
|
| 35 |
entries.each do |entry| |
|
| 36 |
next unless entry.is_file? |
|
| 37 |
# Search the DB for the entry's last change |
|
| 38 |
change = changes.find(:first, :conditions => ["path = ?", scm.with_leading_slash(entry.path)], :order => "#{Changeset.table_name}.committed_on DESC")
|
|
| 39 |
if change |
|
| 40 |
entry.lastrev.identifier = change.changeset.revision |
|
| 41 |
entry.lastrev.name = change.changeset.revision |
|
| 42 |
entry.lastrev.author = change.changeset.committer |
|
| 43 |
entry.lastrev.revision = change.revision |
|
| 44 |
end |
|
| 45 |
end |
|
| 46 |
end |
|
| 47 |
entries |
|
| 48 |
end |
|
| 49 | ||
| 50 |
def fetch_changesets |
|
| 51 |
scm_info = scm.info |
|
| 52 |
|
|
| 53 |
if scm_info |
|
| 54 |
# latest revision found in database |
|
| 55 |
db_revision = latest_changeset ? latest_changeset.revision : nil |
|
| 56 |
# latest revision in the repository |
|
| 57 |
scm_revision = scm_info.lastrev.identifier |
|
| 58 | ||
| 59 |
unless changesets.find_by_revision(scm_revision) |
|
| 60 | ||
| 61 |
revisions = scm.revisions('', db_revision, nil)
|
|
| 62 |
transaction do |
|
| 63 |
revisions.reverse_each do |revision| |
|
| 64 |
changeset = Changeset.create(:repository => self, |
|
| 65 |
:revision => revision.identifier, |
|
| 66 |
:scmid => revision.scmid, |
|
| 67 |
:committer => revision.author, |
|
| 68 |
:committed_on => revision.time, |
|
| 69 |
:comments => revision.message) |
|
| 70 |
|
|
| 71 |
revision.paths.each do |change| |
|
| 72 |
Change.create(:changeset => changeset, |
|
| 73 |
:action => change[:action], |
|
| 74 |
:path => change[:path], |
|
| 75 |
:from_path => change[:from_path], |
|
| 76 |
:from_revision => change[:from_revision]) |
|
| 77 |
end |
|
| 78 |
end |
|
| 79 |
end |
|
| 80 |
end |
|
| 81 |
end |
|
| 82 |
end |
|
| 83 |
end |
|
| app/models/changeset.rb (working copy) | ||
|---|---|---|
| 32 | 32 |
:date_column => 'committed_on' |
| 33 | 33 |
|
| 34 | 34 |
validates_presence_of :repository_id, :revision, :committed_on, :commit_date |
| 35 |
validates_numericality_of :revision, :only_integer => true |
|
| 35 |
# validates_numericality_of :revision, :only_integer => true
|
|
| 36 | 36 |
validates_uniqueness_of :revision, :scope => :repository_id |
| 37 | 37 |
validates_uniqueness_of :scmid, :scope => :repository_id, :allow_nil => true |
| 38 | 38 |
|
| app/controllers/repositories_controller.rb (working copy) | ||
|---|---|---|
| 46 | 46 |
|
| 47 | 47 |
def show |
| 48 | 48 |
# check if new revisions have been committed in the repository |
| 49 |
@repository.fetch_changesets if Setting.autofetch_changesets? |
|
| 49 |
@repository.fetch_changesets #if Setting.autofetch_changesets?
|
|
| 50 | 50 |
# get entries for the browse frame |
| 51 | 51 |
@entries = @repository.entries('')
|
| 52 | 52 |
# latest changesets |
| ... | ... | |
| 105 | 105 |
end |
| 106 | 106 |
|
| 107 | 107 |
def diff |
| 108 |
@rev_to = params[:rev_to] ? params[:rev_to].to_i : (@rev - 1)
|
|
| 108 |
get_rev_to
|
|
| 109 | 109 |
@diff_type = ('sbs' == params[:type]) ? 'sbs' : 'inline'
|
| 110 | 110 |
|
| 111 | 111 |
@cache_key = "repositories/diff/#{@repository.id}/" + Digest::MD5.hexdigest("#{@path}-#{@rev}-#{@rev_to}-#{@diff_type}")
|
| ... | ... | |
| 147 | 147 |
render_404 and return false unless @repository |
| 148 | 148 |
@path = params[:path].join('/') unless params[:path].nil?
|
| 149 | 149 |
@path ||= '' |
| 150 |
@rev = params[:rev].to_i if params[:rev]
|
|
| 150 |
@rev = params[:rev] if params[:rev] |
|
| 151 | 151 |
rescue ActiveRecord::RecordNotFound |
| 152 | 152 |
render_404 |
| 153 | 153 |
end |
| 154 | 154 | |
| 155 |
def get_rev_to |
|
| 156 |
@rev_to = params[:rev_to].to_i ? params[:rev_to].to_i : (@rev.to_i - 1) if @rev !~ /\D/ |
|
| 157 |
@rev_to = params[:rev_to] ? params[:rev_to] : (nil) if !(@rev !~ /\D/) |
|
| 158 |
end |
|
| 159 | ||
| 155 | 160 |
def show_error |
| 156 | 161 |
flash.now[:error] = l(:notice_scm_error) |
| 157 | 162 |
render :nothing => true, :layout => true |
| db/migrate/078_make_revisions_string.rb (revision 0) | ||
|---|---|---|
| 1 |
class MakeRevisionsString < ActiveRecord::Migration |
|
| 2 |
def self.up |
|
| 3 |
change_column :changes, :from_revision, :string |
|
| 4 |
change_column :changesets, :revision, :string |
|
| 5 |
end |
|
| 6 | ||
| 7 |
def self.down |
|
| 8 |
change_column :changes, :from_revision, :integer |
|
| 9 |
change_column :changesets, :revision, :integer |
|
| 10 |
end |
|
| 11 |
end |
|
| lib/redmine/scm/adapters/abstract_adapter.rb (working copy) | ||
|---|---|---|
| 172 | 172 |
end |
| 173 | 173 |
}.last |
| 174 | 174 |
end |
| 175 |
end |
|
| 175 |
end |
|
| 176 |
|
|
| 177 | ||
| 178 |
def get_rev(rev,path) |
|
| 179 |
Revision.new |
|
| 180 |
end |
|
| 176 | 181 |
|
| 177 | 182 |
class Revision |
| 178 | 183 |
attr_accessor :identifier, :scmid, :name, :author, :time, :message, :paths, :revision, :branch |
| lib/redmine/scm/adapters/git_adapter.rb (revision 0) | ||
|---|---|---|
| 1 |
# redMine - project management software |
|
| 2 |
# Copyright (C) 2006-2007 Jean-Philippe Lang |
|
| 3 |
# Copyright (C) 2007 Patrick Aljord patcito@ŋmail.com |
|
| 4 |
# This program is free software; you can redistribute it and/or |
|
| 5 |
# modify it under the terms of the GNU General Public License |
|
| 6 |
# as published by the Free Software Foundation; either version 2 |
|
| 7 |
# of the License, or (at your option) any later version. |
|
| 8 |
# |
|
| 9 |
# This program is distributed in the hope that it will be useful, |
|
| 10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 12 |
# GNU General Public License for more details. |
|
| 13 |
# |
|
| 14 |
# You should have received a copy of the GNU General Public License |
|
| 15 |
# along with this program; if not, write to the Free Software |
|
| 16 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
| 17 | ||
| 18 |
require 'redmine/scm/adapters/abstract_adapter' |
|
| 19 | ||
| 20 |
module Redmine |
|
| 21 |
module Scm |
|
| 22 |
module Adapters |
|
| 23 |
class GitAdapter < AbstractAdapter |
|
| 24 |
|
|
| 25 |
# Git executable name |
|
| 26 |
GIT_BIN = "git" |
|
| 27 |
|
|
| 28 | ||
| 29 |
#get the revision of a particuliar file |
|
| 30 |
def get_rev (rev,path) |
|
| 31 |
cmd="cd #{target('')} && git show #{rev} #{path}" if rev!='latest'
|
|
| 32 |
cmd="cd #{target('')} && git log -1 master -- #{path}" if
|
|
| 33 |
rev=='latest' or rev.nil? |
|
| 34 |
puts cmd |
|
| 35 |
rev=[] |
|
| 36 |
i=0 |
|
| 37 |
shellout(cmd) do |io| |
|
| 38 |
commit_files=[] |
|
| 39 |
params={:commit=>'',:author=>'',:date=>'',:message=>'',:file=>{:path=>'',:action=>''}}
|
|
| 40 |
|
|
| 41 |
message='' |
|
| 42 |
io.each_line do |line| |
|
| 43 | ||
| 44 |
i=0 if line=~/^commit/ |
|
| 45 |
params[:commit]=line.chomp.gsub("commit ",'') if i==0
|
|
| 46 |
|
|
| 47 |
params[:author]=line.chomp.gsub("Author: ",'') if i==1
|
|
| 48 |
params[:date]=line.chomp.gsub("Date: ",'') if i==2
|
|
| 49 |
params[:message]+= line.chomp.to_s if i==4 and line[0..0]!=':' |
|
| 50 |
params[:file][:action], params[:file][:path]= line.chomp.slice(/[ACDMRTUXB].*/).split(' ', 2) if i>=4 and line[0..0]==':'
|
|
| 51 |
commit_files << {:action=>params[:file][:action],:path=>params[:file][:path]} if i>=4 and line[0..0]==':'
|
|
| 52 |
i+=1 |
|
| 53 |
end |
|
| 54 |
|
|
| 55 |
rev = Revision.new({:identifier => params[:commit],
|
|
| 56 |
:scmid => params[:commit], |
|
| 57 |
:author => params[:author], |
|
| 58 |
:time => Time.parse(params[:date]), |
|
| 59 |
:message => params[:message], |
|
| 60 |
:paths => commit_files |
|
| 61 |
}) |
|
| 62 |
end |
|
| 63 | ||
| 64 |
get_rev('latest',path) if i==0
|
|
| 65 | ||
| 66 |
return nil if $? && $?.exitstatus != 0 |
|
| 67 |
return rev |
|
| 68 |
# rescue Errno::ENOENT => e |
|
| 69 |
# raise CommandFailed |
|
| 70 |
end |
|
| 71 | ||
| 72 | ||
| 73 |
def info |
|
| 74 |
# cmd = "#{GIT_BIN} -R #{target('')} root"
|
|
| 75 |
# root_url = nil |
|
| 76 |
# shellout(cmd) do |io| |
|
| 77 |
root_url = target('')
|
|
| 78 |
# end |
|
| 79 |
return nil if $? && $?.exitstatus != 0 |
|
| 80 |
info = Info.new({:root_url => target(''),
|
|
| 81 |
:lastrev => revisions(root_url,nil,nil,nil).first |
|
| 82 |
}) |
|
| 83 |
info |
|
| 84 |
rescue Errno::ENOENT => e |
|
| 85 |
return nil |
|
| 86 |
end |
|
| 87 |
|
|
| 88 |
def entries(path=nil, identifier=nil) |
|
| 89 |
path ||= '' |
|
| 90 |
entries = Entries.new |
|
| 91 |
cmd = "cd #{target('')} && #{GIT_BIN} show HEAD:#{path}" if identifier.nil?
|
|
| 92 |
cmd = "cd #{target('')} && #{GIT_BIN} show #{identifier}:#{path}" if identifier
|
|
| 93 |
shellout(cmd) do |io| |
|
| 94 |
io.each_line do |line| |
|
| 95 |
e = line.chomp.split('\\')
|
|
| 96 |
unless e.to_s.strip=='' or line[0..3]=='tree' |
|
| 97 |
name=e.first.split('/')[0]
|
|
| 98 |
entries << Entry.new({:name => name,
|
|
| 99 |
:path => (path.empty? ? name : "#{path}/#{name}"),
|
|
| 100 |
:kind => ((e.first.include? '/') ? 'dir' : 'file'), |
|
| 101 |
:lastrev => get_rev(identifier,(path.empty? ? name : "#{path}/#{name}"))
|
|
| 102 |
}) unless entries.detect{|entry| entry.name == name}
|
|
| 103 |
puts e[0..3] |
|
| 104 |
end |
|
| 105 |
end |
|
| 106 |
end |
|
| 107 |
return nil if $? && $?.exitstatus != 0 |
|
| 108 |
entries.sort_by_name |
|
| 109 |
# rescue Errno::ENOENT => e |
|
| 110 |
# raise CommandFailed |
|
| 111 |
end |
|
| 112 |
|
|
| 113 |
def entry(path=nil, identifier=nil) |
|
| 114 |
path ||= '' |
|
| 115 |
search_path = path.split('/')[0..-2].join('/')
|
|
| 116 |
entry_name = path.split('/').last
|
|
| 117 |
e = entries(search_path, identifier) |
|
| 118 |
e ? e.detect{|entry| entry.name == entry_name} : nil
|
|
| 119 |
end |
|
| 120 |
|
|
| 121 |
def revisions(path, identifier_from, identifier_to, options={})
|
|
| 122 |
revisions = Revisions.new |
|
| 123 |
cmd = "cd #{target('')} && #{GIT_BIN} whatchanged "
|
|
| 124 |
cmd << " #{identifier_from}.. " if identifier_from
|
|
| 125 |
cmd << " #{identifier_to} " if identifier_to
|
|
| 126 |
#cmd << " HEAD " if !identifier_to |
|
| 127 |
puts cmd |
|
| 128 |
shellout(cmd) do |io| |
|
| 129 |
files=[] |
|
| 130 |
params={:commit=>'',:author=>'',:date=>'',:message=>'',:file=>{:path=>'',:action=>''}}
|
|
| 131 |
i=0 |
|
| 132 |
message='' |
|
| 133 |
io.each_line do |line| |
|
| 134 |
|
|
| 135 |
if line=~/^commit/ and i>0 |
|
| 136 |
revisions << Revision.new({:identifier => params[:commit],
|
|
| 137 |
:scmid => params[:commit], |
|
| 138 |
:author => params[:author], |
|
| 139 |
:time => Time.parse(params[:date]), |
|
| 140 |
:message => params[:message], |
|
| 141 |
:paths => files |
|
| 142 |
}) |
|
| 143 |
|
|
| 144 |
files=[] |
|
| 145 |
i=0 |
|
| 146 |
params={:commit=>'',:author=>'',:date=>'',:message=>'',:file=>{:path=>'',:action=>''}}
|
|
| 147 |
end |
|
| 148 |
params[:commit]=line.chomp.gsub("commit ",'') if i==0
|
|
| 149 |
params[:author]=line.chomp.gsub("Author: ",'') if i==1
|
|
| 150 |
params[:date]=line.chomp.gsub("Date: ",'') if i==2
|
|
| 151 |
params[:message]+= line.chomp.to_s if i>=4 and line[0..0]!=':' |
|
| 152 |
params[:file][:action], params[:file][:path]= line.chomp.slice(/[ACDMRTUXB].*/).split(' ', 2) if i>=4 and line[0..0]==':'
|
|
| 153 |
files << {:action=>params[:file][:action],:path=>params[:file][:path]} if i>=4 and line[0..0]==':'
|
|
| 154 |
i+=1 |
|
| 155 |
end |
|
| 156 |
end |
|
| 157 | ||
| 158 |
return nil if $? && $?.exitstatus != 0 |
|
| 159 |
revisions |
|
| 160 |
rescue Errno::ENOENT => e |
|
| 161 |
raise CommandFailed |
|
| 162 |
puts 'revs: #{revisions}'
|
|
| 163 |
end |
|
| 164 |
|
|
| 165 |
def diff(path, identifier_from, identifier_to=nil, type="inline") |
|
| 166 |
path ||= '' |
|
| 167 |
if identifier_to |
|
| 168 |
identifier_to = identifier_to |
|
| 169 |
else |
|
| 170 |
identifier_to = nil |
|
| 171 |
end |
|
| 172 |
cmd = "cd #{target('')} && #{GIT_BIN} diff #{identifier_from}^!" if identifier_to.nil?
|
|
| 173 |
cmd = "cd #{target('')} && #{GIT_BIN} diff #{identifier_to} #{identifier_from}" if !identifier_to.nil?
|
|
| 174 |
cmd << " #{path}" unless path.empty?
|
|
| 175 |
diff = [] |
|
| 176 |
shellout(cmd) do |io| |
|
| 177 |
io.each_line do |line| |
|
| 178 |
diff << line |
|
| 179 |
end |
|
| 180 |
end |
|
| 181 |
return nil if $? && $?.exitstatus != 0 |
|
| 182 |
DiffTableList.new diff, type |
|
| 183 |
|
|
| 184 |
rescue Errno::ENOENT => e |
|
| 185 |
raise CommandFailed |
|
| 186 |
end |
|
| 187 |
|
|
| 188 |
def cat(path, identifier=nil) |
|
| 189 |
cmd = "cd #{target('')} && #{GIT_BIN} show #{identifier}:#{path}"
|
|
| 190 |
cat = nil |
|
| 191 |
shellout(cmd) do |io| |
|
| 192 |
io.binmode |
|
| 193 |
cat = io.read |
|
| 194 |
end |
|
| 195 |
return nil if $? && $?.exitstatus != 0 |
|
| 196 |
cat |
|
| 197 |
rescue Errno::ENOENT => e |
|
| 198 |
raise CommandFailed |
|
| 199 |
end |
|
| 200 |
end |
|
| 201 |
end |
|
| 202 |
end |
|
| 203 | ||
| 204 |
end |
|
| 205 | ||
| lib/redmine.rb (working copy) | ||
|---|---|---|
| 10 | 10 |
# RMagick is not available |
| 11 | 11 |
end |
| 12 | 12 | |
| 13 |
REDMINE_SUPPORTED_SCM = %w( Subversion Darcs Mercurial Cvs ) |
|
| 13 |
REDMINE_SUPPORTED_SCM = %w( Subversion Darcs Mercurial Cvs Git)
|
|
| 14 | 14 | |
| 15 | 15 |
# Permissions |
| 16 | 16 |
Redmine::AccessControl.map do |map| |
- « Previous
- 1
- 2
- 3
- 4
- Next »