# HG changeset patch # User Chris Cannam # Date 1301331025 -3600 # Node ID b9c2ba9e49b49a5578d4d093a7b540603e78b6b2 # Parent 2de308601155de912e7df6af4e9313eed0cd15d9# Parent defe55be97b9d9fb210123aa781221dd144a6e7e Merge from branch "feature_73" diff -r 2de308601155 -r b9c2ba9e49b4 app/controllers/repositories_controller.rb --- a/app/controllers/repositories_controller.rb Wed Mar 23 11:33:36 2011 +0000 +++ b/app/controllers/repositories_controller.rb Mon Mar 28 17:50:25 2011 +0100 @@ -36,7 +36,11 @@ def edit @repository = @project.repository + if !@repository + + params[:repository_scm]='Mercurial' + @repository = Repository.factory(params[:repository_scm]) @repository.project = @project if @repository end @@ -44,6 +48,7 @@ @repository.attributes = params[:repository] @repository.save end + render(:update) do |page| page.replace_html "tab-content-repository", :partial => 'projects/settings/repository' if @repository && !@project.repository diff -r 2de308601155 -r b9c2ba9e49b4 app/controllers/sys_controller.rb --- a/app/controllers/sys_controller.rb Wed Mar 23 11:33:36 2011 +0000 +++ b/app/controllers/sys_controller.rb Mon Mar 28 17:50:25 2011 +0100 @@ -55,6 +55,20 @@ render :nothing => true, :status => 404 end + def get_external_repo_url + project = Project.find(params[:id]) + if project.repository + repo = project.repository + if repo.is_external? + render :text => repo.external_url, :status => 200 + else + render :nothing => true, :status => 200 + end + end + rescue ActiveRecord::RecordNotFound + render :nothing => true, :status => 404 + end + def set_embedded_active project = Project.find(params[:id]) mods = project.enabled_modules diff -r 2de308601155 -r b9c2ba9e49b4 app/helpers/repositories_helper.rb --- a/app/helpers/repositories_helper.rb Wed Mar 23 11:33:36 2011 +0000 +++ b/app/helpers/repositories_helper.rb Mon Mar 28 17:50:25 2011 +0100 @@ -151,7 +151,7 @@ scm_options << ["Repository::#{scm}".constantize.scm_name, scm] if Setting.enabled_scm.include?(scm) || (repository && repository.class.name.demodulize == scm) end - select_tag('repository_scm', + select_tag('repository_scm', options_for_select(scm_options, repository.class.name.demodulize), :disabled => (repository && !repository.new_record?), :onchange => remote_function(:url => { :controller => 'repositories', :action => 'edit', :id => @project }, :method => :get, :with => "Form.serialize(this.form)") diff -r 2de308601155 -r b9c2ba9e49b4 app/models/repository/mercurial.rb --- a/app/models/repository/mercurial.rb Wed Mar 23 11:33:36 2011 +0000 +++ b/app/models/repository/mercurial.rb Mon Mar 28 17:50:25 2011 +0100 @@ -19,7 +19,7 @@ class Repository::Mercurial < Repository attr_protected :root_url - validates_presence_of :url + # validates_presence_of :url FETCH_AT_ONCE = 100 # number of changesets to fetch at once diff -r 2de308601155 -r b9c2ba9e49b4 app/views/projects/settings/_repository.rhtml --- a/app/views/projects/settings/_repository.rhtml Wed Mar 23 11:33:36 2011 +0000 +++ b/app/views/projects/settings/_repository.rhtml Mon Mar 28 17:50:25 2011 +0100 @@ -1,3 +1,6 @@ + +<%= javascript_include_tag 'repository' %> + <% remote_form_for :repository, @repository, :url => { :controller => 'repositories', :action => 'edit', :id => @project }, :builder => TabularFormBuilder, @@ -6,22 +9,48 @@ <%= error_messages_for 'repository' %>
<%= label_tag('repository_scm', l(:label_scm)) %><%= scm_select_tag(@repository) %>
-<%= repository_field_tags(f, @repository) if @repository %> + ++<% if @repository %> + <%= l(:text_settings_repo_explanation) %> br> + <% if @repository.is_external %> +
<%= l(:text_settings_repo_is_external) %> br> + <% else %> +
<%= l(:text_settings_repo_is_internal) %> br> + <% end %> +
+ + + + + +
+ <%= label_tag('repository_is_external', l(:label_is_external_repository)) %>
+ <%= check_box :repository, :is_external, :onclick => "toggle_ext_url()" %>
+
<%= l(:setting_external_repository) %>
+
+ <%= label_tag('repository_external_url', l(:label_repository_external_url)) %>
+ <%= text_field :repository, :external_url, :disabled => !(@repository and @repository.is_external) %>
+
<%= l(:setting_external_repository_url) %>
+
<%= l(:text_settings_repo_need_help) %>
+The source code repository for a project will be set up automatically within a few minutes of the project being created.
Please check again in five minutes, and contact us if there is any problem.
If you wish to use this project to track a repository that is already hosted somewhere else, please wait until the repository has been created here and then return to this settings page to configure it.
If you don't want a repository at all, go to the Modules tab and switch it off there.
text_files_active_change:
Click the star to switch active status for a download on or off.
Active files will be shown more prominently in the download page.
+ text_settings_repo_explanation: External repositories
Normally your project's primary repository will be the Mercurial repository hosted at this site.
However, if you already have your project hosted somewhere else, you can specify your existing external repository's URL here – then this site will track that repository in a read-only “mirror” copy. External Mercurial, git and Subversion repositories can be tracked. Note that you cannot switch to an external repository if you have already made any commits to the repository hosted here.
+ text_settings_repo_is_internal: Currently the repository hosted at this site is the primary repository for this project.
+ text_settings_repo_is_external: Currently the repository hosted at this site is a read-only copy of an external repository.
+ text_settings_repo_need_help: Please contact us if you need help deciding how best to set this up.
We can also import complete revision history from other systems into a new primary repository for you if you wish.
+
+
default_role_manager: Manager
default_role_developer: Developer
diff -r 2de308601155 -r b9c2ba9e49b4 config/routes.rb
--- a/config/routes.rb Wed Mar 23 11:33:36 2011 +0000
+++ b/config/routes.rb Mon Mar 28 17:50:25 2011 +0100
@@ -236,6 +236,7 @@
map.with_options :controller => 'sys' do |sys|
sys.connect 'sys/projects.:format', :action => 'projects', :conditions => {:method => :get}
sys.connect 'sys/projects/:id/repository.:format', :action => 'create_project_repository', :conditions => {:method => :post}
+ sys.connect 'sys/projects/:id/external-repository.:format', :action => 'get_external_repo_url', :conditions => {:method => :get}
sys.connect 'sys/projects/:id/embedded.:format', :action => 'set_embedded_active', :conditions => { :method => :post }
end
diff -r 2de308601155 -r b9c2ba9e49b4 db/migrate/20110207142856_add_ext_rep_to_repositories.rb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/db/migrate/20110207142856_add_ext_rep_to_repositories.rb Mon Mar 28 17:50:25 2011 +0100
@@ -0,0 +1,11 @@
+class AddExtRepToRepositories < ActiveRecord::Migration
+ def self.up
+ add_column :repositories, :is_external, :bool
+ add_column :repositories, :external_url, :string
+ end
+
+ def self.down
+ remove_column :repositories, :is_external
+ remove_column :repositories, :external_url
+ end
+end
diff -r 2de308601155 -r b9c2ba9e49b4 extra/soundsoftware/convert-external-repos.rb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/extra/soundsoftware/convert-external-repos.rb Mon Mar 28 17:50:25 2011 +0100
@@ -0,0 +1,173 @@
+#!/usr/bin/env ruby
+
+# == Synopsis
+#
+# convert-external-repos: Update local Mercurial mirrors of external repos,
+# by running an external command for each project requiring an update.
+#
+# == Usage
+#
+# convert-external-repos [OPTIONS...] -s [DIR] -r [HOST]
+#
+# == Arguments (mandatory)
+#
+# -s, --scm-dir=DIR use DIR as base directory for repositories
+# -r, --redmine-host=HOST assume Redmine is hosted on HOST. Examples:
+# -r redmine.example.net
+# -r http://redmine.example.net
+# -r https://example.net/redmine
+# -k, --key=KEY use KEY as the Redmine API key
+# -c, --command=COMMAND use this command to update each external
+# repository: command is called with the name
+# of the project, the path to its repo, and
+# its external repo url as its three args
+#
+# == Options
+#
+# --http-user=USER User for HTTP Basic authentication with Redmine WS
+# --http-pass=PASSWORD Password for Basic authentication with Redmine WS
+# -t, --test only show what should be done
+# -h, --help show help and exit
+# -v, --verbose verbose
+# -V, --version print version and exit
+# -q, --quiet no log
+
+
+require 'getoptlong'
+require 'rdoc/usage'
+require 'find'
+require 'etc'
+
+Version = "1.0"
+
+opts = GetoptLong.new(
+ ['--scm-dir', '-s', GetoptLong::REQUIRED_ARGUMENT],
+ ['--redmine-host', '-r', GetoptLong::REQUIRED_ARGUMENT],
+ ['--key', '-k', GetoptLong::REQUIRED_ARGUMENT],
+ ['--http-user', GetoptLong::REQUIRED_ARGUMENT],
+ ['--http-pass', GetoptLong::REQUIRED_ARGUMENT],
+ ['--command' , '-c', GetoptLong::REQUIRED_ARGUMENT],
+ ['--test', '-t', GetoptLong::NO_ARGUMENT],
+ ['--verbose', '-v', GetoptLong::NO_ARGUMENT],
+ ['--version', '-V', GetoptLong::NO_ARGUMENT],
+ ['--help' , '-h', GetoptLong::NO_ARGUMENT],
+ ['--quiet' , '-q', GetoptLong::NO_ARGUMENT]
+ )
+
+$verbose = 0
+$quiet = false
+$redmine_host = ''
+$repos_base = ''
+$http_user = ''
+$http_pass = ''
+$test = false
+
+def log(text, options={})
+ level = options[:level] || 0
+ puts text unless $quiet or level > $verbose
+ exit 1 if options[:exit]
+end
+
+def system_or_raise(command)
+ raise "\"#{command}\" failed" unless system command
+end
+
+begin
+ opts.each do |opt, arg|
+ case opt
+ when '--scm-dir'; $repos_base = arg.dup
+ when '--redmine-host'; $redmine_host = arg.dup
+ when '--key'; $api_key = arg.dup
+ when '--http-user'; $http_user = arg.dup
+ when '--http-pass'; $http_pass = arg.dup
+ when '--command'; $command = arg.dup
+ when '--verbose'; $verbose += 1
+ when '--test'; $test = true
+ when '--version'; puts Version; exit
+ when '--help'; RDoc::usage
+ when '--quiet'; $quiet = true
+ end
+ end
+rescue
+ exit 1
+end
+
+if $test
+ log("running in test mode")
+end
+
+if ($redmine_host.empty? or $repos_base.empty? or $command.empty?)
+ RDoc::usage
+end
+
+unless File.directory?($repos_base)
+ log("directory '#{$repos_base}' doesn't exist", :exit => true)
+end
+
+begin
+ require 'active_resource'
+rescue LoadError
+ log("This script requires activeresource.\nRun 'gem install activeresource' to install it.", :exit => true)
+end
+
+class Project < ActiveResource::Base
+ self.headers["User-agent"] = "SoundSoftware external repository converter/#{Version}"
+end
+
+log("querying Redmine for projects...", :level => 1);
+
+$redmine_host.gsub!(/^/, "http://") unless $redmine_host.match("^https?://")
+$redmine_host.gsub!(/\/$/, '')
+
+Project.site = "#{$redmine_host}/sys";
+Project.user = $http_user;
+Project.password = $http_pass;
+
+begin
+ # Get all active projects that have the Repository module enabled
+ projects = Project.find(:all, :params => {:key => $api_key})
+rescue => e
+ log("Unable to connect to #{Project.site}: #{e}", :exit => true)
+end
+
+if projects.nil?
+ log('no project found, perhaps you forgot to "Enable WS for repository management"', :exit => true)
+end
+
+log("retrieved #{projects.size} projects", :level => 1)
+
+projects.each do |project|
+ log("treating project #{project.name}", :level => 1)
+
+ if project.identifier.empty?
+ log("\tno identifier for project #{project.name}")
+ next
+ elsif not project.identifier.match(/^[a-z0-9\-]+$/)
+ log("\tinvalid identifier for project #{project.name} : #{project.identifier}");
+ next
+ end
+
+ if !project.respond_to?(:repository) or !project.repository.is_external?
+ log("\tproject #{project.identifier} does not use an external repository");
+ next
+ end
+
+ external_url = project.repository.external_url;
+ log("\tproject #{project.identifier} has external repository url #{external_url}");
+
+ if !external_url.match(/^[a-z][a-z+]{0,8}[a-z]:\/\//)
+ log("\tthis doesn't look like a plausible url to me, skipping")
+ next
+ end
+
+ repos_path = File.join($repos_base, project.identifier).gsub(File::SEPARATOR, File::ALT_SEPARATOR || File::SEPARATOR)
+
+ unless File.directory?(repos_path)
+ log("\tproject repo directory '#{repos_path}' doesn't exist")
+ next
+ end
+
+ system($command, project.identifier, repos_path, external_url)
+
+end
+
diff -r 2de308601155 -r b9c2ba9e49b4 extra/soundsoftware/reposman-soundsoftware.rb
--- a/extra/soundsoftware/reposman-soundsoftware.rb Wed Mar 23 11:33:36 2011 +0000
+++ b/extra/soundsoftware/reposman-soundsoftware.rb Mon Mar 28 17:50:25 2011 +0100
@@ -9,12 +9,12 @@
# reposman [OPTIONS...] -s [DIR] -r [HOST]
#
# Examples:
-# reposman --svn-dir=/var/svn --redmine-host=redmine.example.net --scm subversion
+# reposman --scm-dir=/var/svn --redmine-host=redmine.example.net --scm subversion
# reposman -s /var/git -r redmine.example.net -u http://svn.example.net --scm git
#
# == Arguments (mandatory)
#
-# -s, --svn-dir=DIR use DIR as base directory for svn repositories
+# -s, --scm-dir=DIR use DIR as base directory for repositories
# -r, --redmine-host=HOST assume Redmine is hosted on HOST. Examples:
# -r redmine.example.net
# -r http://redmine.example.net
@@ -70,7 +70,7 @@
SUPPORTED_SCM = %w( Subversion Darcs Mercurial Bazaar Git Filesystem )
opts = GetoptLong.new(
- ['--svn-dir', '-s', GetoptLong::REQUIRED_ARGUMENT],
+ ['--scm-dir', '-s', GetoptLong::REQUIRED_ARGUMENT],
['--redmine-host', '-r', GetoptLong::REQUIRED_ARGUMENT],
['--key', '-k', GetoptLong::REQUIRED_ARGUMENT],
['--owner', '-o', GetoptLong::REQUIRED_ARGUMENT],
@@ -133,7 +133,7 @@
begin
opts.each do |opt, arg|
case opt
- when '--svn-dir'; $repos_base = arg.dup
+ when '--scm-dir'; $repos_base = arg.dup
when '--redmine-host'; $redmine_host = arg.dup
when '--key'; $api_key = arg.dup
when '--owner'; $svn_owner = arg.dup; $use_groupid = false;
@@ -174,7 +174,7 @@
end
unless File.directory?($repos_base)
- log("directory '#{$repos_base}' doesn't exists", :exit => true)
+ log("directory '#{$repos_base}' doesn't exist", :exit => true)
end
begin
@@ -184,7 +184,7 @@
end
class Project < ActiveResource::Base
- self.headers["User-agent"] = "Redmine repository manager/#{Version}"
+ self.headers["User-agent"] = "SoundSoftware repository manager/#{Version}"
end
log("querying Redmine for projects...", :level => 1);
@@ -346,5 +346,14 @@
log("\trepository #{repos_path} created");
end
+ if project.respond_to?(:repository) and project.repository.is_external?
+ external_url = project.repository.external_url;
+ log("\tproject #{project.identifier} has external repository url #{external_url}");
+ if !external_url.match(/^https?:/)
+ # wot about git, svn/svn+ssh, etc? should we just check for a scheme at all?
+ log("\tthis is not an http(s) url: ignoring");
+ end
+ end
+
end
diff -r 2de308601155 -r b9c2ba9e49b4 extra/soundsoftware/update-external-repo.sh
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/extra/soundsoftware/update-external-repo.sh Mon Mar 28 17:50:25 2011 +0100
@@ -0,0 +1,107 @@
+#!/bin/sh
+
+mirrordir="/var/mirror"
+logfile="/var/www/test-cannam/log/update-external-repo.log"
+
+project="$1"
+local_repo="$2"
+remote_repo="$3"
+
+if [ -z "$project" ] || [ -z "$local_repo" ] || [ -z "$remote_repo" ]; then
+ echo "Usage: $0