From 3a2a185a0e90719522fa318178240e73d280157b Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Thu, 5 Feb 2009 06:04:57 -0800 Subject: [PATCH 001/219] [NEW] Extend the Subversion parsers to get the copyfrom-rev and copyfrom-path. --- lib/scm/adapters/svn_adapter.rb | 1 + lib/scm/diff.rb | 4 ++++ lib/scm/parsers/svn_parser.rb | 4 ++-- lib/scm/parsers/svn_xml_parser.rb | 4 +++- test/unit/svn_parser_test.rb | 18 ++++++++++++++++++ test/unit/svn_xml_parser_test.rb | 26 ++++++++++++++++++++++++++ 6 files changed, 54 insertions(+), 3 deletions(-) diff --git a/lib/scm/adapters/svn_adapter.rb b/lib/scm/adapters/svn_adapter.rb index cb2569fc..bd57f41b 100644 --- a/lib/scm/adapters/svn_adapter.rb +++ b/lib/scm/adapters/svn_adapter.rb @@ -13,3 +13,4 @@ def english_name require 'lib/scm/adapters/svn/pull' require 'lib/scm/adapters/svn/head' require 'lib/scm/adapters/svn/misc' +require 'lib/scm/adapters/svn/chain' diff --git a/lib/scm/diff.rb b/lib/scm/diff.rb index 82db21a8..1263cb96 100644 --- a/lib/scm/diff.rb +++ b/lib/scm/diff.rb @@ -27,6 +27,10 @@ class Diff # These must be computed using the same method as Git. attr_accessor :parent_sha1, :sha1 + # For Subversion only, a path may be reported as copied from another location. + # These attributes store the path and revision number of the source of the copy. + attr_accessor :from_path, :from_revision + def initialize(params={}) params.each { |k,v| send(k.to_s + '=', v) if respond_to?(k.to_s + '=') } end diff --git a/lib/scm/parsers/svn_parser.rb b/lib/scm/parsers/svn_parser.rb index 97f0d4ac..c3541d50 100644 --- a/lib/scm/parsers/svn_parser.rb +++ b/lib/scm/parsers/svn_parser.rb @@ -24,9 +24,9 @@ def self.internal_parse(buffer, opts) end elsif state == :diffs - if l =~ /^ (\w) ([^\(\)]+)( \(from .+:\d+\))?$/ + if l =~ /^ (\w) ([^\(\)]+)( \(from (.+):(\d+)\))?$/ e.diffs ||= [] - e.diffs << Scm::Diff.new(:action => $1, :path => $2) + e.diffs << Scm::Diff.new(:action => $1, :path => $2, :from_path => $4, :from_revision => $5.to_i) else next_state = :comment end diff --git a/lib/scm/parsers/svn_xml_parser.rb b/lib/scm/parsers/svn_xml_parser.rb index 5d95ce39..8bb7f6ea 100644 --- a/lib/scm/parsers/svn_xml_parser.rb +++ b/lib/scm/parsers/svn_xml_parser.rb @@ -20,7 +20,9 @@ def tag_start(name, attrs) @commit.diffs = [] @commit.token = attrs['revision'].to_i when 'path' - @diff = Scm::Diff.new(:action => attrs['action']) + @diff = Scm::Diff.new(:action => attrs['action'], + :from_path => attrs['copyfrom-path'], + :from_revision => attrs['copyfrom-rev'].to_i) end end diff --git a/test/unit/svn_parser_test.rb b/test/unit/svn_parser_test.rb index ffcaa0b7..09790fd9 100644 --- a/test/unit/svn_parser_test.rb +++ b/test/unit/svn_parser_test.rb @@ -133,5 +133,23 @@ def test_log_embedded_in_comments COMMENT assert_equal comment, revs[0].message end + + def test_svn_copy + log = <<-LOG +------------------------------------------------------------------------ +r8 | robin | 2009-02-05 05:40:46 -0800 (Thu, 05 Feb 2009) | 1 line +Changed paths: + A /trunk (from /branches/development:7) + +the branch becomes the new trunk + LOG + + commits = SvnParser.parse(log) + assert_equal 1, commits.size + assert_equal 1, commits.first.diffs.size + assert_equal "/trunk", commits.first.diffs.first.path + assert_equal "/branches/development", commits.first.diffs.first.from_path + assert_equal 7, commits.first.diffs.first.from_revision + end end end diff --git a/test/unit/svn_xml_parser_test.rb b/test/unit/svn_xml_parser_test.rb index de1f12d0..1eeb337d 100644 --- a/test/unit/svn_xml_parser_test.rb +++ b/test/unit/svn_xml_parser_test.rb @@ -14,6 +14,32 @@ def test_empty_array def test_empty_xml assert_equal("\n\n\n", SvnXmlParser.parse('', :writer => XmlWriter.new)) end + + def test_copy_from + xml = <<-XML + + + +robin +2009-02-05T13:40:46.386190Z + +/trunk + +the branch becomes the new trunk + + + XML + commits = SvnXmlParser.parse(xml) + assert_equal 1, commits.size + assert_equal 1, commits.first.diffs.size + assert_equal "/trunk", commits.first.diffs.first.path + assert_equal "/branches/development", commits.first.diffs.first.from_path + assert_equal 7, commits.first.diffs.first.from_revision + end end end From e55c445565c75d8d374c1e0ee51e3c6eb7f24059 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Thu, 5 Feb 2009 07:08:38 -0800 Subject: [PATCH 002/219] [NEW] Subversion "chain" detects when the first commit of the current branch is actually a directory copy from somewhere else. --- lib/scm/adapters/svn/chain.rb | 26 +++++++ lib/scm/adapters/svn/commits.rb | 17 +++-- .../svn_with_branching/README.txt | 5 ++ .../svn_with_branching/conf/authz | 21 ++++++ .../svn_with_branching/conf/passwd | 8 ++ .../svn_with_branching/conf/svnserve.conf | 30 ++++++++ .../svn_with_branching/db/current | 1 + .../repositories/svn_with_branching/db/format | 1 + .../svn_with_branching/db/fs-type | 1 + .../svn_with_branching/db/revprops/0 | 5 ++ .../svn_with_branching/db/revprops/1 | 13 ++++ .../svn_with_branching/db/revprops/2 | 13 ++++ .../svn_with_branching/db/revprops/3 | 13 ++++ .../svn_with_branching/db/revprops/4 | 13 ++++ .../svn_with_branching/db/revprops/5 | 13 ++++ .../svn_with_branching/db/revprops/6 | 13 ++++ .../svn_with_branching/db/revprops/7 | 13 ++++ .../svn_with_branching/db/revprops/8 | 13 ++++ .../svn_with_branching/db/revprops/9 | 13 ++++ .../repositories/svn_with_branching/db/revs/0 | 11 +++ .../repositories/svn_with_branching/db/revs/1 | 49 ++++++++++++ .../repositories/svn_with_branching/db/revs/2 | Bin 0 -> 681 bytes .../repositories/svn_with_branching/db/revs/3 | 23 ++++++ .../repositories/svn_with_branching/db/revs/4 | 35 +++++++++ .../repositories/svn_with_branching/db/revs/5 | Bin 0 -> 1041 bytes .../repositories/svn_with_branching/db/revs/6 | 54 ++++++++++++++ .../repositories/svn_with_branching/db/revs/7 | 23 ++++++ .../repositories/svn_with_branching/db/revs/8 | 35 +++++++++ .../repositories/svn_with_branching/db/revs/9 | Bin 0 -> 781 bytes test/repositories/svn_with_branching/db/uuid | 1 + .../svn_with_branching/db/write-lock | 0 test/repositories/svn_with_branching/format | 1 + .../svn_with_branching/hooks/post-commit.tmpl | 51 +++++++++++++ .../svn_with_branching/hooks/post-lock.tmpl | 44 +++++++++++ .../hooks/post-revprop-change.tmpl | 56 ++++++++++++++ .../svn_with_branching/hooks/post-unlock.tmpl | 42 +++++++++++ .../svn_with_branching/hooks/pre-commit.tmpl | 70 ++++++++++++++++++ .../svn_with_branching/hooks/pre-lock.tmpl | 64 ++++++++++++++++ .../hooks/pre-revprop-change.tmpl | 66 +++++++++++++++++ .../svn_with_branching/hooks/pre-unlock.tmpl | 60 +++++++++++++++ .../hooks/start-commit.tmpl | 54 ++++++++++++++ .../svn_with_branching/locks/db-logs.lock | 3 + .../svn_with_branching/locks/db.lock | 3 + test/test_helper.rb | 27 ++++--- test/unit/svn_chain_test.rb | 21 ++++++ test/unit/svn_commits_test.rb | 17 +++++ 46 files changed, 1025 insertions(+), 17 deletions(-) create mode 100644 lib/scm/adapters/svn/chain.rb create mode 100644 test/repositories/svn_with_branching/README.txt create mode 100644 test/repositories/svn_with_branching/conf/authz create mode 100644 test/repositories/svn_with_branching/conf/passwd create mode 100644 test/repositories/svn_with_branching/conf/svnserve.conf create mode 100644 test/repositories/svn_with_branching/db/current create mode 100644 test/repositories/svn_with_branching/db/format create mode 100644 test/repositories/svn_with_branching/db/fs-type create mode 100644 test/repositories/svn_with_branching/db/revprops/0 create mode 100644 test/repositories/svn_with_branching/db/revprops/1 create mode 100644 test/repositories/svn_with_branching/db/revprops/2 create mode 100644 test/repositories/svn_with_branching/db/revprops/3 create mode 100644 test/repositories/svn_with_branching/db/revprops/4 create mode 100644 test/repositories/svn_with_branching/db/revprops/5 create mode 100644 test/repositories/svn_with_branching/db/revprops/6 create mode 100644 test/repositories/svn_with_branching/db/revprops/7 create mode 100644 test/repositories/svn_with_branching/db/revprops/8 create mode 100644 test/repositories/svn_with_branching/db/revprops/9 create mode 100644 test/repositories/svn_with_branching/db/revs/0 create mode 100644 test/repositories/svn_with_branching/db/revs/1 create mode 100644 test/repositories/svn_with_branching/db/revs/2 create mode 100644 test/repositories/svn_with_branching/db/revs/3 create mode 100644 test/repositories/svn_with_branching/db/revs/4 create mode 100644 test/repositories/svn_with_branching/db/revs/5 create mode 100644 test/repositories/svn_with_branching/db/revs/6 create mode 100644 test/repositories/svn_with_branching/db/revs/7 create mode 100644 test/repositories/svn_with_branching/db/revs/8 create mode 100644 test/repositories/svn_with_branching/db/revs/9 create mode 100644 test/repositories/svn_with_branching/db/uuid create mode 100644 test/repositories/svn_with_branching/db/write-lock create mode 100644 test/repositories/svn_with_branching/format create mode 100644 test/repositories/svn_with_branching/hooks/post-commit.tmpl create mode 100644 test/repositories/svn_with_branching/hooks/post-lock.tmpl create mode 100644 test/repositories/svn_with_branching/hooks/post-revprop-change.tmpl create mode 100644 test/repositories/svn_with_branching/hooks/post-unlock.tmpl create mode 100644 test/repositories/svn_with_branching/hooks/pre-commit.tmpl create mode 100644 test/repositories/svn_with_branching/hooks/pre-lock.tmpl create mode 100644 test/repositories/svn_with_branching/hooks/pre-revprop-change.tmpl create mode 100644 test/repositories/svn_with_branching/hooks/pre-unlock.tmpl create mode 100644 test/repositories/svn_with_branching/hooks/start-commit.tmpl create mode 100644 test/repositories/svn_with_branching/locks/db-logs.lock create mode 100644 test/repositories/svn_with_branching/locks/db.lock create mode 100644 test/unit/svn_chain_test.rb diff --git a/lib/scm/adapters/svn/chain.rb b/lib/scm/adapters/svn/chain.rb new file mode 100644 index 00000000..00957f62 --- /dev/null +++ b/lib/scm/adapters/svn/chain.rb @@ -0,0 +1,26 @@ +module Scm::Adapters + class SvnAdapter < AbstractAdapter + + def first_revision(since=0) + commit_tokens(since).first + end + + def first_commit(since=0) + verbose_commit(first_revision) + end + + def parent_svn(since=0) + c = first_commit(since) + if c && c.diffs.size == 1 + d = c.diffs.first + if d.action == 'A' && d.path == branch_name && d.from_path && d.from_revision + prior_svn = self.clone + prior_svn.branch_name = d.from_path + prior_svn.final_revision = d.from_revision + prior_svn + end + end + end + + end +end diff --git a/lib/scm/adapters/svn/commits.rb b/lib/scm/adapters/svn/commits.rb index 2ea8dd95..87e7af9f 100644 --- a/lib/scm/adapters/svn/commits.rb +++ b/lib/scm/adapters/svn/commits.rb @@ -3,6 +3,11 @@ module Scm::Adapters class SvnAdapter < AbstractAdapter + # The last revision to be analyzed in this repository. Everything after this revision is ignored. + # The repository is considered to be retired after this point, and under no circumstances should + # this adapter ever return information regarding commits after this point. + attr_accessor :final_revision + # In all commit- and log-related methods, 'since' refers to the revision number of the last known commit, # and the methods return the commits *following* this commit. # @@ -14,12 +19,14 @@ class SvnAdapter < AbstractAdapter # Returns the count of commits following revision number 'since'. def commit_count(since=0) - run("svn log -q -r #{since.to_i + 1}:HEAD --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}' | grep -E -e '^r[0-9]+ ' | wc -l").strip.to_i + return 0 if final_revision && since > final_revision + run("svn log -q -r #{since.to_i + 1}:#{final_revision || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}' | grep -E -e '^r[0-9]+ ' | wc -l").strip.to_i end # Returns an array of revision numbers for all commits following revision number 'since'. def commit_tokens(since=0) - cmd = "svn log -q -r #{since.to_i + 1}:HEAD --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}' | grep -E -e '^r[0-9]+ ' | cut -f 1 -d '|' | cut -c 2-" + return [] if final_revision && since > final_revision + cmd = "svn log -q -r #{since.to_i + 1}:#{final_revision || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}' | grep -E -e '^r[0-9]+ ' | cut -f 1 -d '|' | cut -c 2-" run(cmd).split.collect { |r| r.to_i } end @@ -141,13 +148,13 @@ def verbose_commit(rev) #--------------------------------------------------------------------- def log(since=0) - run "svn log --xml --stop-on-copy -r #{since.to_i + 1}:HEAD '#{SvnAdapter.uri_encode(self.url)}' #{opt_auth}" + run "svn log --xml --stop-on-copy -r #{since.to_i + 1}:#{final_revision || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name.to_s))}' #{opt_auth}" end def open_log_file(since=0) begin if (since.to_i + 1) <= head_token - run "svn log --xml --stop-on-copy -r #{since.to_i + 1}:HEAD '#{SvnAdapter.uri_encode(self.url)}' #{opt_auth} > #{log_filename}" + run "svn log --xml --stop-on-copy -r #{since.to_i + 1}:#{final_revision || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}' #{opt_auth} > #{log_filename}" else # As a time optimization, just create an empty file rather than fetch a log we know will be empty. File.open(log_filename, 'w') { |f| f.puts '' } @@ -171,7 +178,7 @@ def single_revision_xml(revision) # Directories named 'CVSROOT' are always ignored and the files they contain are never returned. # An empty array means that the call succeeded, but the remote directory is empty. # A nil result means that the call failed and the remote server could not be queried. - def recurse_files(path=nil, revision='HEAD') + def recurse_files(path=nil, revision=final_revision || 'HEAD') begin stdout = run "svn ls -r #{revision} --recursive #{opt_auth} '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s, path.to_s))}@#{revision}'" rescue diff --git a/test/repositories/svn_with_branching/README.txt b/test/repositories/svn_with_branching/README.txt new file mode 100644 index 00000000..3bf5a571 --- /dev/null +++ b/test/repositories/svn_with_branching/README.txt @@ -0,0 +1,5 @@ +This is a Subversion repository; use the 'svnadmin' tool to examine +it. Do not add, delete, or modify files here unless you know how +to avoid corrupting the repository. + +Visit http://subversion.tigris.org/ for more information. diff --git a/test/repositories/svn_with_branching/conf/authz b/test/repositories/svn_with_branching/conf/authz new file mode 100644 index 00000000..78cb28e9 --- /dev/null +++ b/test/repositories/svn_with_branching/conf/authz @@ -0,0 +1,21 @@ +### This file is an example authorization file for svnserve. +### Its format is identical to that of mod_authz_svn authorization +### files. +### As shown below each section defines authorizations for the path and +### (optional) repository specified by the section name. +### The authorizations follow. An authorization line can refer to a +### single user, to a group of users defined in a special [groups] +### section, or to anyone using the '*' wildcard. Each definition can +### grant read ('r') access, read-write ('rw') access, or no access +### (''). + +[groups] +# harry_and_sally = harry,sally + +# [/foo/bar] +# harry = rw +# * = + +# [repository:/baz/fuz] +# @harry_and_sally = rw +# * = r diff --git a/test/repositories/svn_with_branching/conf/passwd b/test/repositories/svn_with_branching/conf/passwd new file mode 100644 index 00000000..ecaa08dc --- /dev/null +++ b/test/repositories/svn_with_branching/conf/passwd @@ -0,0 +1,8 @@ +### This file is an example password file for svnserve. +### Its format is similar to that of svnserve.conf. As shown in the +### example below it contains one section labelled [users]. +### The name and password for each user follow, one account per line. + +[users] +# harry = harryssecret +# sally = sallyssecret diff --git a/test/repositories/svn_with_branching/conf/svnserve.conf b/test/repositories/svn_with_branching/conf/svnserve.conf new file mode 100644 index 00000000..b52bc5ab --- /dev/null +++ b/test/repositories/svn_with_branching/conf/svnserve.conf @@ -0,0 +1,30 @@ +### This file controls the configuration of the svnserve daemon, if you +### use it to allow access to this repository. (If you only allow +### access through http: and/or file: URLs, then this file is +### irrelevant.) + +### Visit http://subversion.tigris.org/ for more information. + +[general] +### These options control access to the repository for unauthenticated +### and authenticated users. Valid values are "write", "read", +### and "none". The sample settings below are the defaults. +# anon-access = read +# auth-access = write +### The password-db option controls the location of the password +### database file. Unless you specify a path starting with a /, +### the file's location is relative to the conf directory. +### Uncomment the line below to use the default password file. +# password-db = passwd +### The authz-db option controls the location of the authorization +### rules for path-based access control. Unless you specify a path +### starting with a /, the file's location is relative to the conf +### directory. If you don't specify an authz-db, no path-based access +### control is done. +### Uncomment the line below to use the default authorization file. +# authz-db = authz +### This option specifies the authentication realm of the repository. +### If two repositories have the same authentication realm, they should +### have the same password database, and vice versa. The default realm +### is repository's uuid. +# realm = My First Repository diff --git a/test/repositories/svn_with_branching/db/current b/test/repositories/svn_with_branching/db/current new file mode 100644 index 00000000..a25d7ec7 --- /dev/null +++ b/test/repositories/svn_with_branching/db/current @@ -0,0 +1 @@ +9 6 5 diff --git a/test/repositories/svn_with_branching/db/format b/test/repositories/svn_with_branching/db/format new file mode 100644 index 00000000..0cfbf088 --- /dev/null +++ b/test/repositories/svn_with_branching/db/format @@ -0,0 +1 @@ +2 diff --git a/test/repositories/svn_with_branching/db/fs-type b/test/repositories/svn_with_branching/db/fs-type new file mode 100644 index 00000000..4fdd9531 --- /dev/null +++ b/test/repositories/svn_with_branching/db/fs-type @@ -0,0 +1 @@ +fsfs diff --git a/test/repositories/svn_with_branching/db/revprops/0 b/test/repositories/svn_with_branching/db/revprops/0 new file mode 100644 index 00000000..8e6bc273 --- /dev/null +++ b/test/repositories/svn_with_branching/db/revprops/0 @@ -0,0 +1,5 @@ +K 8 +svn:date +V 27 +2009-02-05T13:31:04.304965Z +END diff --git a/test/repositories/svn_with_branching/db/revprops/1 b/test/repositories/svn_with_branching/db/revprops/1 new file mode 100644 index 00000000..7db8b2cb --- /dev/null +++ b/test/repositories/svn_with_branching/db/revprops/1 @@ -0,0 +1,13 @@ +K 10 +svn:author +V 5 +robin +K 8 +svn:date +V 27 +2009-02-05T13:32:07.992496Z +K 7 +svn:log +V 16 +Initial Revision +END diff --git a/test/repositories/svn_with_branching/db/revprops/2 b/test/repositories/svn_with_branching/db/revprops/2 new file mode 100644 index 00000000..bb99492a --- /dev/null +++ b/test/repositories/svn_with_branching/db/revprops/2 @@ -0,0 +1,13 @@ +K 10 +svn:author +V 5 +robin +K 8 +svn:date +V 27 +2009-02-05T13:33:19.430758Z +K 7 +svn:log +V 27 +Added helloworld.c to trunk +END diff --git a/test/repositories/svn_with_branching/db/revprops/3 b/test/repositories/svn_with_branching/db/revprops/3 new file mode 100644 index 00000000..ae29e169 --- /dev/null +++ b/test/repositories/svn_with_branching/db/revprops/3 @@ -0,0 +1,13 @@ +K 10 +svn:author +V 5 +robin +K 8 +svn:date +V 27 +2009-02-05T13:33:46.533428Z +K 7 +svn:log +V 30 +Accidentally deleted the trunk +END diff --git a/test/repositories/svn_with_branching/db/revprops/4 b/test/repositories/svn_with_branching/db/revprops/4 new file mode 100644 index 00000000..7dc8e421 --- /dev/null +++ b/test/repositories/svn_with_branching/db/revprops/4 @@ -0,0 +1,13 @@ +K 10 +svn:author +V 5 +robin +K 8 +svn:date +V 27 +2009-02-05T13:35:52.897202Z +K 7 +svn:log +V 35 +Resurrect the trunk from revision 2 +END diff --git a/test/repositories/svn_with_branching/db/revprops/5 b/test/repositories/svn_with_branching/db/revprops/5 new file mode 100644 index 00000000..6cc9c465 --- /dev/null +++ b/test/repositories/svn_with_branching/db/revprops/5 @@ -0,0 +1,13 @@ +K 10 +svn:author +V 5 +robin +K 8 +svn:date +V 27 +2009-02-05T13:38:28.466012Z +K 7 +svn:log +V 37 +add a new branch, with goodbyeworld.c +END diff --git a/test/repositories/svn_with_branching/db/revprops/6 b/test/repositories/svn_with_branching/db/revprops/6 new file mode 100644 index 00000000..b8f13722 --- /dev/null +++ b/test/repositories/svn_with_branching/db/revprops/6 @@ -0,0 +1,13 @@ +K 10 +svn:author +V 5 +robin +K 8 +svn:date +V 27 +2009-02-05T13:39:21.552787Z +K 7 +svn:log +V 33 +copy goodbye world onto the trunk +END diff --git a/test/repositories/svn_with_branching/db/revprops/7 b/test/repositories/svn_with_branching/db/revprops/7 new file mode 100644 index 00000000..98a0b5e7 --- /dev/null +++ b/test/repositories/svn_with_branching/db/revprops/7 @@ -0,0 +1,13 @@ +K 10 +svn:author +V 5 +robin +K 8 +svn:date +V 27 +2009-02-05T13:40:20.923103Z +K 7 +svn:log +V 16 +delete the trunk +END diff --git a/test/repositories/svn_with_branching/db/revprops/8 b/test/repositories/svn_with_branching/db/revprops/8 new file mode 100644 index 00000000..3cbd0693 --- /dev/null +++ b/test/repositories/svn_with_branching/db/revprops/8 @@ -0,0 +1,13 @@ +K 10 +svn:author +V 5 +robin +K 8 +svn:date +V 27 +2009-02-05T13:40:46.386190Z +K 7 +svn:log +V 32 +the branch becomes the new trunk +END diff --git a/test/repositories/svn_with_branching/db/revprops/9 b/test/repositories/svn_with_branching/db/revprops/9 new file mode 100644 index 00000000..717c1c09 --- /dev/null +++ b/test/repositories/svn_with_branching/db/revprops/9 @@ -0,0 +1,13 @@ +K 10 +svn:author +V 5 +robin +K 8 +svn:date +V 27 +2009-02-05T13:41:24.149619Z +K 7 +svn:log +V 21 +modified helloworld.c +END diff --git a/test/repositories/svn_with_branching/db/revs/0 b/test/repositories/svn_with_branching/db/revs/0 new file mode 100644 index 00000000..10f5c45f --- /dev/null +++ b/test/repositories/svn_with_branching/db/revs/0 @@ -0,0 +1,11 @@ +PLAIN +END +ENDREP +id: 0.0.r0/17 +type: dir +count: 0 +text: 0 0 4 4 2d2977d1c96f487abe4a1e202dd03b4e +cpath: / + + +17 107 diff --git a/test/repositories/svn_with_branching/db/revs/1 b/test/repositories/svn_with_branching/db/revs/1 new file mode 100644 index 00000000..c3e1e9eb --- /dev/null +++ b/test/repositories/svn_with_branching/db/revs/1 @@ -0,0 +1,49 @@ +id: 3.0.r1/0 +type: dir +count: 0 +cpath: /trunk +copyroot: 0 / + +id: 1.0.r1/61 +type: dir +count: 0 +cpath: /branches +copyroot: 0 / + +id: 2.0.r1/126 +type: dir +count: 0 +cpath: /tags +copyroot: 0 / + +PLAIN +K 8 +branches +V 13 +dir 1.0.r1/61 +K 4 +tags +V 14 +dir 2.0.r1/126 +K 5 +trunk +V 12 +dir 3.0.r1/0 +END +ENDREP +id: 0.0.r1/294 +type: dir +pred: 0.0.r0/17 +count: 1 +text: 1 188 93 93 ccb9bef85dcf6713091037d4ac8a1c33 +cpath: / +copyroot: 0 / + +_2.0.t0-1 add false false /trunk + +_0.0.t0-1 add false false /branches + +_1.0.t0-1 add false false /tags + + +294 419 diff --git a/test/repositories/svn_with_branching/db/revs/2 b/test/repositories/svn_with_branching/db/revs/2 new file mode 100644 index 0000000000000000000000000000000000000000..d7c8d17bbc00660fb22910ac8e10ca1f3d28a0ef GIT binary patch literal 681 zcmZ{hQES^U5XalS?LNh=dud^dbthS|-7zRM(6JKAR{As;vLr8No^2e3t(1MSeY(jG z$G!+4TwLE?z~{T=@zGK7;{5ne@w#qpvvD5Zt%Iw(+3G#~Fm-!+1`qJE zAL=$#rzcmwX}UM~vl|-s>Pvfab`HN`vAq1WxPjUgsAgg|aFR&~_q{K$sv8fs+q9uT z0m1)@C!@f*z%)Z4t(jZaEQl(_mdO&AWhRW$!etfM-h@?wNfUU?@*XnFEi>yKw5tc`2Oo8&h!U|=puGZ%3>A-6 zmfE^hs%)O-g1yYRG|pMAQ=260PRyGxJ8`FmV$xaa^oU5HK?{#I)n5SbIZz{?wEi@acQzE6L oDJh#<$vzk5UiYc#*Rg+~w}f##7=b-jrdj*{ZWkaDqKWY5sexVYXR-H_A`{_g$G-0 z%65h@wEkCk3WSlONMhtLqmrsLNsLUb&y;0=pN)bJP|{9uD0lq;lZSC(txMaDQ*S{i4tJ#e(AEA(rQN)5D!W>ch7KtS} zu#ka;Cj{}nG|AEodrgS<$}pTV#i`UbF&?K*%Kum<5n>dN(ls3NA7xL(-5?IFd03B4 z+9@Y7p)!OW)b~yVVhTIreGW&wc*m=T%RBP+Egn-ogcrWLzsyo;l<=-H8CbPYS;Dyt ztHCU!DZRy3CWFnZwWHaq0AI(zh9re$V0keY&sc0pB+5@WdH&!N(g~} DE>$Z8 literal 0 HcmV?d00001 diff --git a/test/repositories/svn_with_branching/db/revs/6 b/test/repositories/svn_with_branching/db/revs/6 new file mode 100644 index 00000000..3350b67b --- /dev/null +++ b/test/repositories/svn_with_branching/db/revs/6 @@ -0,0 +1,54 @@ +id: 5.3.r6/0 +type: file +pred: 5.2.r5/85 +count: 1 +text: 5 0 72 60 d032627b99a6bcef7d6061d4142e5257 +cpath: /trunk/goodbyeworld.c +copyfrom: 5 /branches/development/goodbyeworld.c + +PLAIN +K 14 +goodbyeworld.c +V 13 +file 5.3.r6/0 +K 12 +helloworld.c +V 14 +file 4.0.r2/83 +END +ENDREP +id: 3.1.r6/271 +type: dir +pred: 3.1.r4/0 +count: 3 +text: 6 177 81 81 2e2ef6d7c38eb0716e6983a582e3b7ae +cpath: /trunk +copyroot: 4 /trunk + +PLAIN +K 8 +branches +V 14 +dir 1.0.r5/545 +K 4 +tags +V 14 +dir 2.0.r1/126 +K 5 +trunk +V 14 +dir 3.1.r6/271 +END +ENDREP +id: 0.0.r6/514 +type: dir +pred: 0.0.r5/785 +count: 6 +text: 6 405 96 96 2809ce963ca9b8638c46c1ef54b172e2 +cpath: / +copyroot: 0 / + +5._0.t5-1 add false false /trunk/goodbyeworld.c +5 /branches/development/goodbyeworld.c + +514 640 diff --git a/test/repositories/svn_with_branching/db/revs/7 b/test/repositories/svn_with_branching/db/revs/7 new file mode 100644 index 00000000..194fae0c --- /dev/null +++ b/test/repositories/svn_with_branching/db/revs/7 @@ -0,0 +1,23 @@ +PLAIN +K 8 +branches +V 14 +dir 1.0.r5/545 +K 4 +tags +V 14 +dir 2.0.r1/126 +END +ENDREP +id: 0.0.r7/79 +type: dir +pred: 0.0.r6/514 +count: 7 +text: 7 0 66 66 2a73fc9e7df4b41d10d586d73b249c73 +cpath: / +copyroot: 0 / + +3.1.r6/271 delete false false /trunk + + +79 202 diff --git a/test/repositories/svn_with_branching/db/revs/8 b/test/repositories/svn_with_branching/db/revs/8 new file mode 100644 index 00000000..6a380351 --- /dev/null +++ b/test/repositories/svn_with_branching/db/revs/8 @@ -0,0 +1,35 @@ +id: 3.4.r8/0 +type: dir +pred: 3.2.r5/342 +count: 4 +text: 5 247 82 82 c485e5f340786ada064a13ca1c86ea5c +cpath: /trunk +copyfrom: 7 /branches/development + +PLAIN +K 8 +branches +V 14 +dir 1.0.r5/545 +K 4 +tags +V 14 +dir 2.0.r1/126 +K 5 +trunk +V 12 +dir 3.4.r8/0 +END +ENDREP +id: 0.0.r8/256 +type: dir +pred: 0.0.r7/79 +count: 8 +text: 8 149 94 94 a404e0a35955f83c7cf610ed21dc7e2b +cpath: / +copyroot: 0 / + +3._0.t7-1 add false false /trunk +7 /branches/development + +256 381 diff --git a/test/repositories/svn_with_branching/db/revs/9 b/test/repositories/svn_with_branching/db/revs/9 new file mode 100644 index 0000000000000000000000000000000000000000..10a052795877107c151a52d71c4b1b2e31308569 GIT binary patch literal 781 zcmaLVU2EGg6b9gZT1KeNrr*FQ45l7O(2oHaq9>-F9$wmsIb85WKGH zErw;#cI&lo2UwfBJw1aT@M6=~?NFYcT>7TzUgNi}Z`{i-?aA3&_zAQ5#i!X4YFA*I zq)D#{V;qM4#ur%DjfYL|$BZUDCrW_rcI{9ggTa3fPaP_1j=4saQp!_jwcuQq)_P{L z%qlKe?sAc>z;4V?6-b7D*M22cY%_LAY&dkY@4GIXrw%#5^6LD<96lmT;kN7CYVVKJ zH}PF8hce+wFNuDrf!<4+An!o~gN*4EIA?1PW>i!@eBSq*D93~E6E(2D?#hh|w zX_cbRGnHp~=E~eCD_2fXrp;sWf0YVWy=iUbw=nWT5oAfYbV+0yc_|F$b`tU!GQxNk z!cZ<=>hG-+*dJsX_h}-v`ine9ig1}7(fR?MDvdge%Tv#U){L1l71Rr@sCP=_mNAi= nQa_+4UWx=DeuhE4VYu#GUG6bd_E?%`>;L&r0ECX1^AvsoHNM%3 literal 0 HcmV?d00001 diff --git a/test/repositories/svn_with_branching/db/uuid b/test/repositories/svn_with_branching/db/uuid new file mode 100644 index 00000000..5a6a233a --- /dev/null +++ b/test/repositories/svn_with_branching/db/uuid @@ -0,0 +1 @@ +150330a3-0ae1-4e76-adb7-e1f1a37d4ad8 diff --git a/test/repositories/svn_with_branching/db/write-lock b/test/repositories/svn_with_branching/db/write-lock new file mode 100644 index 00000000..e69de29b diff --git a/test/repositories/svn_with_branching/format b/test/repositories/svn_with_branching/format new file mode 100644 index 00000000..7ed6ff82 --- /dev/null +++ b/test/repositories/svn_with_branching/format @@ -0,0 +1 @@ +5 diff --git a/test/repositories/svn_with_branching/hooks/post-commit.tmpl b/test/repositories/svn_with_branching/hooks/post-commit.tmpl new file mode 100644 index 00000000..b8345c6f --- /dev/null +++ b/test/repositories/svn_with_branching/hooks/post-commit.tmpl @@ -0,0 +1,51 @@ +#!/bin/sh + +# POST-COMMIT HOOK +# +# The post-commit hook is invoked after a commit. Subversion runs +# this hook by invoking a program (script, executable, binary, etc.) +# named 'post-commit' (for which this file is a template) with the +# following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] REV (the number of the revision just committed) +# +# The default working directory for the invocation is undefined, so +# the program should set one explicitly if it cares. +# +# Because the commit has already completed and cannot be undone, +# the exit code of the hook program is ignored. The hook program +# can use the 'svnlook' utility to help it examine the +# newly-committed tree. +# +# On a Unix system, the normal procedure is to have 'post-commit' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'post-commit' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'post-commit.bat' or 'post-commit.exe', +# but the basic idea is the same. +# +# The hook program typically does not inherit the environment of +# its parent process. For example, a common problem is for the +# PATH environment variable to not be set to its usual value, so +# that subprograms fail to launch unless invoked via absolute path. +# If you're having unexpected problems with a hook program, the +# culprit may be unusual (or missing) environment variables. +# +# Here is an example hook script, for a Unix /bin/sh interpreter. +# For more examples and pre-written hooks, see those in +# the Subversion repository at +# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and +# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/ + + +REPOS="$1" +REV="$2" + +commit-email.pl "$REPOS" "$REV" commit-watchers@example.org +log-commit.py --repository "$REPOS" --revision "$REV" diff --git a/test/repositories/svn_with_branching/hooks/post-lock.tmpl b/test/repositories/svn_with_branching/hooks/post-lock.tmpl new file mode 100644 index 00000000..c779f11d --- /dev/null +++ b/test/repositories/svn_with_branching/hooks/post-lock.tmpl @@ -0,0 +1,44 @@ +#!/bin/sh + +# POST-LOCK HOOK +# +# The post-lock hook is run after a path is locked. Subversion runs +# this hook by invoking a program (script, executable, binary, etc.) +# named 'post-lock' (for which this file is a template) with the +# following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] USER (the user who created the lock) +# +# The paths that were just locked are passed to the hook via STDIN (as +# of Subversion 1.2, only one path is passed per invocation, but the +# plan is to pass all locked paths at once, so the hook program +# should be written accordingly). +# +# The default working directory for the invocation is undefined, so +# the program should set one explicitly if it cares. +# +# Because the lock has already been created and cannot be undone, +# the exit code of the hook program is ignored. The hook program +# can use the 'svnlook' utility to help it examine the +# newly-created lock. +# +# On a Unix system, the normal procedure is to have 'post-lock' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'post-lock' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'post-lock.bat' or 'post-lock.exe', +# but the basic idea is the same. +# +# Here is an example hook script, for a Unix /bin/sh interpreter: + +REPOS="$1" +USER="$2" + +# Send email to interested parties, let them know a lock was created: +mailer.py lock "$REPOS" "$USER" /path/to/mailer.conf diff --git a/test/repositories/svn_with_branching/hooks/post-revprop-change.tmpl b/test/repositories/svn_with_branching/hooks/post-revprop-change.tmpl new file mode 100644 index 00000000..2ed8b9ab --- /dev/null +++ b/test/repositories/svn_with_branching/hooks/post-revprop-change.tmpl @@ -0,0 +1,56 @@ +#!/bin/sh + +# POST-REVPROP-CHANGE HOOK +# +# The post-revprop-change hook is invoked after a revision property +# has been added, modified or deleted. Subversion runs this hook by +# invoking a program (script, executable, binary, etc.) named +# 'post-revprop-change' (for which this file is a template), with the +# following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] REV (the revision that was tweaked) +# [3] USER (the username of the person tweaking the property) +# [4] PROPNAME (the property that was changed) +# [5] ACTION (the property was 'A'dded, 'M'odified, or 'D'eleted) +# +# [STDIN] PROPVAL ** the old property value is passed via STDIN. +# +# Because the propchange has already completed and cannot be undone, +# the exit code of the hook program is ignored. The hook program +# can use the 'svnlook' utility to help it examine the +# new property value. +# +# On a Unix system, the normal procedure is to have 'post-revprop-change' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'post-revprop-change' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'post-revprop-change.bat' or 'post-revprop-change.exe', +# but the basic idea is the same. +# +# The hook program typically does not inherit the environment of +# its parent process. For example, a common problem is for the +# PATH environment variable to not be set to its usual value, so +# that subprograms fail to launch unless invoked via absolute path. +# If you're having unexpected problems with a hook program, the +# culprit may be unusual (or missing) environment variables. +# +# Here is an example hook script, for a Unix /bin/sh interpreter. +# For more examples and pre-written hooks, see those in +# the Subversion repository at +# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and +# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/ + + +REPOS="$1" +REV="$2" +USER="$3" +PROPNAME="$4" +ACTION="$5" + +propchange-email.pl "$REPOS" "$REV" "$USER" "$PROPNAME" watchers@example.org diff --git a/test/repositories/svn_with_branching/hooks/post-unlock.tmpl b/test/repositories/svn_with_branching/hooks/post-unlock.tmpl new file mode 100644 index 00000000..ae95c4bd --- /dev/null +++ b/test/repositories/svn_with_branching/hooks/post-unlock.tmpl @@ -0,0 +1,42 @@ +#!/bin/sh + +# POST-UNLOCK HOOK +# +# The post-unlock hook runs after a path is unlocked. Subversion runs +# this hook by invoking a program (script, executable, binary, etc.) +# named 'post-unlock' (for which this file is a template) with the +# following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] USER (the user who destroyed the lock) +# +# The paths that were just unlocked are passed to the hook via STDIN +# (as of Subversion 1.2, only one path is passed per invocation, but +# the plan is to pass all unlocked paths at once, so the hook program +# should be written accordingly). +# +# The default working directory for the invocation is undefined, so +# the program should set one explicitly if it cares. +# +# Because the lock has already been destroyed and cannot be undone, +# the exit code of the hook program is ignored. +# +# On a Unix system, the normal procedure is to have 'post-unlock' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'post-unlock' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'post-unlock.bat' or 'post-unlock.exe', +# but the basic idea is the same. +# +# Here is an example hook script, for a Unix /bin/sh interpreter: + +REPOS="$1" +USER="$2" + +# Send email to interested parties, let them know a lock was removed: +mailer.py unlock "$REPOS" "$USER" /path/to/mailer.conf diff --git a/test/repositories/svn_with_branching/hooks/pre-commit.tmpl b/test/repositories/svn_with_branching/hooks/pre-commit.tmpl new file mode 100644 index 00000000..ffecfa88 --- /dev/null +++ b/test/repositories/svn_with_branching/hooks/pre-commit.tmpl @@ -0,0 +1,70 @@ +#!/bin/sh + +# PRE-COMMIT HOOK +# +# The pre-commit hook is invoked before a Subversion txn is +# committed. Subversion runs this hook by invoking a program +# (script, executable, binary, etc.) named 'pre-commit' (for which +# this file is a template), with the following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] TXN-NAME (the name of the txn about to be committed) +# +# The default working directory for the invocation is undefined, so +# the program should set one explicitly if it cares. +# +# If the hook program exits with success, the txn is committed; but +# if it exits with failure (non-zero), the txn is aborted, no commit +# takes place, and STDERR is returned to the client. The hook +# program can use the 'svnlook' utility to help it examine the txn. +# +# On a Unix system, the normal procedure is to have 'pre-commit' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# *** NOTE: THE HOOK PROGRAM MUST NOT MODIFY THE TXN, EXCEPT *** +# *** FOR REVISION PROPERTIES (like svn:log or svn:author). *** +# +# This is why we recommend using the read-only 'svnlook' utility. +# In the future, Subversion may enforce the rule that pre-commit +# hooks should not modify the versioned data in txns, or else come +# up with a mechanism to make it safe to do so (by informing the +# committing client of the changes). However, right now neither +# mechanism is implemented, so hook writers just have to be careful. +# +# Note that 'pre-commit' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'pre-commit.bat' or 'pre-commit.exe', +# but the basic idea is the same. +# +# The hook program typically does not inherit the environment of +# its parent process. For example, a common problem is for the +# PATH environment variable to not be set to its usual value, so +# that subprograms fail to launch unless invoked via absolute path. +# If you're having unexpected problems with a hook program, the +# culprit may be unusual (or missing) environment variables. +# +# Here is an example hook script, for a Unix /bin/sh interpreter. +# For more examples and pre-written hooks, see those in +# the Subversion repository at +# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and +# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/ + + +REPOS="$1" +TXN="$2" + +# Make sure that the log message contains some text. +SVNLOOK=/usr/local/bin/svnlook +$SVNLOOK log -t "$TXN" "$REPOS" | \ + grep "[a-zA-Z0-9]" > /dev/null || exit 1 + +# Check that the author of this commit has the rights to perform +# the commit on the files and directories being modified. +commit-access-control.pl "$REPOS" "$TXN" commit-access-control.cfg || exit 1 + +# All checks passed, so allow the commit. +exit 0 diff --git a/test/repositories/svn_with_branching/hooks/pre-lock.tmpl b/test/repositories/svn_with_branching/hooks/pre-lock.tmpl new file mode 100644 index 00000000..b0d67a92 --- /dev/null +++ b/test/repositories/svn_with_branching/hooks/pre-lock.tmpl @@ -0,0 +1,64 @@ +#!/bin/sh + +# PRE-LOCK HOOK +# +# The pre-lock hook is invoked before an exclusive lock is +# created. Subversion runs this hook by invoking a program +# (script, executable, binary, etc.) named 'pre-lock' (for which +# this file is a template), with the following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] PATH (the path in the repository about to be locked) +# [3] USER (the user creating the lock) +# +# The default working directory for the invocation is undefined, so +# the program should set one explicitly if it cares. +# +# If the hook program exits with success, the lock is created; but +# if it exits with failure (non-zero), the lock action is aborted +# and STDERR is returned to the client. + +# On a Unix system, the normal procedure is to have 'pre-lock' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'pre-lock' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'pre-lock.bat' or 'pre-lock.exe', +# but the basic idea is the same. +# +# Here is an example hook script, for a Unix /bin/sh interpreter: + +REPOS="$1" +PATH="$2" +USER="$3" + +# If a lock exists and is owned by a different person, don't allow it +# to be stolen (e.g., with 'svn lock --force ...'). + +# (Maybe this script could send email to the lock owner?) +SVNLOOK=/usr/local/bin/svnlook +GREP=/bin/grep +SED=/bin/sed + +LOCK_OWNER=`$SVNLOOK lock "$REPOS" "$PATH" | \ + $GREP '^Owner: ' | $SED 's/Owner: //'` + +# If we get no result from svnlook, there's no lock, allow the lock to +# happen: +if [ "$LOCK_OWNER" = "" ]; then + exit 0 +fi + +# If the person locking matches the lock's owner, allow the lock to +# happen: +if [ "$LOCK_OWNER" = "$USER" ]; then + exit 0 +fi + +# Otherwise, we've got an owner mismatch, so return failure: +echo "Error: $PATH already locked by ${LOCK_OWNER}." 1>&2 +exit 1 diff --git a/test/repositories/svn_with_branching/hooks/pre-revprop-change.tmpl b/test/repositories/svn_with_branching/hooks/pre-revprop-change.tmpl new file mode 100644 index 00000000..2f2de984 --- /dev/null +++ b/test/repositories/svn_with_branching/hooks/pre-revprop-change.tmpl @@ -0,0 +1,66 @@ +#!/bin/sh + +# PRE-REVPROP-CHANGE HOOK +# +# The pre-revprop-change hook is invoked before a revision property +# is added, modified or deleted. Subversion runs this hook by invoking +# a program (script, executable, binary, etc.) named 'pre-revprop-change' +# (for which this file is a template), with the following ordered +# arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] REVISION (the revision being tweaked) +# [3] USER (the username of the person tweaking the property) +# [4] PROPNAME (the property being set on the revision) +# [5] ACTION (the property is being 'A'dded, 'M'odified, or 'D'eleted) +# +# [STDIN] PROPVAL ** the new property value is passed via STDIN. +# +# If the hook program exits with success, the propchange happens; but +# if it exits with failure (non-zero), the propchange doesn't happen. +# The hook program can use the 'svnlook' utility to examine the +# existing value of the revision property. +# +# WARNING: unlike other hooks, this hook MUST exist for revision +# properties to be changed. If the hook does not exist, Subversion +# will behave as if the hook were present, but failed. The reason +# for this is that revision properties are UNVERSIONED, meaning that +# a successful propchange is destructive; the old value is gone +# forever. We recommend the hook back up the old value somewhere. +# +# On a Unix system, the normal procedure is to have 'pre-revprop-change' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'pre-revprop-change' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'pre-revprop-change.bat' or 'pre-revprop-change.exe', +# but the basic idea is the same. +# +# The hook program typically does not inherit the environment of +# its parent process. For example, a common problem is for the +# PATH environment variable to not be set to its usual value, so +# that subprograms fail to launch unless invoked via absolute path. +# If you're having unexpected problems with a hook program, the +# culprit may be unusual (or missing) environment variables. +# +# Here is an example hook script, for a Unix /bin/sh interpreter. +# For more examples and pre-written hooks, see those in +# the Subversion repository at +# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and +# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/ + + +REPOS="$1" +REV="$2" +USER="$3" +PROPNAME="$4" +ACTION="$5" + +if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:log" ]; then exit 0; fi + +echo "Changing revision properties other than svn:log is prohibited" >&2 +exit 1 diff --git a/test/repositories/svn_with_branching/hooks/pre-unlock.tmpl b/test/repositories/svn_with_branching/hooks/pre-unlock.tmpl new file mode 100644 index 00000000..24c7f440 --- /dev/null +++ b/test/repositories/svn_with_branching/hooks/pre-unlock.tmpl @@ -0,0 +1,60 @@ +#!/bin/sh + +# PRE-UNLOCK HOOK +# +# The pre-unlock hook is invoked before an exclusive lock is +# destroyed. Subversion runs this hook by invoking a program +# (script, executable, binary, etc.) named 'pre-unlock' (for which +# this file is a template), with the following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] PATH (the path in the repository about to be unlocked) +# [3] USER (the user destroying the lock) +# +# The default working directory for the invocation is undefined, so +# the program should set one explicitly if it cares. +# +# If the hook program exits with success, the lock is destroyed; but +# if it exits with failure (non-zero), the unlock action is aborted +# and STDERR is returned to the client. + +# On a Unix system, the normal procedure is to have 'pre-unlock' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'pre-unlock' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'pre-unlock.bat' or 'pre-unlock.exe', +# but the basic idea is the same. +# +# Here is an example hook script, for a Unix /bin/sh interpreter: + +REPOS="$1" +PATH="$2" +USER="$3" + +# If a lock is owned by a different person, don't allow it be broken. +# (Maybe this script could send email to the lock owner?) + +SVNLOOK=/usr/local/bin/svnlook +GREP=/bin/grep +SED=/bin/sed + +LOCK_OWNER=`$SVNLOOK lock "$REPOS" "$PATH" | \ + $GREP '^Owner: ' | $SED 's/Owner: //'` + +# If we get no result from svnlook, there's no lock, return success: +if [ "$LOCK_OWNER" = "" ]; then + exit 0 +fi +# If the person unlocking matches the lock's owner, return success: +if [ "$LOCK_OWNER" = "$USER" ]; then + exit 0 +fi + +# Otherwise, we've got an owner mismatch, so return failure: +echo "Error: $PATH locked by ${LOCK_OWNER}." 1>&2 +exit 1 diff --git a/test/repositories/svn_with_branching/hooks/start-commit.tmpl b/test/repositories/svn_with_branching/hooks/start-commit.tmpl new file mode 100644 index 00000000..348d7063 --- /dev/null +++ b/test/repositories/svn_with_branching/hooks/start-commit.tmpl @@ -0,0 +1,54 @@ +#!/bin/sh + +# START-COMMIT HOOK +# +# The start-commit hook is invoked before a Subversion txn is created +# in the process of doing a commit. Subversion runs this hook +# by invoking a program (script, executable, binary, etc.) named +# 'start-commit' (for which this file is a template) +# with the following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] USER (the authenticated user attempting to commit) +# +# The default working directory for the invocation is undefined, so +# the program should set one explicitly if it cares. +# +# If the hook program exits with success, the commit continues; but +# if it exits with failure (non-zero), the commit is stopped before +# a Subversion txn is created, and STDERR is returned to the client. +# +# On a Unix system, the normal procedure is to have 'start-commit' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'start-commit' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'start-commit.bat' or 'start-commit.exe', +# but the basic idea is the same. +# +# The hook program typically does not inherit the environment of +# its parent process. For example, a common problem is for the +# PATH environment variable to not be set to its usual value, so +# that subprograms fail to launch unless invoked via absolute path. +# If you're having unexpected problems with a hook program, the +# culprit may be unusual (or missing) environment variables. +# +# Here is an example hook script, for a Unix /bin/sh interpreter. +# For more examples and pre-written hooks, see those in +# the Subversion repository at +# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and +# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/ + + +REPOS="$1" +USER="$2" + +commit-allower.pl --repository "$REPOS" --user "$USER" || exit 1 +special-auth-check.py --user "$USER" --auth-level 3 || exit 1 + +# All checks passed, so allow the commit. +exit 0 diff --git a/test/repositories/svn_with_branching/locks/db-logs.lock b/test/repositories/svn_with_branching/locks/db-logs.lock new file mode 100644 index 00000000..20dd6369 --- /dev/null +++ b/test/repositories/svn_with_branching/locks/db-logs.lock @@ -0,0 +1,3 @@ +This file is not used by Subversion 1.3.x or later. +However, its existence is required for compatibility with +Subversion 1.2.x or earlier. diff --git a/test/repositories/svn_with_branching/locks/db.lock b/test/repositories/svn_with_branching/locks/db.lock new file mode 100644 index 00000000..20dd6369 --- /dev/null +++ b/test/repositories/svn_with_branching/locks/db.lock @@ -0,0 +1,3 @@ +This file is not used by Subversion 1.3.x or later. +However, its existence is required for compatibility with +Subversion 1.2.x or earlier. diff --git a/test/test_helper.rb b/test/test_helper.rb index 9cc3e5aa..4a02329c 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -47,7 +47,7 @@ def assert_buffers_equal(expected, actual) assert_equal expected_lines, actual_lines end - def with_repository(type, name, block) + def with_repository(type, name) Scm::ScratchDir.new do |dir| if Dir.entries(REPO_DIR).include?(name) `cp -R #{File.join(REPO_DIR, name)} #{dir}` @@ -56,27 +56,30 @@ def with_repository(type, name, block) else raise RuntimeError.new("Repository archive #{File.join(REPO_DIR, name)} not found.") end - block.call(type.new(:url => File.join(dir, name)).normalize) + yield type.new(:url => File.join(dir, name)).normalize end end - def with_svn_repository(name, &block) - with_repository(Scm::Adapters::SvnAdapter, name, block) + def with_svn_repository(name, branch_name='') + with_repository(Scm::Adapters::SvnAdapter, name) do |svn| + svn.branch_name = branch_name + yield svn + end end - def with_cvs_repository(name, &block) - with_repository(Scm::Adapters::CvsAdapter, name, block) + def with_cvs_repository(name) + with_repository(Scm::Adapters::CvsAdapter, name) { |cvs| yield cvs } end - def with_git_repository(name, &block) - with_repository(Scm::Adapters::GitAdapter, name, block) + def with_git_repository(name) + with_repository(Scm::Adapters::GitAdapter, name) { |git| yield git } end - def with_hg_repository(name, &block) - with_repository(Scm::Adapters::HgAdapter, name, block) + def with_hg_repository(name) + with_repository(Scm::Adapters::HgAdapter, name) { |hg| yield hg } end - def with_bzr_repository(name, &block) - with_repository(Scm::Adapters::BzrAdapter, name, block) + def with_bzr_repository(name) + with_repository(Scm::Adapters::BzrAdapter, name) { |bzr| yield bzr } end end diff --git a/test/unit/svn_chain_test.rb b/test/unit/svn_chain_test.rb new file mode 100644 index 00000000..db9de7d7 --- /dev/null +++ b/test/unit/svn_chain_test.rb @@ -0,0 +1,21 @@ +require File.dirname(__FILE__) + '/../test_helper' + +module Scm::Parsers + class SvnChainTest < Scm::Test + + def test_basic + with_svn_repository('svn_with_branching', '/trunk') do |svn| + # In this repository, /branches/development becomes + # the /trunk in revision 8. So there should be no record + # before revision 8 in the 'traditional' commit parser. + assert_equal [8,9], svn.commit_tokens + + p = svn.parent_svn + assert_equal p.url, svn.url + assert_equal p.branch_name, '/branches/development' + assert_equal p.final_revision, 7 + end + end + + end +end diff --git a/test/unit/svn_commits_test.rb b/test/unit/svn_commits_test.rb index ef90191f..52a2b208 100644 --- a/test/unit/svn_commits_test.rb +++ b/test/unit/svn_commits_test.rb @@ -244,5 +244,22 @@ def test_each_commit assert_equal '/trunk/COPYING', commits[4].diffs[1].path end + def test_final_revision + with_svn_repository('svn') do |svn| + assert_equal 5, svn.commit_count + assert_equal [1,2,3,4,5], svn.commit_tokens + + svn.final_revision = 3 + assert_equal 3, svn.commit_count + assert_equal [1,2,3], svn.commit_tokens + + assert_equal 1, svn.commit_count(2) + assert_equal [3], svn.commit_tokens(2) + + assert_equal 0, svn.commit_count(4) + assert_equal [], svn.commit_tokens(4) + end + end + end end From e65fb1e4d24d2f154f8a93e493e288ee38602b82 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Thu, 5 Feb 2009 12:33:59 -0800 Subject: [PATCH 003/219] [NEW] Subversion adapter can now follow trunk directory renames. --- lib/scm/adapters/abstract_adapter.rb | 6 +- lib/scm/adapters/svn/chain.rb | 61 +++++++++-- lib/scm/adapters/svn/commits.rb | 99 ++++++++++------- lib/scm/adapters/svn/misc.rb | 12 +-- test/test_helper.rb | 2 + test/unit/svn_chain_test.rb | 156 +++++++++++++++++++++++++-- test/unit/svn_commits_test.rb | 98 ++++++++--------- 7 files changed, 315 insertions(+), 119 deletions(-) diff --git a/lib/scm/adapters/abstract_adapter.rb b/lib/scm/adapters/abstract_adapter.rb index aa906716..4fe9f171 100644 --- a/lib/scm/adapters/abstract_adapter.rb +++ b/lib/scm/adapters/abstract_adapter.rb @@ -3,11 +3,7 @@ class AbstractAdapter attr_accessor :url, :branch_name, :username, :password, :errors, :public_urls_only def initialize(params={}) - @url = params[:url] - @branch_name = params[:branch_name] - @username = params[:username] - @password = params[:password] - @public_urls_only = params[:public_urls_only] + params.each { |k,v| send(k.to_s + '=', v) if respond_to?(k.to_s + '=') } end # Handy for test overrides diff --git a/lib/scm/adapters/svn/chain.rb b/lib/scm/adapters/svn/chain.rb index 00957f62..cafeb322 100644 --- a/lib/scm/adapters/svn/chain.rb +++ b/lib/scm/adapters/svn/chain.rb @@ -1,25 +1,66 @@ module Scm::Adapters class SvnAdapter < AbstractAdapter - def first_revision(since=0) - commit_tokens(since).first + def first_token(since=0) + first_commit(since).token end def first_commit(since=0) - verbose_commit(first_revision) + Scm::Parsers::SvnXmlParser.parse(next_revision_xml(since)).first end + # Returns the first commit with a revision number greater than the provided revision number + def next_revision_xml(since) + run "svn log --verbose --xml --stop-on-copy -r #{since+1}:#{final_token || 'HEAD'} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}'" + end + def parent_svn(since=0) + parent = nil c = first_commit(since) - if c && c.diffs.size == 1 - d = c.diffs.first - if d.action == 'A' && d.path == branch_name && d.from_path && d.from_revision - prior_svn = self.clone - prior_svn.branch_name = d.from_path - prior_svn.final_revision = d.from_revision - prior_svn + if c + c.diffs.each do |d| + if d.action == 'A' && d.path == branch_name && d.from_path && d.from_revision + parent = SvnAdapter.new(:url => File.join(root, d.from_path), + :username => username, :password => password, + :branch_name => d.from_path, :final_token => d.from_revision).normalize + break + end end end + parent + end + + # Returns the parent_svn ancestry as a list, oldest first + def chain + (parent_svn ? parent_svn.chain : []) << self + end + + #------------------------------------------------------------------ + # Recursive or "chained" versions of the commit accessors. + # + # These methods recurse through the chain of ancestors for this + # adapter, calling the base_* method in turn for each ancestor. + #------------------------------------------------------------------ + + # Returns the count of commits following revision number 'since'. + def chained_commit_count(since=0) + (parent_svn ? parent_svn.chained_commit_count(since) : 0) + base_commit_count(since) + end + + # Returns an array of revision numbers for all commits following revision number 'since'. + def chained_commit_tokens(since=0) + (parent_svn ? parent_svn.chained_commit_tokens(since) : []) + base_commit_tokens(since) + end + + def chained_commits(since=0) + (parent_svn ? parent_svn.chained_commits(since) : []) + base_commits(since) + end + + def chained_each_commit(since=0, &block) + parent_svn.chained_each_commit(since, &block) if parent_svn + base_each_commit(since) do |commit| + block.call commit + end end end diff --git a/lib/scm/adapters/svn/commits.rb b/lib/scm/adapters/svn/commits.rb index 87e7af9f..345118bb 100644 --- a/lib/scm/adapters/svn/commits.rb +++ b/lib/scm/adapters/svn/commits.rb @@ -3,11 +3,6 @@ module Scm::Adapters class SvnAdapter < AbstractAdapter - # The last revision to be analyzed in this repository. Everything after this revision is ignored. - # The repository is considered to be retired after this point, and under no circumstances should - # this adapter ever return information regarding commits after this point. - attr_accessor :final_revision - # In all commit- and log-related methods, 'since' refers to the revision number of the last known commit, # and the methods return the commits *following* this commit. # @@ -17,39 +12,57 @@ class SvnAdapter < AbstractAdapter # # This is convenient for Ohloh -- Ohloh passes the last commit it is aware of, and these methods return any new commits. - # Returns the count of commits following revision number 'since'. + # The last revision to be analyzed in this repository. Everything after this revision is ignored. + # The repository is considered to be retired after this point, and under no circumstances should + # this adapter ever return information regarding commits after this point. + attr_accessor :final_token + + #------------------------------------------------------------------ + # Commit accessors are now redirected to recursive "chained" versions + #------------------------------------------------------------------ + def commit_count(since=0) - return 0 if final_revision && since > final_revision - run("svn log -q -r #{since.to_i + 1}:#{final_revision || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}' | grep -E -e '^r[0-9]+ ' | wc -l").strip.to_i + chained_commit_count(since) end - # Returns an array of revision numbers for all commits following revision number 'since'. def commit_tokens(since=0) - return [] if final_revision && since > final_revision - cmd = "svn log -q -r #{since.to_i + 1}:#{final_revision || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}' | grep -E -e '^r[0-9]+ ' | cut -f 1 -d '|' | cut -c 2-" + chained_commit_tokens(since) + end + + def commits(since=0) + chained_commits(since) + end + + def each_commit(since=0) + chained_each_commit(since) { |commit| yield commit } + end + + #------------------------------------------------------------------ + # Base versions of the commit accessors. + # + # These are the original, simple commit accessors that are + # unaware of branch "chaining". + #------------------------------------------------------------------ + + # Returns the count of commits following revision number 'since'. + def base_commit_count(since=0) + return 0 if final_token && since >= final_token + run("svn log -q -r #{since.to_i + 1}:#{final_token || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{final_token || 'HEAD'}' | grep -E -e '^r[0-9]+ ' | wc -l").strip.to_i + end + + # Returns an array of revision numbers for all commits following revision number 'since'. + def base_commit_tokens(since=0) + return [] if final_token && since >= final_token + cmd = "svn log -q -r #{since.to_i + 1}:#{final_token || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{final_token || 'HEAD'}' | grep -E -e '^r[0-9]+ ' | cut -f 1 -d '|' | cut -c 2-" run(cmd).split.collect { |r| r.to_i } end # Returns an array of commits following revision number 'since'. These commit objects do not include diffs. - def commits(since=0) + def base_commits(since=0) c = [] open_log_file(since) do |io| c = Scm::Parsers::SvnXmlParser.parse(io) end - - # We may be using a log saved on disk from a previous fetch. - # If so, exclude the portion of the log up to 'since'. - c.each_index do |i| - if c[i].token.to_i == since.to_i - if i == commits.size-1 - # We're up to date - return [] - else - return c[i+1..-1] - end - end - end - c end # Yields each commit following revision number 'since'. These commit object are populated with diffs. @@ -60,8 +73,8 @@ def commits(since=0) # directories, the complexity (and time) of this method comes in expanding directories with a recursion # through every file in the directory. # - def each_commit(since=nil) - commit_tokens(since).each do |rev| + def base_each_commit(since=nil) + base_commit_tokens(since).each do |rev| yield deepen_commit(strip_commit_branch(verbose_commit(rev))) end end @@ -73,7 +86,7 @@ def deepen_commit(commit) if commit.diffs deep_commit.diffs = commit.diffs.collect do |diff| deepen_diff(diff, commit.token) - end.flatten.uniq.sort { |a,b| a.action <=> b.action }.sort { |a,b| a.path <=> b.path } + end.compact.flatten.uniq.sort { |a,b| a.action <=> b.action }.sort { |a,b| a.path <=> b.path } end remove_dupes(deep_commit) @@ -86,10 +99,10 @@ def remove_dupes(commit) # Because we expand directories, the result is that the file may be listed twice -- once as part of our expansion, # and once from the regular log entry. # - # So look for diffs of the form ["M", "path"] which are matched by ["A", "path"] and remove them. + # So look for diffs of the form ["M", "path"] which are matched by ["A", "path"], and keep only the "A" diff. if commit.diffs commit.diffs.delete_if do |d| - d.action =~ /[MR]/ && commit.diffs.select { |x| x.action == 'A' and x.path == d.path }.any? + d && d.action =~ /[MR]/ && commit.diffs.select { |x| x.action == 'A' and x.path == d.path }.any? end end commit @@ -100,11 +113,19 @@ def remove_dupes(commit) def deepen_diff(diff, rev) # Note that if the directory was deleted, we have to look at the previous revision to see what it held. recurse_rev = (diff.action == 'D') ? rev-1 : rev - if (diff.action == 'D' or diff.action == 'A') && is_directory?(diff.path, recurse_rev) + + if diff.action == 'A' && diff.path == '' && rev == first_token && parent_svn + # A very special case. This is the first commit, and the entire tree is being + # copied from somewhere else. In this case, there isn't actually any change, just + # a change of branch_name. Return no diffs at all. + nil + elsif (diff.action == 'D' or diff.action == 'A') && is_directory?(diff.path, recurse_rev) + # Deleting or adding a directory. Expand it out to show every file. recurse_files(diff.path, recurse_rev).collect do |f| Scm::Diff.new(:action => diff.action, :path => File.join(diff.path, f)) end else + # An ordinary file action. Just return the diff. diff end end @@ -148,16 +169,17 @@ def verbose_commit(rev) #--------------------------------------------------------------------- def log(since=0) - run "svn log --xml --stop-on-copy -r #{since.to_i + 1}:#{final_revision || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name.to_s))}' #{opt_auth}" + run "svn log --xml --stop-on-copy -r #{since.to_i + 1}:#{final_token || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name.to_s))}' #{opt_auth}" end def open_log_file(since=0) + since ||= 0 begin - if (since.to_i + 1) <= head_token - run "svn log --xml --stop-on-copy -r #{since.to_i + 1}:#{final_revision || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}' #{opt_auth} > #{log_filename}" - else + if (final_token && since >= final_token) || since >= head_token # As a time optimization, just create an empty file rather than fetch a log we know will be empty. File.open(log_filename, 'w') { |f| f.puts '' } + else + run "svn log --xml --stop-on-copy -r #{since.to_i + 1}:#{final_token || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}' #{opt_auth} > #{log_filename}" end File.open(log_filename, 'r') { |io| yield io } ensure @@ -169,8 +191,9 @@ def log_filename File.join('/tmp', (self.url).gsub(/\W/,'') + '.log') end + # Returns one commit with the exact revision number provided def single_revision_xml(revision) - run "svn log --verbose --xml --stop-on-copy -r #{revision} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(self.url)}@#{revision}'" + run "svn log --verbose --xml --stop-on-copy -r #{revision} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{revision}'" end # Recurses the entire repository and returns an array of file names. @@ -178,7 +201,7 @@ def single_revision_xml(revision) # Directories named 'CVSROOT' are always ignored and the files they contain are never returned. # An empty array means that the call succeeded, but the remote directory is empty. # A nil result means that the call failed and the remote server could not be queried. - def recurse_files(path=nil, revision=final_revision || 'HEAD') + def recurse_files(path=nil, revision=final_token || 'HEAD') begin stdout = run "svn ls -r #{revision} --recursive #{opt_auth} '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s, path.to_s))}@#{revision}'" rescue diff --git a/lib/scm/adapters/svn/misc.rb b/lib/scm/adapters/svn/misc.rb index 307cfaea..b1ec20b2 100644 --- a/lib/scm/adapters/svn/misc.rb +++ b/lib/scm/adapters/svn/misc.rb @@ -57,9 +57,9 @@ def exist? end end - def info(path=nil, revision='HEAD') + def info(path=nil, revision=final_token || 'HEAD') if path || (revision != 'HEAD') - run "svn info -r #{revision} #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name.to_s, path.to_s))}@#{revision}'" + run "svn info -r #{revision} #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.url, path.to_s))}@#{revision}'" else # Cache the default info query for performance @info ||= run "svn info -r #{revision} #{opt_auth} '#{SvnAdapter.uri_encode(self.url)}@#{revision}'" @@ -79,7 +79,7 @@ def uuid # Directories named 'CVSROOT' are always ignored and never returned. # An empty array means that the call succeeded, but the remote directory is empty. # A nil result means that the call failed and the remote server could not be queried. - def ls(path=nil, revision='HEAD') + def ls(path=nil, revision=final_token || 'HEAD') begin stdout = run "svn ls -r #{revision} #{opt_auth} '#{SvnAdapter.uri_encode(File.join(url, path.to_s))}@#{revision}'" rescue @@ -94,11 +94,11 @@ def ls(path=nil, revision='HEAD') files.sort end - def node_kind(path=nil, revision='HEAD') + def node_kind(path=nil, revision=final_token || 'HEAD') $1 if self.info(path, revision) =~ /^Node Kind: (.+)$/ end - def is_directory?(path=nil, revision='HEAD') + def is_directory?(path=nil, revision=final_token || 'HEAD') begin return node_kind(path, revision) == 'directory' rescue @@ -115,7 +115,7 @@ def checkout(rev, dest_dir) run "svn checkout -r #{rev.token} '#{SvnAdapter.uri_encode(self.url)}@#{rev.token}' '#{dest_dir}' --ignore-externals #{opt_auth}" end - def export(dest_dir, commit_id = 'HEAD') + def export(dest_dir, commit_id = final_token || 'HEAD') FileUtils.mkdir_p(File.dirname(dest_dir)) unless FileTest.exist?(File.dirname(dest_dir)) run "svn export --force -r #{commit_id} '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}' '#{dest_dir}'" end diff --git a/test/test_helper.rb b/test/test_helper.rb index 4a02329c..c84fa243 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -63,6 +63,8 @@ def with_repository(type, name) def with_svn_repository(name, branch_name='') with_repository(Scm::Adapters::SvnAdapter, name) do |svn| svn.branch_name = branch_name + svn.url = File.join(svn.root, svn.branch_name) + svn.url = svn.url[0..-2] if svn.url[-1..-1] == '/' # Strip trailing / yield svn end end diff --git a/test/unit/svn_chain_test.rb b/test/unit/svn_chain_test.rb index db9de7d7..b43d5b37 100644 --- a/test/unit/svn_chain_test.rb +++ b/test/unit/svn_chain_test.rb @@ -3,19 +3,161 @@ module Scm::Parsers class SvnChainTest < Scm::Test - def test_basic + def test_chain + with_svn_repository('svn_with_branching', '/trunk') do |svn| + chain = svn.chain + assert_equal 4, chain.size + + # In revision 1, the trunk is created. + assert_equal '/trunk', chain[0].branch_name + assert_equal 1, chain[0].first_token + assert_equal 2, chain[0].final_token + + # In revision 3, the trunk was deleted, but restored in revision 4. + # This creates the first discontinuity, and the first link in the chain. + assert_equal '/trunk', chain[1].branch_name + assert_equal 4, chain[1].first_token + assert_equal 4, chain[1].final_token + + # In revision 5, the branch is created by copying the trunk from revision 4. + assert_equal '/branches/development', chain[2].branch_name + assert_equal 5, chain[2].first_token + assert_equal 7, chain[2].final_token + + # In revision 8, a new trunk is created by copying the branch. + # This trunk still lives on, so its final_token is nil. + assert_equal '/trunk', chain[3].branch_name + assert_equal 8, chain[3].first_token + assert_equal nil, chain[3].final_token + end + end + + def test_parent_svn with_svn_repository('svn_with_branching', '/trunk') do |svn| # In this repository, /branches/development becomes # the /trunk in revision 8. So there should be no record - # before revision 8 in the 'traditional' commit parser. - assert_equal [8,9], svn.commit_tokens + # before revision 8 in the 'traditional' base commit parser. + assert_equal [8,9], svn.base_commit_tokens + + p1 = svn.parent_svn + assert_equal p1.url, svn.root + '/branches/development' + assert_equal p1.branch_name, '/branches/development' + assert_equal p1.final_token, 7 - p = svn.parent_svn - assert_equal p.url, svn.url - assert_equal p.branch_name, '/branches/development' - assert_equal p.final_revision, 7 + # There's another move at revision 5, in which /branch/development + # is created by copying /trunk from revision 4. + p2 = p1.parent_svn + assert_equal p2.url, svn.root + '/trunk' + assert_equal p2.branch_name, '/trunk' + assert_equal p2.final_token, 4 end end + def test_chained_commit_tokens + with_svn_repository('svn_with_branching', '/trunk') do |svn| + assert_equal [1,2,4,5,8,9], svn.chained_commit_tokens + assert_equal [2,4,5,8,9], svn.chained_commit_tokens(1) + assert_equal [4,5,8,9], svn.chained_commit_tokens(2) + assert_equal [4,5,8,9], svn.chained_commit_tokens(3) + assert_equal [5,8,9], svn.chained_commit_tokens(4) + assert_equal [8,9], svn.chained_commit_tokens(5) + assert_equal [8,9], svn.chained_commit_tokens(6) + assert_equal [8,9], svn.chained_commit_tokens(7) + assert_equal [9], svn.chained_commit_tokens(8) + assert_equal [], svn.chained_commit_tokens(9) + assert_equal [], svn.chained_commit_tokens(10) + end + end + + def test_chained_commit_count + with_svn_repository('svn_with_branching', '/trunk') do |svn| + assert_equal 6, svn.chained_commit_count + assert_equal 5, svn.chained_commit_count(1) + assert_equal 4, svn.chained_commit_count(2) + assert_equal 4, svn.chained_commit_count(3) + assert_equal 3, svn.chained_commit_count(4) + assert_equal 2, svn.chained_commit_count(5) + assert_equal 2, svn.chained_commit_count(6) + assert_equal 2, svn.chained_commit_count(7) + assert_equal 1, svn.chained_commit_count(8) + assert_equal 0, svn.chained_commit_count(9) + end + end + + def test_chained_commits + with_svn_repository('svn_with_branching', '/trunk') do |svn| + assert_equal [1,2,4,5,8,9], svn.chained_commits.collect { |c| c.token } + assert_equal [2,4,5,8,9], svn.chained_commits(1).collect { |c| c.token } + assert_equal [4,5,8,9], svn.chained_commits(2).collect { |c| c.token } + assert_equal [4,5,8,9], svn.chained_commits(3).collect { |c| c.token } + assert_equal [5,8,9], svn.chained_commits(4).collect { |c| c.token } + assert_equal [8,9], svn.chained_commits(5).collect { |c| c.token } + assert_equal [8,9], svn.chained_commits(6).collect { |c| c.token } + assert_equal [8,9], svn.chained_commits(7).collect { |c| c.token } + assert_equal [9], svn.chained_commits(8).collect { |c| c.token } + assert_equal [], svn.chained_commits(9).collect { |c| c.token } + end + end + + # This test is primarly concerned with the checking the diffs + # of commits. Specifically, when an entire branch is moved + # to a new name, we should not see any diffs. From our + # point of view the code is unchanged; only the base directory + # has moved. + def test_chained_each_commit + commits = [] + with_svn_repository('svn_with_branching', '/trunk') do |svn| + svn.chained_each_commit do |c| + commits << c + # puts "r#{c.token} #{c.message}" + c.diffs.each do |d| + # puts "\t#{d.action} #{d.path}" + end + end + end + + assert_equal [1,2,4,5,8,9], commits.collect { |c| c.token } + + # This repository spends a lot of energy moving directories around. + # File edits actually occur in just 3 commits. + + # Revision 1: /trunk directory created, but it is empty + assert_equal 0, commits[0].diffs.size + + # Revision 2: /trunk/helloworld.c is added + assert_equal 1, commits[1].diffs.size + assert_equal 'A', commits[1].diffs.first.action + assert_equal '/helloworld.c', commits[1].diffs.first.path + + # Revision 3: /trunk is deleted. We can't see this revision. + + # Revision 4: /trunk is re-created by copying it from revision 2. + # From our point of view, there has been no change at all, and thus no diffs. + assert_equal 0, commits[2].diffs.size + + # Revision 5: /branches/development is created by copying /trunk. + # From our point of view, the contents of the repository are unchanged, so + # no diffs result from the copy. + # However, /branches/development/goodbyeworld.c is also created, so we should + # have a diff for that. + assert_equal 1, commits[3].diffs.size + assert_equal 'A', commits[3].diffs.first.action + assert_equal '/goodbyeworld.c', commits[3].diffs.first.path + + # Revision 6: /trunk/goodbyeworld.c is created, but we only see activity + # on /branches/development, so no commit reported. + + # Revision 7: /trunk is deleted, but again we don't see it. + + # Revision 8: /branches/development is moved to become the new /trunk. + # The directory contents are unchanged, so no diffs result. + assert_equal 0, commits[4].diffs.size + + # Revision 9: an edit to /trunk/helloworld.c + assert_equal 1, commits[5].diffs.size + assert_equal 'M', commits[5].diffs.first.action + assert_equal '/helloworld.c', commits[5].diffs.first.path + end + end end diff --git a/test/unit/svn_commits_test.rb b/test/unit/svn_commits_test.rb index 52a2b208..54dc0861 100644 --- a/test/unit/svn_commits_test.rb +++ b/test/unit/svn_commits_test.rb @@ -121,19 +121,40 @@ def test_deep_commits # The full repository contains 4 revisions... assert_equal 4, svn.commit_count - # ...however, the current trunk contains only revisions 3 and 4. - # That's because the branch was moved to replace the trunk at revision 3. + # ..however, looking only at the history of /trunk@4 shows 3 revisions. + # + # That's because /trunk@3 was created by copying /branches/b@1 # - # Even though there was a different trunk directory present in - # revisions 1 and 2, it is not visible to Ohloh. + # I hope the following diagram helps to explain: + # + # r1 | r2 | r3 | r4 + # ----------------|----------------|---------------------|--------------- + # | | | + # /trunk(x) ------|-> deleted(x) | /--> /trunk(*) --|--> /trunk(*) + # | | / | + # /branches/b(*)--|----------------|--/ | + # | | | + # + # (*) activity we track + # (x) activity we ignore trunk = SvnAdapter.new(:url => File.join(svn.url,'trunk'), :branch_name => '/trunk').normalize - assert_equal 2, trunk.commit_count - assert_equal [3,4], trunk.commit_tokens + assert_equal 3, trunk.commit_count + assert_equal [1,3,4], trunk.commit_tokens + + commits = [] + trunk.each_commit { |c| commits << c } + # The first commit we should see is /branches/b@1. + # It should contain two files. - deep_commits = [] - trunk.each_commit { |c| deep_commits << c } + assert_equal 1, commits.first.token + assert_equal 2, commits.first.diffs.size # Two files seen + + assert_equal 'A', commits.first.diffs[0].action + assert_equal '/subdir/bar.rb', commits.first.diffs[0].path + assert_equal 'A', commits.first.diffs[1].action + assert_equal '/subdir/foo.rb', commits.first.diffs[1].path # When the branch is moved to replace the trunk in revision 3, # the Subversion log shows @@ -141,46 +162,34 @@ def test_deep_commits # D /branches/b # A /trunk (from /branches/b:2) # - # However, there are files in those directories. Make sure the commits - # that we generate include all of those files not shown by the log. - # - # Also, our commits do not include diffs for the actual directories; - # only the files within those directories. - # - # Also, since we are only tracking the /trunk and not /branches/b, then - # there should not be anything referring to activity in /branches/b. - - assert_equal 3, deep_commits.first.token # Make sure this is the right revision - assert_equal 2, deep_commits.first.diffs.size # Two files seen + # The branch_name changes at this point, but none of the file contents + # actually change. So there are no diffs to report at this point. + assert_equal 3, commits[1].token + assert_equal 0, commits[1].diffs.size - assert_equal 'A', deep_commits.first.diffs[0].action - assert_equal '/subdir/bar.rb', deep_commits.first.diffs[0].path - assert_equal 'A', deep_commits.first.diffs[1].action - assert_equal '/subdir/foo.rb', deep_commits.first.diffs[1].path - - # In Revision 4, a directory is renamed. This shows in the Subversion log as + # In Revision 4, a subdirectory is renamed. This shows in the Subversion log as # # A /trunk/newdir (from /trunk/subdir:3) # D /trunk/subdir # - # Again, there are files in this directory, so make sure our commit includes + # There are files in this directory, so make sure our commit includes # both delete and add events for all of the files in this directory, but does # not actually refer to the directories themselves. - assert_equal 4, deep_commits.last.token # Make sure we're checking the right revision + assert_equal 4, commits.last.token # There should be 2 files removed and two files added - assert_equal 4, deep_commits.last.diffs.size + assert_equal 4, commits.last.diffs.size - assert_equal 'A', deep_commits.last.diffs[0].action - assert_equal '/newdir/bar.rb', deep_commits.last.diffs[0].path - assert_equal 'A', deep_commits.last.diffs[1].action - assert_equal '/newdir/foo.rb', deep_commits.last.diffs[1].path + assert_equal 'A', commits.last.diffs[0].action + assert_equal '/newdir/bar.rb', commits.last.diffs[0].path + assert_equal 'A', commits.last.diffs[1].action + assert_equal '/newdir/foo.rb', commits.last.diffs[1].path - assert_equal 'D', deep_commits.last.diffs[2].action - assert_equal '/subdir/bar.rb', deep_commits.last.diffs[2].path - assert_equal 'D', deep_commits.last.diffs[3].action - assert_equal '/subdir/foo.rb', deep_commits.last.diffs[3].path + assert_equal 'D', commits.last.diffs[2].action + assert_equal '/subdir/bar.rb', commits.last.diffs[2].path + assert_equal 'D', commits.last.diffs[3].action + assert_equal '/subdir/foo.rb', commits.last.diffs[3].path end end @@ -244,22 +253,5 @@ def test_each_commit assert_equal '/trunk/COPYING', commits[4].diffs[1].path end - def test_final_revision - with_svn_repository('svn') do |svn| - assert_equal 5, svn.commit_count - assert_equal [1,2,3,4,5], svn.commit_tokens - - svn.final_revision = 3 - assert_equal 3, svn.commit_count - assert_equal [1,2,3], svn.commit_tokens - - assert_equal 1, svn.commit_count(2) - assert_equal [3], svn.commit_tokens(2) - - assert_equal 0, svn.commit_count(4) - assert_equal [], svn.commit_tokens(4) - end - end - end end From 127dee2c5156ee20aad547c40875bca2ecf58959 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Thu, 5 Feb 2009 13:09:35 -0800 Subject: [PATCH 004/219] [NEW] An attempt to explain SvnAdapter chaining. --- lib/scm/adapters/svn/chain.rb | 72 +++++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 15 deletions(-) diff --git a/lib/scm/adapters/svn/chain.rb b/lib/scm/adapters/svn/chain.rb index cafeb322..74b5d294 100644 --- a/lib/scm/adapters/svn/chain.rb +++ b/lib/scm/adapters/svn/chain.rb @@ -1,19 +1,50 @@ module Scm::Adapters class SvnAdapter < AbstractAdapter - def first_token(since=0) - first_commit(since).token - end + # Some explanation is in order about "chaining." + # + # First, realize that a base SvnAdapter only tracks the history of a single + # subdirectory. If you point an adapter at /trunk, then that adapter is + # going to ignore eveything in /branches and /tags. + # + # The problem with this is that directories often get moved about. What is + # called "/trunk" today might have been in a branch directory at some point + # in the past. But since we completely ignore other directories, we never see + # that old history. + # + # Suppose for example that from revisions 1 to 100, development occured in + # /branches/beta. Then at revision 101, /trunk was created by copying + # /branches/beta, and this /trunk lives on to this day. + # + # The log for revision 101 is going to look something like this: + # + # Changed paths: + # D /branches/beta + # A /trunk (from /branches/beta:100) + # + # A single SvnAdapter pointed at today's /trunk will only see revisions 101 + # to HEAD, because /trunk didn't even exist before revision 101. + # + # To capture the prior history, we need to create *another* SvnAdapter + # which points at /branches/beta, and which considers revisions from 1 to 100. + # + # That's what chaining is: when we find that the first commit of an adapter + # indicates the wholesale renaming or copying of the entire tree from + # another location, then we generate a new SvnAdapter that points to that + # prior location, and process that SvnAdapter as well. + # + # This behavior recurses ("chains") all the way back to revision 1. + # + # It only works if the *entire branch* changes names. We don't chain when + # subdirectories or individual files are copied. - def first_commit(since=0) - Scm::Parsers::SvnXmlParser.parse(next_revision_xml(since)).first - end - - # Returns the first commit with a revision number greater than the provided revision number - def next_revision_xml(since) - run "svn log --verbose --xml --stop-on-copy -r #{since+1}:#{final_token || 'HEAD'} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}'" + # Returns the entire parent ancestry chain as a simple array. + def chain + (parent_svn ? parent_svn.chain : []) << self end + # If this adapter's branch was created by copying or renaming another branch, + # then return a new adapter that points to that prior branch. def parent_svn(since=0) parent = nil c = first_commit(since) @@ -30,11 +61,6 @@ def parent_svn(since=0) parent end - # Returns the parent_svn ancestry as a list, oldest first - def chain - (parent_svn ? parent_svn.chain : []) << self - end - #------------------------------------------------------------------ # Recursive or "chained" versions of the commit accessors. # @@ -52,10 +78,12 @@ def chained_commit_tokens(since=0) (parent_svn ? parent_svn.chained_commit_tokens(since) : []) + base_commit_tokens(since) end + # Returns an array of commits following revision number 'since'. def chained_commits(since=0) (parent_svn ? parent_svn.chained_commits(since) : []) + base_commits(since) end + # Yield verbose commits following revision number 'since', one at a time. def chained_each_commit(since=0, &block) parent_svn.chained_each_commit(since, &block) if parent_svn base_each_commit(since) do |commit| @@ -63,5 +91,19 @@ def chained_each_commit(since=0, &block) end end + # Helper methods for parent_svn + + def first_token(since=0) + first_commit(since).token + end + + def first_commit(since=0) + Scm::Parsers::SvnXmlParser.parse(next_revision_xml(since)).first + end + + # Returns the first commit with a revision number greater than the provided revision number + def next_revision_xml(since) + run "svn log --verbose --xml --stop-on-copy -r #{since+1}:#{final_token || 'HEAD'} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}'" + end end end From 204fa221c88280e32fbbb01cd3a12fdef0939d3f Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Mon, 9 Feb 2009 14:43:43 -0800 Subject: [PATCH 005/219] [FIX] Escape the ">" character and others. Surely there's a better way.... --- lib/scm/adapters/bzr/cat_file.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scm/adapters/bzr/cat_file.rb b/lib/scm/adapters/bzr/cat_file.rb index 8017919d..53b74567 100644 --- a/lib/scm/adapters/bzr/cat_file.rb +++ b/lib/scm/adapters/bzr/cat_file.rb @@ -20,7 +20,7 @@ def cat(revision, path) # Example: # "Foo Bar & Baz" => "Foo\ Bar\ \&\ Baz" def escape(path) - path.gsub(/[ '"&]/) { |c| '\\' + c } + path.gsub(/[ '"&<>\|]/) { |c| '\\' + c } end end end From a3ece0394e57230d8b3d8780680e0cd0a8c8ee6b Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 10 Feb 2009 10:01:18 -0800 Subject: [PATCH 006/219] [FIX] Fixes ticket 2. Always check the exit status code of bzr cat. Non-empty STDERR does not always imply failure. In this specific case, we are receiving an upgrade warning on STDERR, but this does not mean that we should abort. --- lib/scm/adapters/abstract/system.rb | 4 ++-- lib/scm/adapters/bzr/cat_file.rb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/scm/adapters/abstract/system.rb b/lib/scm/adapters/abstract/system.rb index d3b452ac..6dd6bcaa 100644 --- a/lib/scm/adapters/abstract/system.rb +++ b/lib/scm/adapters/abstract/system.rb @@ -27,11 +27,11 @@ def run(cmd) end # As above, but does not raise an exception when an error occurs. - # Returns two values, stdout and stderr. + # Returns three values: stdout, stderr, and process exit code def self.run_with_err(cmd) logger.debug { cmd } status, out, err = systemu(cmd) - [out, err] + [out, err, status] end def run_with_err(cmd) diff --git a/lib/scm/adapters/bzr/cat_file.rb b/lib/scm/adapters/bzr/cat_file.rb index 53b74567..32206777 100644 --- a/lib/scm/adapters/bzr/cat_file.rb +++ b/lib/scm/adapters/bzr/cat_file.rb @@ -10,9 +10,9 @@ def cat_file_parent(commit, diff) end def cat(revision, path) - out, err = run_with_err("cd '#{url}' && bzr cat --name-from-revision -r #{to_rev_param(revision)} #{escape(path)}") + out, err, status = run_with_err("cd '#{url}' && bzr cat --name-from-revision -r #{to_rev_param(revision)} #{escape(path)}") return nil if err =~ / is not present in revision / - raise RuntimeError.new(err) unless err.to_s == '' + raise RuntimeError.new(err) unless status == 0 out end From 94603a12bc7d38d5768145b1409fbe6bcff2a1bc Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 10 Feb 2009 11:40:20 -0800 Subject: [PATCH 007/219] [FIX] Fixes ticket 1. Add BzrParser support for file renames. In addition, it turns out that there are multiple ways in which Bazaar can report multiple operations to a file in a single commit. I've made the parser a bit messier in order to handle all of these cases. --- lib/scm/adapters/bzr/commits.rb | 18 +------- lib/scm/parsers/bzr_parser.rb | 47 ++++++++++++++++--- test/unit/bzr_commits_test.rb | 9 ---- test/unit/bzr_parser_test.rb | 81 +++++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+), 32 deletions(-) diff --git a/lib/scm/adapters/bzr/commits.rb b/lib/scm/adapters/bzr/commits.rb index 4101e3bc..1511d754 100644 --- a/lib/scm/adapters/bzr/commits.rb +++ b/lib/scm/adapters/bzr/commits.rb @@ -49,7 +49,7 @@ def verbose_commit(token) def each_commit(since=nil) open_log_file(since) do |io| Scm::Parsers::BzrParser.parse(io) do |commit| - yield remove_dupes(remove_directories(commit)) if block_given? && commit.token != since + yield remove_directories(commit) if block_given? && commit.token != since end end end @@ -61,22 +61,6 @@ def remove_directories(commit) commit end - # Bazaar may report that a file was both removed and added in the same commit. - # We're going to consider this to be simply a modification of the file. - # So we'll remove the 'D' action, and replace the 'A' with an 'M' action. - def remove_dupes(commit) - if commit.diffs - dupes = commit.diffs.collect do |d| - d if d.action == 'D' && commit.diffs.select { |x| x.action == 'A' and x.path == d.path }.any? - end.compact - dupes.each do |dupe| - commit.diffs.delete_if { |del| del.action == 'D' and del.path == dupe.path } - commit.diffs.each { |add| add.action = 'M' if add.path == dupe.path } - end - end - commit - end - # Not used by Ohloh proper, but handy for debugging and testing def log(since=nil) diff --git a/lib/scm/parsers/bzr_parser.rb b/lib/scm/parsers/bzr_parser.rb index 056642aa..aad7d35a 100644 --- a/lib/scm/parsers/bzr_parser.rb +++ b/lib/scm/parsers/bzr_parser.rb @@ -19,7 +19,10 @@ def self.internal_parse(buffer, opts) when /^( *)-+$/ # a new commit begins indent = $1 - yield e if e && block_given? + if e && block_given? + e.diffs = remove_dupes(e.diffs) + yield e + end e = Scm::Commit.new e.diffs = [] next_state = :data @@ -46,16 +49,19 @@ def self.internal_parse(buffer, opts) when /^#{indent}removed:$/ next_state = :collect_files action = 'D' + when /^#{indent}renamed:$/ + next_state = :collect_files + action = :rename when /^#{indent}message:$/ next_state = :collect_message e.message ||= '' when /^#{indent} (.*)$/ case state when :collect_files - path = $1 - # strip the id from the filename if it is present - path = $1 if show_id && path =~ /^(.+?)\s+(\S+)$/ - e.diffs << Scm::Diff.new(:action => action, :path => path) + line = $1 + # strip the id from the end of the line if it is present + line = $1 if show_id && line =~ /^(.+?)\s+(\S+)$/ + parse_diffs(action, line).each { |d| e.diffs << d } when :collect_message e.message << $1 e.message << "\n" @@ -64,8 +70,37 @@ def self.internal_parse(buffer, opts) state = next_state end - yield e if e && block_given? + if e && block_given? + e.diffs = remove_dupes(e.diffs) + yield e + end end + # Given a line from the log represent a file operation, + # return a collection of diffs for that action + def self.parse_diffs(action, line) + case action + when :rename + # A rename action requires two diffs: one to remove the old filename, + # another to add the new filename + before, after = line.scan(/(.+) => (.+)/).first + [ Scm::Diff.new(:action => 'D', :path => before), + Scm::Diff.new(:action => 'A', :path => after )] + else + [Scm::Diff.new(:action => action, :path => line)] + end + end + + # Bazaar may report that a file was both deleted, added, and/or modified all + # in a single commit. + # + # All such cases mean that the path in question still exists, and that some + # kind of modification occured, so we reduce all such multiple cases to + # a single diff with an 'M' action. + def self.remove_dupes(diffs) + diffs.each do |d| + d.action = 'M' if diffs.select { |x| x.path == d.path }.size > 1 + end.uniq + end end end diff --git a/test/unit/bzr_commits_test.rb b/test/unit/bzr_commits_test.rb index c4c0549b..12350c8a 100644 --- a/test/unit/bzr_commits_test.rb +++ b/test/unit/bzr_commits_test.rb @@ -63,15 +63,6 @@ def test_each_commit end end - def test_remove_dupes_add_remove - bzr = BzrAdapter.new - c = Scm::Commit.new(:diffs => [ Scm::Diff.new(:action => "A", :path => "foo"), - Scm::Diff.new(:action => "D", :path => "foo") ]) - bzr.remove_dupes(c) - assert_equal 1, c.diffs.size - assert_equal 'M', c.diffs.first.action - end - # This bzr repository contains the following tree structure # /foo/ # /foo/helloworld.c diff --git a/test/unit/bzr_parser_test.rb b/test/unit/bzr_parser_test.rb index 57d0e5a0..6359475e 100644 --- a/test/unit/bzr_parser_test.rb +++ b/test/unit/bzr_parser_test.rb @@ -264,5 +264,86 @@ def test_verbose_log_with_nested_merge_commits assert_equal 'hello_world.c', commits[3].diffs[0].path assert_equal 'M', commits[3].diffs[0].action end + + def test_parse_diffs + assert_equal 'A', BzrParser.parse_diffs('A', "helloworld.c").first.action + assert_equal 'helloworld.c', BzrParser.parse_diffs('A', "helloworld.c").first.path + end + + def test_parse_diffs_rename + diffs = BzrParser.parse_diffs(:rename, "helloworld.c => goodbyeworld.c") + assert_equal 2, diffs.size + assert_equal 'D', diffs.first.action + assert_equal 'helloworld.c', diffs.first.path + assert_equal 'A', diffs.last.action + assert_equal 'goodbyeworld.c', diffs.last.path + end + + def test_rename + log = <<-SAMPLE +------------------------------------------------------------ +revno: 2 +committer: info +timestamp: Wed 2005-09-14 21:27:20 +1000 +message: + rename a file +renamed: + helloworld.c => goodbyeworld.c + SAMPLE + + commits = BzrParser.parse(log) + + assert commits + assert_equal 1, commits.size + assert_equal 2, commits.first.diffs.size + + assert_equal 'D', commits.first.diffs.first.action + assert_equal 'helloworld.c', commits.first.diffs.first.path + + assert_equal 'A', commits.first.diffs.last.action + assert_equal 'goodbyeworld.c', commits.first.diffs.last.path + end + + def test_remove_dupes_add_remove + diffs = BzrParser.remove_dupes([ Scm::Diff.new(:action => "A", :path => "foo"), + Scm::Diff.new(:action => "D", :path => "foo") ]) + assert_equal 1, diffs.size + assert_equal 'M', diffs.first.action + assert_equal 'foo', diffs.first.path + end + + # A somewhat tricky case. A file is deleted, and another + # file is renamed to take its place. That file is then modified! + # + # This is what Ohloh expects to see: + # + # D goodbyeworld.c + # M helloworld.c + # + def test_complex_rename + log = <<-SAMPLE +------------------------------------------------------------ +revno: 147.1.24 +committer: info +timestamp: Wed 2005-09-14 21:27:20 +1000 +message: + rename a file to replace an existing one, then modify it! +removed: + helloworld.c +renamed: + goodbyeworld.c => helloworld.c +modified: + helloworld.c + SAMPLE + + diffs = BzrParser.parse(log).first.diffs + diffs.sort! { |a,b| a.path <=> b.path } + + assert_equal 2, diffs.size + assert_equal 'D', diffs.first.action + assert_equal 'goodbyeworld.c', diffs.first.path + assert_equal 'M', diffs.last.action + assert_equal 'helloworld.c', diffs.last.path + end end end From 6f0ed8c9a0555fdbe34bd4c3b471407711d2e0bb Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 10 Feb 2009 12:57:56 -0800 Subject: [PATCH 008/219] [FIX] Fixes ticket 3. "bzr://" is now a valid protocol for a Bazaar URL. --- lib/scm/adapters/bzr/validation.rb | 4 ++-- test/unit/bzr_validation_test.rb | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/scm/adapters/bzr/validation.rb b/lib/scm/adapters/bzr/validation.rb index 468818b2..113b0539 100644 --- a/lib/scm/adapters/bzr/validation.rb +++ b/lib/scm/adapters/bzr/validation.rb @@ -1,11 +1,11 @@ module Scm::Adapters class BzrAdapter < AbstractAdapter def self.url_regex - /^((http|https|bzr\+ssh|file):\/\/((\w+@)?[A-Za-z0-9_\-\.]+(:\d+)?\/)?)?[A-Za-z0-9_\-\.\/\~\+]*$/ + /^((http|https|bzr|bzr\+ssh|file):\/\/((\w+@)?[A-Za-z0-9_\-\.]+(:\d+)?\/)?)?[A-Za-z0-9_\-\.\/\~\+]*$/ end def self.public_url_regex - /^(http|https):\/\/(\w+@)?[A-Za-z0-9_\-\.]+(:\d+)?\/[A-Za-z0-9_\-\.\/\~\+]*$/ + /^(http|https|bzr):\/\/(\w+@)?[A-Za-z0-9_\-\.]+(:\d+)?\/[A-Za-z0-9_\-\.\/\~\+]*$/ end def validate_server_connection diff --git a/test/unit/bzr_validation_test.rb b/test/unit/bzr_validation_test.rb index 7ebe0d1b..1a17beb9 100644 --- a/test/unit/bzr_validation_test.rb +++ b/test/unit/bzr_validation_test.rb @@ -19,6 +19,7 @@ def test_accepted_urls [ "http://www.selenic.com/repo/hello", "http://www.selenic.com:80/repo/hello", "https://www.selenic.com/repo/hello", + "bzr://www.selenic.com/repo/hello", ].each do |url| bzr = BzrAdapter.new(:url => url, :public_urls_only => true) assert !bzr.validate_url @@ -47,6 +48,9 @@ def test_guess_forge bzr = BzrAdapter.new(:url => "/home/test/bzr") assert_equal nil, bzr.guess_forge + bzr = BzrAdapter.new( :url => 'bzr://www.selenic.com/repo/hello') + assert_equal 'www.selenic.com', bzr.guess_forge + bzr = BzrAdapter.new( :url => 'http://www.selenic.com/repo/hello') assert_equal 'www.selenic.com', bzr.guess_forge end From 67165ede1be4102fb6a1daf6b4d2778913938045 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 10 Feb 2009 13:22:34 -0800 Subject: [PATCH 009/219] [FIX] Fixes ticket 4. Strip trailing "*" from executable filenames. --- lib/scm/parsers/bzr_parser.rb | 6 ++++++ test/unit/bzr_parser_test.rb | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/lib/scm/parsers/bzr_parser.rb b/lib/scm/parsers/bzr_parser.rb index aad7d35a..8f9bfc93 100644 --- a/lib/scm/parsers/bzr_parser.rb +++ b/lib/scm/parsers/bzr_parser.rb @@ -88,9 +88,15 @@ def self.parse_diffs(action, line) Scm::Diff.new(:action => 'A', :path => after )] else [Scm::Diff.new(:action => action, :path => line)] + end.each do |d| + d.path = strip_trailing_asterisk(d.path) end end + def self.strip_trailing_asterisk(path) + path[-1..-1] == '*' ? path[0..-2] : path + end + # Bazaar may report that a file was both deleted, added, and/or modified all # in a single commit. # diff --git a/test/unit/bzr_parser_test.rb b/test/unit/bzr_parser_test.rb index 6359475e..baa223a5 100644 --- a/test/unit/bzr_parser_test.rb +++ b/test/unit/bzr_parser_test.rb @@ -345,5 +345,28 @@ def test_complex_rename assert_equal 'M', diffs.last.action assert_equal 'helloworld.c', diffs.last.path end + + def test_strip_trailing_asterisk_from_executables + log = <<-SAMPLE +------------------------------------------------------------ +revno: 1 +committer: info +timestamp: Wed 2005-09-14 21:27:20 +1000 +message: + added an executable, also renamed an executable +added: + script* +renamed: + helloworld* => goodbyeworld* + SAMPLE + + diffs = BzrParser.parse(log).first.diffs + diffs.sort! { |a,b| a.path <=> b.path } + + assert_equal 'goodbyeworld', diffs[0].path + assert_equal 'helloworld', diffs[1].path + assert_equal 'script', diffs[2].path + + end end end From d4482b2e946d6c4c8014b417141825273797925f Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 10 Feb 2009 14:32:06 -0800 Subject: [PATCH 010/219] [FIX] Fixes ticket 5. Filter out the majority of cases where the commit message includes a line of only dashes (thus confusing the parser). --- lib/scm/parsers/bzr_parser.rb | 9 ++++++++- test/unit/bzr_parser_test.rb | 37 +++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/lib/scm/parsers/bzr_parser.rb b/lib/scm/parsers/bzr_parser.rb index 8f9bfc93..bedfb36b 100644 --- a/lib/scm/parsers/bzr_parser.rb +++ b/lib/scm/parsers/bzr_parser.rb @@ -16,7 +16,14 @@ def self.internal_parse(buffer, opts) next_state = state case l - when /^( *)-+$/ + # A commit message can contain lines of only dashes, which makes parsing difficult. + # + # This delimiter detector filters most casual cases of using dash lines in commits. + # We check that the dashed line is exactly 60 chars long, and is prepended by 4*n spaces. + # + # Unless the commit message itself includes leading spaces, the commit message will + # begin in column 4*n+2, and thus will not match our pattern. + when /^(( )*)-{60,60}$/ # a new commit begins indent = $1 if e && block_given? diff --git a/test/unit/bzr_parser_test.rb b/test/unit/bzr_parser_test.rb index baa223a5..59e9060a 100644 --- a/test/unit/bzr_parser_test.rb +++ b/test/unit/bzr_parser_test.rb @@ -366,7 +366,44 @@ def test_strip_trailing_asterisk_from_executables assert_equal 'goodbyeworld', diffs[0].path assert_equal 'helloworld', diffs[1].path assert_equal 'script', diffs[2].path + end + + def test_comment_that_contains_dashes + log = <<-SAMPLE +------------------------------------------------------------ +revno: 2 +committer: info +timestamp: Wed 2005-09-14 21:27:20 +1000 +message: + This is a tricky commit message to confirm fix + to Ticket 5. We're including a line of dashes in + the message that resembles a log delimiter. + + ------------------------------------------------------------ + + Happy parsing! +added: + goodbyeworld.c +------------------------------------------------------------ +revno: 1 +committer: info +timestamp: Wed 2005-09-14 21:27:20 +1000 +message: + Initial Revision +added: + helloworld.c + SAMPLE + + commits = BzrParser.parse(log) + + assert_equal 2, commits.size + assert_equal '2', commits.first.token + assert_equal 1, commits.first.diffs.size + assert_equal "goodbyeworld.c", commits.first.diffs.first.path + assert_equal '1', commits.last.token + assert_equal 1, commits.last.diffs.size + assert_equal "helloworld.c", commits.last.diffs.first.path end end end From 4bc15012831707b4c5ecd4f49852d5daeda1d273 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 10 Feb 2009 14:58:58 -0800 Subject: [PATCH 011/219] [FIX] D'OH! Stop trying to escape every possible special char. Just put it in quotes, already. --- lib/scm/adapters/bzr/cat_file.rb | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/lib/scm/adapters/bzr/cat_file.rb b/lib/scm/adapters/bzr/cat_file.rb index 32206777..ff7d2fd0 100644 --- a/lib/scm/adapters/bzr/cat_file.rb +++ b/lib/scm/adapters/bzr/cat_file.rb @@ -10,17 +10,10 @@ def cat_file_parent(commit, diff) end def cat(revision, path) - out, err, status = run_with_err("cd '#{url}' && bzr cat --name-from-revision -r #{to_rev_param(revision)} #{escape(path)}") + out, err, status = run_with_err("cd '#{url}' && bzr cat --name-from-revision -r #{to_rev_param(revision)} '#{path}'") return nil if err =~ / is not present in revision / raise RuntimeError.new(err) unless status == 0 out end - - # Escape bash-significant characters in the filename - # Example: - # "Foo Bar & Baz" => "Foo\ Bar\ \&\ Baz" - def escape(path) - path.gsub(/[ '"&<>\|]/) { |c| '\\' + c } - end end end From 3d2acf41857a76373b8172b6d8342758de379c89 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 10 Feb 2009 15:43:44 -0800 Subject: [PATCH 012/219] [FIX] BzrAdapter.cat_file() breaks if filename begins with colon. It feels like just deleted this silly escape() method... --- lib/scm/adapters/bzr/cat_file.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/scm/adapters/bzr/cat_file.rb b/lib/scm/adapters/bzr/cat_file.rb index ff7d2fd0..c12d7311 100644 --- a/lib/scm/adapters/bzr/cat_file.rb +++ b/lib/scm/adapters/bzr/cat_file.rb @@ -10,10 +10,15 @@ def cat_file_parent(commit, diff) end def cat(revision, path) - out, err, status = run_with_err("cd '#{url}' && bzr cat --name-from-revision -r #{to_rev_param(revision)} '#{path}'") + out, err, status = run_with_err("cd '#{url}' && bzr cat --name-from-revision -r #{to_rev_param(revision)} '#{escape(path)}'") return nil if err =~ / is not present in revision / raise RuntimeError.new(err) unless status == 0 out end + + # Bzr doesn't like it when the filename includes a colon + def escape(path) + path.gsub(/[:]/) { |c| '\\' + c } + end end end From 727c15f7535c3482e4b35d8d662b44cfc5c4191a Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Wed, 11 Feb 2009 14:27:21 -0800 Subject: [PATCH 013/219] [FIX] svn.verbose_commit() and svn.cat_file() now work when the requested revision belongs to a chained parent. --- lib/scm/adapters/svn/cat_file.rb | 6 +++++- lib/scm/adapters/svn/chain.rb | 21 +++++++++++++++------ lib/scm/adapters/svn/commits.rb | 14 +++++++++----- test/unit/svn_cat_file_test.rb | 21 +++++++++++++++++++-- test/unit/svn_commits_test.rb | 28 ++++++++++++++++++++++++++++ 5 files changed, 76 insertions(+), 14 deletions(-) diff --git a/lib/scm/adapters/svn/cat_file.rb b/lib/scm/adapters/svn/cat_file.rb index 68c3b2d0..fb2a8d11 100644 --- a/lib/scm/adapters/svn/cat_file.rb +++ b/lib/scm/adapters/svn/cat_file.rb @@ -8,7 +8,11 @@ def cat_file_parent(commit, diff) cat(diff.path, commit.token.to_i-1) end - def cat(path=nil, revision='HEAD') + def cat(path, revision) + parent_svn(revision) ? parent_svn.cat(path, revision) : base_cat(path, revision) + end + + def base_cat(path, revision) begin run "svn cat -r #{revision} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name.to_s, path.to_s))}@#{revision}'" rescue diff --git a/lib/scm/adapters/svn/chain.rb b/lib/scm/adapters/svn/chain.rb index 74b5d294..7bfdd961 100644 --- a/lib/scm/adapters/svn/chain.rb +++ b/lib/scm/adapters/svn/chain.rb @@ -45,6 +45,9 @@ def chain # If this adapter's branch was created by copying or renaming another branch, # then return a new adapter that points to that prior branch. + # + # Only commits following +since+ are considered, so if the copy or rename + # occured on or before +since+, then no parent will be found or returned. def parent_svn(since=0) parent = nil c = first_commit(since) @@ -75,12 +78,12 @@ def chained_commit_count(since=0) # Returns an array of revision numbers for all commits following revision number 'since'. def chained_commit_tokens(since=0) - (parent_svn ? parent_svn.chained_commit_tokens(since) : []) + base_commit_tokens(since) + (parent_svn(since) ? parent_svn.chained_commit_tokens(since) : []) + base_commit_tokens(since) end # Returns an array of commits following revision number 'since'. def chained_commits(since=0) - (parent_svn ? parent_svn.chained_commits(since) : []) + base_commits(since) + (parent_svn(since) ? parent_svn.chained_commits(since) : []) + base_commits(since) end # Yield verbose commits following revision number 'since', one at a time. @@ -91,19 +94,25 @@ def chained_each_commit(since=0, &block) end end + def chained_verbose_commit(since=0) + parent_svn(since) ? parent_svn.chained_verbose_commit(since) : base_verbose_commit(since) + end + # Helper methods for parent_svn def first_token(since=0) - first_commit(since).token + c = first_commit(since) + c && c.token end def first_commit(since=0) Scm::Parsers::SvnXmlParser.parse(next_revision_xml(since)).first end - + # Returns the first commit with a revision number greater than the provided revision number - def next_revision_xml(since) - run "svn log --verbose --xml --stop-on-copy -r #{since+1}:#{final_token || 'HEAD'} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}'" + def next_revision_xml(since=0) + return "" if since.to_i >= head_token + run "svn log --verbose --xml --stop-on-copy -r #{since.to_i+1}:#{final_token || 'HEAD'} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}'" end end end diff --git a/lib/scm/adapters/svn/commits.rb b/lib/scm/adapters/svn/commits.rb index 345118bb..b88318aa 100644 --- a/lib/scm/adapters/svn/commits.rb +++ b/lib/scm/adapters/svn/commits.rb @@ -37,6 +37,10 @@ def each_commit(since=0) chained_each_commit(since) { |commit| yield commit } end + def verbose_commit(since=0) + chained_verbose_commit(since) + end + #------------------------------------------------------------------ # Base versions of the commit accessors. # @@ -46,12 +50,14 @@ def each_commit(since=0) # Returns the count of commits following revision number 'since'. def base_commit_count(since=0) + since ||= 0 return 0 if final_token && since >= final_token run("svn log -q -r #{since.to_i + 1}:#{final_token || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{final_token || 'HEAD'}' | grep -E -e '^r[0-9]+ ' | wc -l").strip.to_i end # Returns an array of revision numbers for all commits following revision number 'since'. def base_commit_tokens(since=0) + since ||= 0 return [] if final_token && since >= final_token cmd = "svn log -q -r #{since.to_i + 1}:#{final_token || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{final_token || 'HEAD'}' | grep -E -e '^r[0-9]+ ' | cut -f 1 -d '|' | cut -c 2-" run(cmd).split.collect { |r| r.to_i } @@ -75,7 +81,7 @@ def base_commits(since=0) # def base_each_commit(since=nil) base_commit_tokens(since).each do |rev| - yield deepen_commit(strip_commit_branch(verbose_commit(rev))) + yield base_verbose_commit(rev) end end @@ -158,10 +164,8 @@ def strip_path_branch(path) end end - # A single commit, including any changed paths. - # Basically equivalent to the data you get back from the Subversion log when you pass the --verbose flag. - def verbose_commit(rev) - Scm::Parsers::SvnXmlParser.parse(single_revision_xml(rev)).first + def base_verbose_commit(rev) + deepen_commit(strip_commit_branch(Scm::Parsers::SvnXmlParser.parse(single_revision_xml(rev)).first)) end #--------------------------------------------------------------------- diff --git a/test/unit/svn_cat_file_test.rb b/test/unit/svn_cat_file_test.rb index acb5908f..188ad624 100644 --- a/test/unit/svn_cat_file_test.rb +++ b/test/unit/svn_cat_file_test.rb @@ -13,11 +13,28 @@ def test_cat_file printf("Hello, World!\\n"); } EXPECTED - assert_equal expected, svn.cat_file(Scm::Commit.new(:token => "1"), Scm::Diff.new(:path => "trunk/helloworld.c")) + assert_equal expected, svn.cat_file(Scm::Commit.new(:token => 1), Scm::Diff.new(:path => "trunk/helloworld.c")) - assert_equal nil, svn.cat_file(Scm::Commit.new(:token => "1"), Scm::Diff.new(:path => "file not found")) + assert_equal nil, svn.cat_file(Scm::Commit.new(:token => 1), Scm::Diff.new(:path => "file not found")) end + end + + def test_cat_file_with_chaining +goodbye = <<-EXPECTED +#include +main() +{ + printf("Goodbye, world!\\n"); +} +EXPECTED + with_svn_repository('svn_with_branching', '/trunk') do |svn| + # The first case asks for the file on the HEAD, so it should easily be found + assert_equal goodbye, svn.cat_file(Scm::Commit.new(:token => 8), Scm::Diff.new(:path => "goodbyeworld.c")) + # The next test asks for the file as it appeared before /branches/development was moved to /trunk, + # so this request requires traversal up the chain to the parent SvnAdapter. + assert_equal goodbye, svn.cat_file(Scm::Commit.new(:token => 5), Scm::Diff.new(:path => "goodbyeworld.c")) + end end end end diff --git a/test/unit/svn_commits_test.rb b/test/unit/svn_commits_test.rb index 54dc0861..eaf2e64e 100644 --- a/test/unit/svn_commits_test.rb +++ b/test/unit/svn_commits_test.rb @@ -253,5 +253,33 @@ def test_each_commit assert_equal '/trunk/COPYING', commits[4].diffs[1].path end + def test_verbose_commit_with_chaining + with_svn_repository('svn_with_branching','/trunk') do |svn| + + assert svn.verbose_commit(9) + assert_equal 'modified helloworld.c', svn.verbose_commit(9).message + assert_equal ['/helloworld.c'], svn.verbose_commit(9).diffs.collect { |d| d.path } + + assert svn.verbose_commit(8) + assert_equal [], svn.verbose_commit(8).diffs + + # Reaching these commits requires chaining + assert svn.verbose_commit(5) + assert_equal 'add a new branch, with goodbyeworld.c', svn.verbose_commit(5).message + assert_equal ['/goodbyeworld.c'], svn.verbose_commit(5).diffs.collect { |d| d.path } + + assert svn.verbose_commit(4) + assert_equal [], svn.verbose_commit(4).diffs + + # Reaching these commits requires chaining twice + assert svn.verbose_commit(2) + assert_equal 'Added helloworld.c to trunk', svn.verbose_commit(2).message + assert_equal ['/helloworld.c'], svn.verbose_commit(2).diffs.collect { |d| d.path } + + assert svn.verbose_commit(1) + assert_equal [], svn.verbose_commit(1).diffs + end + end + end end From d145c1d3707b5e30633a80f647bde42b019057e2 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Thu, 12 Feb 2009 12:04:44 -0800 Subject: [PATCH 014/219] [NEW] Conversion to git now supports svn chaining. We achieve this by passing a pointer to the "current" link in the svn chain along with the commit itself. So when we want to check out a particular commit from Subversion, we can determine the appropriate branch/URL to check out from. --- lib/scm/adapters/cvs/commits.rb | 3 +++ lib/scm/adapters/git/pull.rb | 4 ++-- lib/scm/adapters/svn/commits.rb | 20 ++++++++++------ lib/scm/commit.rb | 3 +++ test/unit/cvs_commits_test.rb | 8 +++++++ test/unit/svn_commits_test.rb | 42 ++++++++++++++++++++------------- 6 files changed, 54 insertions(+), 26 deletions(-) diff --git a/lib/scm/adapters/cvs/commits.rb b/lib/scm/adapters/cvs/commits.rb index f17721aa..db3770ed 100644 --- a/lib/scm/adapters/cvs/commits.rb +++ b/lib/scm/adapters/cvs/commits.rb @@ -5,6 +5,9 @@ def commits(since=nil) open_log_file(since) do |io| result = Scm::Parsers::CvsParser.parse(io, :branch_name => branch_name) end + + # Git converter needs a backpointer to the scm for each commit + result.each { |c| c.scm = self } return result if result.size == 0 # Nothing found; we're done here. return result if since.to_s == '' # We requested everything, so just return everything. diff --git a/lib/scm/adapters/git/pull.rb b/lib/scm/adapters/git/pull.rb index 1b6d7f58..c57d17d6 100644 --- a/lib/scm/adapters/git/pull.rb +++ b/lib/scm/adapters/git/pull.rb @@ -83,14 +83,14 @@ def convert(source_scm) logger.info { "Downloading revision #{r.token} (#{i+1} of #{commits.size})... " } begin - source_scm.checkout(r, url) + r.scm.checkout(r, url) rescue logger.error { $!.inspect } # If we fail to checkout, it's often because there is junk of some kind # in our working directory. logger.info { "Checkout failed. Cleaning and trying again..." } clean_up_disk - source_scm.checkout(r, url) + r.scm.checkout(r, url) end logger.debug { "Committing revision #{r.token} (#{i+1} of #{commits.size})... " } diff --git a/lib/scm/adapters/svn/commits.rb b/lib/scm/adapters/svn/commits.rb index b88318aa..a0824dde 100644 --- a/lib/scm/adapters/svn/commits.rb +++ b/lib/scm/adapters/svn/commits.rb @@ -3,14 +3,16 @@ module Scm::Adapters class SvnAdapter < AbstractAdapter - # In all commit- and log-related methods, 'since' refers to the revision number of the last known commit, - # and the methods return the commits *following* this commit. + # In all commit- and log-related methods, 'since' refers to the revision + # number of the last known commit, and the methods return the commits + # *following* this commit. # # Examples: # commits(1) => [rev 2, rev 3, ..., HEAD] # commits(3) => [rev 4, rev 5, ..., HEAD] # - # This is convenient for Ohloh -- Ohloh passes the last commit it is aware of, and these methods return any new commits. + # This is convenient for Ohloh -- Ohloh passes the last commit it is aware + # of, and these methods return any new commits. # The last revision to be analyzed in this repository. Everything after this revision is ignored. # The repository is considered to be retired after this point, and under no circumstances should @@ -63,12 +65,14 @@ def base_commit_tokens(since=0) run(cmd).split.collect { |r| r.to_i } end - # Returns an array of commits following revision number 'since'. These commit objects do not include diffs. + # Returns an array of commits following revision number 'since'. + # These commit objects do not include diffs. def base_commits(since=0) - c = [] + list = [] open_log_file(since) do |io| - c = Scm::Parsers::SvnXmlParser.parse(io) + list = Scm::Parsers::SvnXmlParser.parse(io) end + list.each { |c| c.scm = self } end # Yields each commit following revision number 'since'. These commit object are populated with diffs. @@ -165,7 +169,9 @@ def strip_path_branch(path) end def base_verbose_commit(rev) - deepen_commit(strip_commit_branch(Scm::Parsers::SvnXmlParser.parse(single_revision_xml(rev)).first)) + c = Scm::Parsers::SvnXmlParser.parse(single_revision_xml(rev)).first + c.scm = self + deepen_commit(strip_commit_branch(c)) end #--------------------------------------------------------------------- diff --git a/lib/scm/commit.rb b/lib/scm/commit.rb index af119113..ddb9fa13 100644 --- a/lib/scm/commit.rb +++ b/lib/scm/commit.rb @@ -34,6 +34,9 @@ class Commit # the approximate timestamp of the change. attr_accessor :token + # A pointer back to the adapter that contains this commit. + attr_accessor :scm + # Hack. To optimize CVS updates, we will store the names of all the # directories that require updating during this commit. Ohloh itself never # actually sees this. diff --git a/test/unit/cvs_commits_test.rb b/test/unit/cvs_commits_test.rb index 83cb55f2..442cdb7e 100644 --- a/test/unit/cvs_commits_test.rb +++ b/test/unit/cvs_commits_test.rb @@ -23,5 +23,13 @@ def test_commits assert_equal [], cvs.commits('2006/06/29 18:52:23').collect { |c| c.token } end end + + def test_commits_sets_scm + with_cvs_repository('cvs') do |cvs| + cvs.commits.each do |c| + assert_equal cvs, c.scm + end + end + end end end diff --git a/test/unit/svn_commits_test.rb b/test/unit/svn_commits_test.rb index eaf2e64e..6f051d81 100644 --- a/test/unit/svn_commits_test.rb +++ b/test/unit/svn_commits_test.rb @@ -209,6 +209,7 @@ def test_each_commit assert d.action.length == 1 assert d.path.length > 0 end + assert_equal svn, e.scm # Commit points back to its containing scm. end assert !FileTest.exist?(svn.log_filename) # Make sure we cleaned up after ourselves end @@ -256,28 +257,35 @@ def test_each_commit def test_verbose_commit_with_chaining with_svn_repository('svn_with_branching','/trunk') do |svn| - assert svn.verbose_commit(9) - assert_equal 'modified helloworld.c', svn.verbose_commit(9).message - assert_equal ['/helloworld.c'], svn.verbose_commit(9).diffs.collect { |d| d.path } + c = svn.verbose_commit(9) + assert_equal 'modified helloworld.c', c.message + assert_equal ['/helloworld.c'], c.diffs.collect { |d| d.path } + assert_equal '/trunk', c.scm.branch_name - assert svn.verbose_commit(8) - assert_equal [], svn.verbose_commit(8).diffs + c = svn.verbose_commit(8) + assert_equal [], c.diffs + assert_equal '/trunk', c.scm.branch_name # Reaching these commits requires chaining - assert svn.verbose_commit(5) - assert_equal 'add a new branch, with goodbyeworld.c', svn.verbose_commit(5).message - assert_equal ['/goodbyeworld.c'], svn.verbose_commit(5).diffs.collect { |d| d.path } - - assert svn.verbose_commit(4) - assert_equal [], svn.verbose_commit(4).diffs + c = svn.verbose_commit(5) + assert_equal 'add a new branch, with goodbyeworld.c', c.message + assert_equal ['/goodbyeworld.c'], c.diffs.collect { |d| d.path } + assert_equal '/branches/development', c.scm.branch_name # Reaching these commits requires chaining twice - assert svn.verbose_commit(2) - assert_equal 'Added helloworld.c to trunk', svn.verbose_commit(2).message - assert_equal ['/helloworld.c'], svn.verbose_commit(2).diffs.collect { |d| d.path } - - assert svn.verbose_commit(1) - assert_equal [], svn.verbose_commit(1).diffs + c = svn.verbose_commit(4) + assert_equal [], c.diffs + assert_equal '/trunk', c.scm.branch_name + + # And now a fourth chain (to skip over /trunk deletion in rev 3) + c = svn.verbose_commit(2) + assert_equal 'Added helloworld.c to trunk', c.message + assert_equal ['/helloworld.c'], c.diffs.collect { |d| d.path } + assert_equal '/trunk', c.scm.branch_name + + c = svn.verbose_commit(1) + assert_equal [], c.diffs + assert_equal '/trunk', c.scm.branch_name end end From 0641fcc30035e63cad3cf557c39c4b86a47c72ef Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Thu, 12 Feb 2009 16:31:03 -0800 Subject: [PATCH 015/219] [FIX] Several bug fixes and improvements for Subversion chaining. --- lib/scm/adapters/git/commit_all.rb | 2 +- lib/scm/adapters/svn/chain.rb | 15 +++- lib/scm/adapters/svn/commits.rb | 4 +- .../svn_with_tree_move/README.txt | 5 ++ .../svn_with_tree_move/conf/authz | 21 ++++++ .../svn_with_tree_move/conf/passwd | 8 ++ .../svn_with_tree_move/conf/svnserve.conf | 30 ++++++++ .../svn_with_tree_move/db/current | 1 + .../repositories/svn_with_tree_move/db/format | 1 + .../svn_with_tree_move/db/fs-type | 1 + .../svn_with_tree_move/db/revprops/0 | 5 ++ .../svn_with_tree_move/db/revprops/1 | 13 ++++ .../svn_with_tree_move/db/revprops/2 | 13 ++++ .../repositories/svn_with_tree_move/db/revs/0 | 11 +++ .../repositories/svn_with_tree_move/db/revs/1 | Bin 0 -> 1098 bytes .../repositories/svn_with_tree_move/db/revs/2 | 44 +++++++++++ test/repositories/svn_with_tree_move/db/uuid | 1 + .../svn_with_tree_move/db/write-lock | 0 test/repositories/svn_with_tree_move/format | 1 + .../svn_with_tree_move/hooks/post-commit.tmpl | 51 +++++++++++++ .../svn_with_tree_move/hooks/post-lock.tmpl | 44 +++++++++++ .../hooks/post-revprop-change.tmpl | 56 ++++++++++++++ .../svn_with_tree_move/hooks/post-unlock.tmpl | 42 +++++++++++ .../svn_with_tree_move/hooks/pre-commit.tmpl | 70 ++++++++++++++++++ .../svn_with_tree_move/hooks/pre-lock.tmpl | 64 ++++++++++++++++ .../hooks/pre-revprop-change.tmpl | 66 +++++++++++++++++ .../svn_with_tree_move/hooks/pre-unlock.tmpl | 60 +++++++++++++++ .../hooks/start-commit.tmpl | 54 ++++++++++++++ .../svn_with_tree_move/locks/db-logs.lock | 3 + .../svn_with_tree_move/locks/db.lock | 3 + test/unit/svn_chain_test.rb | 32 +++++++- 31 files changed, 714 insertions(+), 7 deletions(-) create mode 100644 test/repositories/svn_with_tree_move/README.txt create mode 100644 test/repositories/svn_with_tree_move/conf/authz create mode 100644 test/repositories/svn_with_tree_move/conf/passwd create mode 100644 test/repositories/svn_with_tree_move/conf/svnserve.conf create mode 100644 test/repositories/svn_with_tree_move/db/current create mode 100644 test/repositories/svn_with_tree_move/db/format create mode 100644 test/repositories/svn_with_tree_move/db/fs-type create mode 100644 test/repositories/svn_with_tree_move/db/revprops/0 create mode 100644 test/repositories/svn_with_tree_move/db/revprops/1 create mode 100644 test/repositories/svn_with_tree_move/db/revprops/2 create mode 100644 test/repositories/svn_with_tree_move/db/revs/0 create mode 100644 test/repositories/svn_with_tree_move/db/revs/1 create mode 100644 test/repositories/svn_with_tree_move/db/revs/2 create mode 100644 test/repositories/svn_with_tree_move/db/uuid create mode 100644 test/repositories/svn_with_tree_move/db/write-lock create mode 100644 test/repositories/svn_with_tree_move/format create mode 100644 test/repositories/svn_with_tree_move/hooks/post-commit.tmpl create mode 100644 test/repositories/svn_with_tree_move/hooks/post-lock.tmpl create mode 100644 test/repositories/svn_with_tree_move/hooks/post-revprop-change.tmpl create mode 100644 test/repositories/svn_with_tree_move/hooks/post-unlock.tmpl create mode 100644 test/repositories/svn_with_tree_move/hooks/pre-commit.tmpl create mode 100644 test/repositories/svn_with_tree_move/hooks/pre-lock.tmpl create mode 100644 test/repositories/svn_with_tree_move/hooks/pre-revprop-change.tmpl create mode 100644 test/repositories/svn_with_tree_move/hooks/pre-unlock.tmpl create mode 100644 test/repositories/svn_with_tree_move/hooks/start-commit.tmpl create mode 100644 test/repositories/svn_with_tree_move/locks/db-logs.lock create mode 100644 test/repositories/svn_with_tree_move/locks/db.lock diff --git a/lib/scm/adapters/git/commit_all.rb b/lib/scm/adapters/git/commit_all.rb index acf06cf6..4ee7fbb6 100644 --- a/lib/scm/adapters/git/commit_all.rb +++ b/lib/scm/adapters/git/commit_all.rb @@ -16,7 +16,7 @@ def commit_all(commit=Commit.new) run "cd '#{self.url}' && git add ." if anything_to_commit? - run " cd '#{self.url}' && git commit -a -F #{message_filename}" + run "cd '#{self.url}' && git commit -a -F #{message_filename}" else logger.info { "nothing to commit" } end diff --git a/lib/scm/adapters/svn/chain.rb b/lib/scm/adapters/svn/chain.rb index 7bfdd961..8f67b55e 100644 --- a/lib/scm/adapters/svn/chain.rb +++ b/lib/scm/adapters/svn/chain.rb @@ -53,10 +53,10 @@ def parent_svn(since=0) c = first_commit(since) if c c.diffs.each do |d| - if d.action == 'A' && d.path == branch_name && d.from_path && d.from_revision - parent = SvnAdapter.new(:url => File.join(root, d.from_path), + if (b = new_branch_name(d)) + parent = SvnAdapter.new(:url => File.join(root, b), :branch_name => b, :username => username, :password => password, - :branch_name => d.from_path, :final_token => d.from_revision).normalize + :final_token => d.from_revision).normalize break end end @@ -114,5 +114,14 @@ def next_revision_xml(since=0) return "" if since.to_i >= head_token run "svn log --verbose --xml --stop-on-copy -r #{since.to_i+1}:#{final_token || 'HEAD'} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}'" end + + # If the passed diff represents the wholesale movement of the entire + # code tree from one directory to another, this method returns the name + # of the previous directory. + def new_branch_name(d) + if d.action == 'A' && branch_name[0, d.path.size] == d.path && d.from_path && d.from_revision + d.from_path + branch_name[d.path.size..-1] + end + end end end diff --git a/lib/scm/adapters/svn/commits.rb b/lib/scm/adapters/svn/commits.rb index a0824dde..e9566530 100644 --- a/lib/scm/adapters/svn/commits.rb +++ b/lib/scm/adapters/svn/commits.rb @@ -179,7 +179,7 @@ def base_verbose_commit(rev) #--------------------------------------------------------------------- def log(since=0) - run "svn log --xml --stop-on-copy -r #{since.to_i + 1}:#{final_token || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name.to_s))}' #{opt_auth}" + run "svn log --xml --stop-on-copy -r #{since.to_i + 1}:#{final_token || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name.to_s))}@#{final_token || 'HEAD'}' #{opt_auth}" end def open_log_file(since=0) @@ -189,7 +189,7 @@ def open_log_file(since=0) # As a time optimization, just create an empty file rather than fetch a log we know will be empty. File.open(log_filename, 'w') { |f| f.puts '' } else - run "svn log --xml --stop-on-copy -r #{since.to_i + 1}:#{final_token || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}' #{opt_auth} > #{log_filename}" + run "svn log --xml --stop-on-copy -r #{since.to_i + 1}:#{final_token || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}' #{opt_auth} > #{log_filename}" end File.open(log_filename, 'r') { |io| yield io } ensure diff --git a/test/repositories/svn_with_tree_move/README.txt b/test/repositories/svn_with_tree_move/README.txt new file mode 100644 index 00000000..3bf5a571 --- /dev/null +++ b/test/repositories/svn_with_tree_move/README.txt @@ -0,0 +1,5 @@ +This is a Subversion repository; use the 'svnadmin' tool to examine +it. Do not add, delete, or modify files here unless you know how +to avoid corrupting the repository. + +Visit http://subversion.tigris.org/ for more information. diff --git a/test/repositories/svn_with_tree_move/conf/authz b/test/repositories/svn_with_tree_move/conf/authz new file mode 100644 index 00000000..78cb28e9 --- /dev/null +++ b/test/repositories/svn_with_tree_move/conf/authz @@ -0,0 +1,21 @@ +### This file is an example authorization file for svnserve. +### Its format is identical to that of mod_authz_svn authorization +### files. +### As shown below each section defines authorizations for the path and +### (optional) repository specified by the section name. +### The authorizations follow. An authorization line can refer to a +### single user, to a group of users defined in a special [groups] +### section, or to anyone using the '*' wildcard. Each definition can +### grant read ('r') access, read-write ('rw') access, or no access +### (''). + +[groups] +# harry_and_sally = harry,sally + +# [/foo/bar] +# harry = rw +# * = + +# [repository:/baz/fuz] +# @harry_and_sally = rw +# * = r diff --git a/test/repositories/svn_with_tree_move/conf/passwd b/test/repositories/svn_with_tree_move/conf/passwd new file mode 100644 index 00000000..ecaa08dc --- /dev/null +++ b/test/repositories/svn_with_tree_move/conf/passwd @@ -0,0 +1,8 @@ +### This file is an example password file for svnserve. +### Its format is similar to that of svnserve.conf. As shown in the +### example below it contains one section labelled [users]. +### The name and password for each user follow, one account per line. + +[users] +# harry = harryssecret +# sally = sallyssecret diff --git a/test/repositories/svn_with_tree_move/conf/svnserve.conf b/test/repositories/svn_with_tree_move/conf/svnserve.conf new file mode 100644 index 00000000..b52bc5ab --- /dev/null +++ b/test/repositories/svn_with_tree_move/conf/svnserve.conf @@ -0,0 +1,30 @@ +### This file controls the configuration of the svnserve daemon, if you +### use it to allow access to this repository. (If you only allow +### access through http: and/or file: URLs, then this file is +### irrelevant.) + +### Visit http://subversion.tigris.org/ for more information. + +[general] +### These options control access to the repository for unauthenticated +### and authenticated users. Valid values are "write", "read", +### and "none". The sample settings below are the defaults. +# anon-access = read +# auth-access = write +### The password-db option controls the location of the password +### database file. Unless you specify a path starting with a /, +### the file's location is relative to the conf directory. +### Uncomment the line below to use the default password file. +# password-db = passwd +### The authz-db option controls the location of the authorization +### rules for path-based access control. Unless you specify a path +### starting with a /, the file's location is relative to the conf +### directory. If you don't specify an authz-db, no path-based access +### control is done. +### Uncomment the line below to use the default authorization file. +# authz-db = authz +### This option specifies the authentication realm of the repository. +### If two repositories have the same authentication realm, they should +### have the same password database, and vice versa. The default realm +### is repository's uuid. +# realm = My First Repository diff --git a/test/repositories/svn_with_tree_move/db/current b/test/repositories/svn_with_tree_move/db/current new file mode 100644 index 00000000..394811d0 --- /dev/null +++ b/test/repositories/svn_with_tree_move/db/current @@ -0,0 +1 @@ +2 5 2 diff --git a/test/repositories/svn_with_tree_move/db/format b/test/repositories/svn_with_tree_move/db/format new file mode 100644 index 00000000..0cfbf088 --- /dev/null +++ b/test/repositories/svn_with_tree_move/db/format @@ -0,0 +1 @@ +2 diff --git a/test/repositories/svn_with_tree_move/db/fs-type b/test/repositories/svn_with_tree_move/db/fs-type new file mode 100644 index 00000000..4fdd9531 --- /dev/null +++ b/test/repositories/svn_with_tree_move/db/fs-type @@ -0,0 +1 @@ +fsfs diff --git a/test/repositories/svn_with_tree_move/db/revprops/0 b/test/repositories/svn_with_tree_move/db/revprops/0 new file mode 100644 index 00000000..1716bf45 --- /dev/null +++ b/test/repositories/svn_with_tree_move/db/revprops/0 @@ -0,0 +1,5 @@ +K 8 +svn:date +V 27 +2009-02-12T23:29:46.930803Z +END diff --git a/test/repositories/svn_with_tree_move/db/revprops/1 b/test/repositories/svn_with_tree_move/db/revprops/1 new file mode 100644 index 00000000..296a9a0a --- /dev/null +++ b/test/repositories/svn_with_tree_move/db/revprops/1 @@ -0,0 +1,13 @@ +K 10 +svn:author +V 5 +robin +K 8 +svn:date +V 27 +2009-02-12T23:31:42.224055Z +K 7 +svn:log +V 16 +Initial Revision +END diff --git a/test/repositories/svn_with_tree_move/db/revprops/2 b/test/repositories/svn_with_tree_move/db/revprops/2 new file mode 100644 index 00000000..eed0157a --- /dev/null +++ b/test/repositories/svn_with_tree_move/db/revprops/2 @@ -0,0 +1,13 @@ +K 10 +svn:author +V 5 +robin +K 8 +svn:date +V 27 +2009-02-12T23:32:13.278922Z +K 7 +svn:log +V 22 +Move tree up one level +END diff --git a/test/repositories/svn_with_tree_move/db/revs/0 b/test/repositories/svn_with_tree_move/db/revs/0 new file mode 100644 index 00000000..10f5c45f --- /dev/null +++ b/test/repositories/svn_with_tree_move/db/revs/0 @@ -0,0 +1,11 @@ +PLAIN +END +ENDREP +id: 0.0.r0/17 +type: dir +count: 0 +text: 0 0 4 4 2d2977d1c96f487abe4a1e202dd03b4e +cpath: / + + +17 107 diff --git a/test/repositories/svn_with_tree_move/db/revs/1 b/test/repositories/svn_with_tree_move/db/revs/1 new file mode 100644 index 0000000000000000000000000000000000000000..72b68a3e8d1ec73269ec06ba08a02b3e55d362c2 GIT binary patch literal 1098 zcma)*(Q4Z;6o%W~?L39n-L$a9(vfUQ?idsr*jNc=8@(C?S(b@6*EX)h7RFv|PdCY4 zQ!h(O;ef$9^7;P%{JxxDeZGKCH;dz=qx9MN@$d9yS=(xzJM!kP&&y`EdJDIvtWVG2 zCp>SvvhIu1lXtGFnpfm|(^dJ4FZIdUIsAh8;_~DC8p=E+Vn$~jixh``)4G%tW#zy& z>$*<~h2H(}Pev$_l*EcqZjH2ZG+_#f0Isht-Y?(-VF>@U-4G@qFik)`{Zs)T6`+)VCFEuI zzXC)gVkpd!Q5DO~XvHNWmpm3+Dy1`{Y{4GWa0okwK_U#eemMSJ0Sn z5lSG7WnyA&tm6zd5B?{K$dnL9NxdKU5U7UjRvus{NIS4>giX*39OALp+gN&16{^UB zvo_P3X{{2AnUICYRQ^4ef=^)&A#(8Hd4QWB?7-0xPO7PsZRdQdha(y>c^?F}jk4sD za14co%VffRY$X~-xniae8D-piOPT-beVBJimtng-ea(o;bK*DeNMWiw_k`HPGU(af e9k1=X46qDqc|zy-clrJx`d~i*c%z7>68-?oWHq+{ literal 0 HcmV?d00001 diff --git a/test/repositories/svn_with_tree_move/db/revs/2 b/test/repositories/svn_with_tree_move/db/revs/2 new file mode 100644 index 00000000..61d2ca3e --- /dev/null +++ b/test/repositories/svn_with_tree_move/db/revs/2 @@ -0,0 +1,44 @@ +PLAIN +END +ENDREP +id: 1.0.r2/17 +type: dir +pred: 1.0.r1/625 +count: 1 +text: 2 0 4 4 2d2977d1c96f487abe4a1e202dd03b4e +cpath: /all +copyroot: 0 / + +id: 2.1.r2/141 +type: dir +pred: 2.0.r1/452 +count: 1 +text: 1 405 34 34 421576a59ace312937c26664b844a879 +cpath: /myproject +copyfrom: 1 /all/myproject + +PLAIN +K 3 +all +V 13 +dir 1.0.r2/17 +K 9 +myproject +V 14 +dir 2.1.r2/141 +END +ENDREP +id: 0.0.r2/367 +type: dir +pred: 0.0.r1/782 +count: 2 +text: 2 289 65 65 bc780155f14b1d1109add7e03a436d9f +cpath: / +copyroot: 0 / + +2.0.r1/452 delete false false /all/myproject + +2._0.t1-1 add false false /myproject +1 /all/myproject + +367 493 diff --git a/test/repositories/svn_with_tree_move/db/uuid b/test/repositories/svn_with_tree_move/db/uuid new file mode 100644 index 00000000..65ff7b93 --- /dev/null +++ b/test/repositories/svn_with_tree_move/db/uuid @@ -0,0 +1 @@ +72ad96da-afe6-45cb-97a1-ca313a930b66 diff --git a/test/repositories/svn_with_tree_move/db/write-lock b/test/repositories/svn_with_tree_move/db/write-lock new file mode 100644 index 00000000..e69de29b diff --git a/test/repositories/svn_with_tree_move/format b/test/repositories/svn_with_tree_move/format new file mode 100644 index 00000000..7ed6ff82 --- /dev/null +++ b/test/repositories/svn_with_tree_move/format @@ -0,0 +1 @@ +5 diff --git a/test/repositories/svn_with_tree_move/hooks/post-commit.tmpl b/test/repositories/svn_with_tree_move/hooks/post-commit.tmpl new file mode 100644 index 00000000..b8345c6f --- /dev/null +++ b/test/repositories/svn_with_tree_move/hooks/post-commit.tmpl @@ -0,0 +1,51 @@ +#!/bin/sh + +# POST-COMMIT HOOK +# +# The post-commit hook is invoked after a commit. Subversion runs +# this hook by invoking a program (script, executable, binary, etc.) +# named 'post-commit' (for which this file is a template) with the +# following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] REV (the number of the revision just committed) +# +# The default working directory for the invocation is undefined, so +# the program should set one explicitly if it cares. +# +# Because the commit has already completed and cannot be undone, +# the exit code of the hook program is ignored. The hook program +# can use the 'svnlook' utility to help it examine the +# newly-committed tree. +# +# On a Unix system, the normal procedure is to have 'post-commit' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'post-commit' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'post-commit.bat' or 'post-commit.exe', +# but the basic idea is the same. +# +# The hook program typically does not inherit the environment of +# its parent process. For example, a common problem is for the +# PATH environment variable to not be set to its usual value, so +# that subprograms fail to launch unless invoked via absolute path. +# If you're having unexpected problems with a hook program, the +# culprit may be unusual (or missing) environment variables. +# +# Here is an example hook script, for a Unix /bin/sh interpreter. +# For more examples and pre-written hooks, see those in +# the Subversion repository at +# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and +# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/ + + +REPOS="$1" +REV="$2" + +commit-email.pl "$REPOS" "$REV" commit-watchers@example.org +log-commit.py --repository "$REPOS" --revision "$REV" diff --git a/test/repositories/svn_with_tree_move/hooks/post-lock.tmpl b/test/repositories/svn_with_tree_move/hooks/post-lock.tmpl new file mode 100644 index 00000000..c779f11d --- /dev/null +++ b/test/repositories/svn_with_tree_move/hooks/post-lock.tmpl @@ -0,0 +1,44 @@ +#!/bin/sh + +# POST-LOCK HOOK +# +# The post-lock hook is run after a path is locked. Subversion runs +# this hook by invoking a program (script, executable, binary, etc.) +# named 'post-lock' (for which this file is a template) with the +# following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] USER (the user who created the lock) +# +# The paths that were just locked are passed to the hook via STDIN (as +# of Subversion 1.2, only one path is passed per invocation, but the +# plan is to pass all locked paths at once, so the hook program +# should be written accordingly). +# +# The default working directory for the invocation is undefined, so +# the program should set one explicitly if it cares. +# +# Because the lock has already been created and cannot be undone, +# the exit code of the hook program is ignored. The hook program +# can use the 'svnlook' utility to help it examine the +# newly-created lock. +# +# On a Unix system, the normal procedure is to have 'post-lock' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'post-lock' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'post-lock.bat' or 'post-lock.exe', +# but the basic idea is the same. +# +# Here is an example hook script, for a Unix /bin/sh interpreter: + +REPOS="$1" +USER="$2" + +# Send email to interested parties, let them know a lock was created: +mailer.py lock "$REPOS" "$USER" /path/to/mailer.conf diff --git a/test/repositories/svn_with_tree_move/hooks/post-revprop-change.tmpl b/test/repositories/svn_with_tree_move/hooks/post-revprop-change.tmpl new file mode 100644 index 00000000..2ed8b9ab --- /dev/null +++ b/test/repositories/svn_with_tree_move/hooks/post-revprop-change.tmpl @@ -0,0 +1,56 @@ +#!/bin/sh + +# POST-REVPROP-CHANGE HOOK +# +# The post-revprop-change hook is invoked after a revision property +# has been added, modified or deleted. Subversion runs this hook by +# invoking a program (script, executable, binary, etc.) named +# 'post-revprop-change' (for which this file is a template), with the +# following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] REV (the revision that was tweaked) +# [3] USER (the username of the person tweaking the property) +# [4] PROPNAME (the property that was changed) +# [5] ACTION (the property was 'A'dded, 'M'odified, or 'D'eleted) +# +# [STDIN] PROPVAL ** the old property value is passed via STDIN. +# +# Because the propchange has already completed and cannot be undone, +# the exit code of the hook program is ignored. The hook program +# can use the 'svnlook' utility to help it examine the +# new property value. +# +# On a Unix system, the normal procedure is to have 'post-revprop-change' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'post-revprop-change' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'post-revprop-change.bat' or 'post-revprop-change.exe', +# but the basic idea is the same. +# +# The hook program typically does not inherit the environment of +# its parent process. For example, a common problem is for the +# PATH environment variable to not be set to its usual value, so +# that subprograms fail to launch unless invoked via absolute path. +# If you're having unexpected problems with a hook program, the +# culprit may be unusual (or missing) environment variables. +# +# Here is an example hook script, for a Unix /bin/sh interpreter. +# For more examples and pre-written hooks, see those in +# the Subversion repository at +# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and +# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/ + + +REPOS="$1" +REV="$2" +USER="$3" +PROPNAME="$4" +ACTION="$5" + +propchange-email.pl "$REPOS" "$REV" "$USER" "$PROPNAME" watchers@example.org diff --git a/test/repositories/svn_with_tree_move/hooks/post-unlock.tmpl b/test/repositories/svn_with_tree_move/hooks/post-unlock.tmpl new file mode 100644 index 00000000..ae95c4bd --- /dev/null +++ b/test/repositories/svn_with_tree_move/hooks/post-unlock.tmpl @@ -0,0 +1,42 @@ +#!/bin/sh + +# POST-UNLOCK HOOK +# +# The post-unlock hook runs after a path is unlocked. Subversion runs +# this hook by invoking a program (script, executable, binary, etc.) +# named 'post-unlock' (for which this file is a template) with the +# following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] USER (the user who destroyed the lock) +# +# The paths that were just unlocked are passed to the hook via STDIN +# (as of Subversion 1.2, only one path is passed per invocation, but +# the plan is to pass all unlocked paths at once, so the hook program +# should be written accordingly). +# +# The default working directory for the invocation is undefined, so +# the program should set one explicitly if it cares. +# +# Because the lock has already been destroyed and cannot be undone, +# the exit code of the hook program is ignored. +# +# On a Unix system, the normal procedure is to have 'post-unlock' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'post-unlock' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'post-unlock.bat' or 'post-unlock.exe', +# but the basic idea is the same. +# +# Here is an example hook script, for a Unix /bin/sh interpreter: + +REPOS="$1" +USER="$2" + +# Send email to interested parties, let them know a lock was removed: +mailer.py unlock "$REPOS" "$USER" /path/to/mailer.conf diff --git a/test/repositories/svn_with_tree_move/hooks/pre-commit.tmpl b/test/repositories/svn_with_tree_move/hooks/pre-commit.tmpl new file mode 100644 index 00000000..7444c511 --- /dev/null +++ b/test/repositories/svn_with_tree_move/hooks/pre-commit.tmpl @@ -0,0 +1,70 @@ +#!/bin/sh + +# PRE-COMMIT HOOK +# +# The pre-commit hook is invoked before a Subversion txn is +# committed. Subversion runs this hook by invoking a program +# (script, executable, binary, etc.) named 'pre-commit' (for which +# this file is a template), with the following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] TXN-NAME (the name of the txn about to be committed) +# +# The default working directory for the invocation is undefined, so +# the program should set one explicitly if it cares. +# +# If the hook program exits with success, the txn is committed; but +# if it exits with failure (non-zero), the txn is aborted, no commit +# takes place, and STDERR is returned to the client. The hook +# program can use the 'svnlook' utility to help it examine the txn. +# +# On a Unix system, the normal procedure is to have 'pre-commit' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# *** NOTE: THE HOOK PROGRAM MUST NOT MODIFY THE TXN, EXCEPT *** +# *** FOR REVISION PROPERTIES (like svn:log or svn:author). *** +# +# This is why we recommend using the read-only 'svnlook' utility. +# In the future, Subversion may enforce the rule that pre-commit +# hooks should not modify the versioned data in txns, or else come +# up with a mechanism to make it safe to do so (by informing the +# committing client of the changes). However, right now neither +# mechanism is implemented, so hook writers just have to be careful. +# +# Note that 'pre-commit' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'pre-commit.bat' or 'pre-commit.exe', +# but the basic idea is the same. +# +# The hook program typically does not inherit the environment of +# its parent process. For example, a common problem is for the +# PATH environment variable to not be set to its usual value, so +# that subprograms fail to launch unless invoked via absolute path. +# If you're having unexpected problems with a hook program, the +# culprit may be unusual (or missing) environment variables. +# +# Here is an example hook script, for a Unix /bin/sh interpreter. +# For more examples and pre-written hooks, see those in +# the Subversion repository at +# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and +# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/ + + +REPOS="$1" +TXN="$2" + +# Make sure that the log message contains some text. +SVNLOOK=/opt/local/bin/svnlook +$SVNLOOK log -t "$TXN" "$REPOS" | \ + grep "[a-zA-Z0-9]" > /dev/null || exit 1 + +# Check that the author of this commit has the rights to perform +# the commit on the files and directories being modified. +commit-access-control.pl "$REPOS" "$TXN" commit-access-control.cfg || exit 1 + +# All checks passed, so allow the commit. +exit 0 diff --git a/test/repositories/svn_with_tree_move/hooks/pre-lock.tmpl b/test/repositories/svn_with_tree_move/hooks/pre-lock.tmpl new file mode 100644 index 00000000..020d1727 --- /dev/null +++ b/test/repositories/svn_with_tree_move/hooks/pre-lock.tmpl @@ -0,0 +1,64 @@ +#!/bin/sh + +# PRE-LOCK HOOK +# +# The pre-lock hook is invoked before an exclusive lock is +# created. Subversion runs this hook by invoking a program +# (script, executable, binary, etc.) named 'pre-lock' (for which +# this file is a template), with the following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] PATH (the path in the repository about to be locked) +# [3] USER (the user creating the lock) +# +# The default working directory for the invocation is undefined, so +# the program should set one explicitly if it cares. +# +# If the hook program exits with success, the lock is created; but +# if it exits with failure (non-zero), the lock action is aborted +# and STDERR is returned to the client. + +# On a Unix system, the normal procedure is to have 'pre-lock' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'pre-lock' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'pre-lock.bat' or 'pre-lock.exe', +# but the basic idea is the same. +# +# Here is an example hook script, for a Unix /bin/sh interpreter: + +REPOS="$1" +PATH="$2" +USER="$3" + +# If a lock exists and is owned by a different person, don't allow it +# to be stolen (e.g., with 'svn lock --force ...'). + +# (Maybe this script could send email to the lock owner?) +SVNLOOK=/opt/local/bin/svnlook +GREP=/bin/grep +SED=/bin/sed + +LOCK_OWNER=`$SVNLOOK lock "$REPOS" "$PATH" | \ + $GREP '^Owner: ' | $SED 's/Owner: //'` + +# If we get no result from svnlook, there's no lock, allow the lock to +# happen: +if [ "$LOCK_OWNER" = "" ]; then + exit 0 +fi + +# If the person locking matches the lock's owner, allow the lock to +# happen: +if [ "$LOCK_OWNER" = "$USER" ]; then + exit 0 +fi + +# Otherwise, we've got an owner mismatch, so return failure: +echo "Error: $PATH already locked by ${LOCK_OWNER}." 1>&2 +exit 1 diff --git a/test/repositories/svn_with_tree_move/hooks/pre-revprop-change.tmpl b/test/repositories/svn_with_tree_move/hooks/pre-revprop-change.tmpl new file mode 100644 index 00000000..2f2de984 --- /dev/null +++ b/test/repositories/svn_with_tree_move/hooks/pre-revprop-change.tmpl @@ -0,0 +1,66 @@ +#!/bin/sh + +# PRE-REVPROP-CHANGE HOOK +# +# The pre-revprop-change hook is invoked before a revision property +# is added, modified or deleted. Subversion runs this hook by invoking +# a program (script, executable, binary, etc.) named 'pre-revprop-change' +# (for which this file is a template), with the following ordered +# arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] REVISION (the revision being tweaked) +# [3] USER (the username of the person tweaking the property) +# [4] PROPNAME (the property being set on the revision) +# [5] ACTION (the property is being 'A'dded, 'M'odified, or 'D'eleted) +# +# [STDIN] PROPVAL ** the new property value is passed via STDIN. +# +# If the hook program exits with success, the propchange happens; but +# if it exits with failure (non-zero), the propchange doesn't happen. +# The hook program can use the 'svnlook' utility to examine the +# existing value of the revision property. +# +# WARNING: unlike other hooks, this hook MUST exist for revision +# properties to be changed. If the hook does not exist, Subversion +# will behave as if the hook were present, but failed. The reason +# for this is that revision properties are UNVERSIONED, meaning that +# a successful propchange is destructive; the old value is gone +# forever. We recommend the hook back up the old value somewhere. +# +# On a Unix system, the normal procedure is to have 'pre-revprop-change' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'pre-revprop-change' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'pre-revprop-change.bat' or 'pre-revprop-change.exe', +# but the basic idea is the same. +# +# The hook program typically does not inherit the environment of +# its parent process. For example, a common problem is for the +# PATH environment variable to not be set to its usual value, so +# that subprograms fail to launch unless invoked via absolute path. +# If you're having unexpected problems with a hook program, the +# culprit may be unusual (or missing) environment variables. +# +# Here is an example hook script, for a Unix /bin/sh interpreter. +# For more examples and pre-written hooks, see those in +# the Subversion repository at +# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and +# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/ + + +REPOS="$1" +REV="$2" +USER="$3" +PROPNAME="$4" +ACTION="$5" + +if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:log" ]; then exit 0; fi + +echo "Changing revision properties other than svn:log is prohibited" >&2 +exit 1 diff --git a/test/repositories/svn_with_tree_move/hooks/pre-unlock.tmpl b/test/repositories/svn_with_tree_move/hooks/pre-unlock.tmpl new file mode 100644 index 00000000..795f55f8 --- /dev/null +++ b/test/repositories/svn_with_tree_move/hooks/pre-unlock.tmpl @@ -0,0 +1,60 @@ +#!/bin/sh + +# PRE-UNLOCK HOOK +# +# The pre-unlock hook is invoked before an exclusive lock is +# destroyed. Subversion runs this hook by invoking a program +# (script, executable, binary, etc.) named 'pre-unlock' (for which +# this file is a template), with the following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] PATH (the path in the repository about to be unlocked) +# [3] USER (the user destroying the lock) +# +# The default working directory for the invocation is undefined, so +# the program should set one explicitly if it cares. +# +# If the hook program exits with success, the lock is destroyed; but +# if it exits with failure (non-zero), the unlock action is aborted +# and STDERR is returned to the client. + +# On a Unix system, the normal procedure is to have 'pre-unlock' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'pre-unlock' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'pre-unlock.bat' or 'pre-unlock.exe', +# but the basic idea is the same. +# +# Here is an example hook script, for a Unix /bin/sh interpreter: + +REPOS="$1" +PATH="$2" +USER="$3" + +# If a lock is owned by a different person, don't allow it be broken. +# (Maybe this script could send email to the lock owner?) + +SVNLOOK=/opt/local/bin/svnlook +GREP=/bin/grep +SED=/bin/sed + +LOCK_OWNER=`$SVNLOOK lock "$REPOS" "$PATH" | \ + $GREP '^Owner: ' | $SED 's/Owner: //'` + +# If we get no result from svnlook, there's no lock, return success: +if [ "$LOCK_OWNER" = "" ]; then + exit 0 +fi +# If the person unlocking matches the lock's owner, return success: +if [ "$LOCK_OWNER" = "$USER" ]; then + exit 0 +fi + +# Otherwise, we've got an owner mismatch, so return failure: +echo "Error: $PATH locked by ${LOCK_OWNER}." 1>&2 +exit 1 diff --git a/test/repositories/svn_with_tree_move/hooks/start-commit.tmpl b/test/repositories/svn_with_tree_move/hooks/start-commit.tmpl new file mode 100644 index 00000000..348d7063 --- /dev/null +++ b/test/repositories/svn_with_tree_move/hooks/start-commit.tmpl @@ -0,0 +1,54 @@ +#!/bin/sh + +# START-COMMIT HOOK +# +# The start-commit hook is invoked before a Subversion txn is created +# in the process of doing a commit. Subversion runs this hook +# by invoking a program (script, executable, binary, etc.) named +# 'start-commit' (for which this file is a template) +# with the following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] USER (the authenticated user attempting to commit) +# +# The default working directory for the invocation is undefined, so +# the program should set one explicitly if it cares. +# +# If the hook program exits with success, the commit continues; but +# if it exits with failure (non-zero), the commit is stopped before +# a Subversion txn is created, and STDERR is returned to the client. +# +# On a Unix system, the normal procedure is to have 'start-commit' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'start-commit' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'start-commit.bat' or 'start-commit.exe', +# but the basic idea is the same. +# +# The hook program typically does not inherit the environment of +# its parent process. For example, a common problem is for the +# PATH environment variable to not be set to its usual value, so +# that subprograms fail to launch unless invoked via absolute path. +# If you're having unexpected problems with a hook program, the +# culprit may be unusual (or missing) environment variables. +# +# Here is an example hook script, for a Unix /bin/sh interpreter. +# For more examples and pre-written hooks, see those in +# the Subversion repository at +# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and +# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/ + + +REPOS="$1" +USER="$2" + +commit-allower.pl --repository "$REPOS" --user "$USER" || exit 1 +special-auth-check.py --user "$USER" --auth-level 3 || exit 1 + +# All checks passed, so allow the commit. +exit 0 diff --git a/test/repositories/svn_with_tree_move/locks/db-logs.lock b/test/repositories/svn_with_tree_move/locks/db-logs.lock new file mode 100644 index 00000000..20dd6369 --- /dev/null +++ b/test/repositories/svn_with_tree_move/locks/db-logs.lock @@ -0,0 +1,3 @@ +This file is not used by Subversion 1.3.x or later. +However, its existence is required for compatibility with +Subversion 1.2.x or earlier. diff --git a/test/repositories/svn_with_tree_move/locks/db.lock b/test/repositories/svn_with_tree_move/locks/db.lock new file mode 100644 index 00000000..20dd6369 --- /dev/null +++ b/test/repositories/svn_with_tree_move/locks/db.lock @@ -0,0 +1,3 @@ +This file is not used by Subversion 1.3.x or later. +However, its existence is required for compatibility with +Subversion 1.2.x or earlier. diff --git a/test/unit/svn_chain_test.rb b/test/unit/svn_chain_test.rb index b43d5b37..52e593b9 100644 --- a/test/unit/svn_chain_test.rb +++ b/test/unit/svn_chain_test.rb @@ -146,7 +146,7 @@ def test_chained_each_commit # Revision 6: /trunk/goodbyeworld.c is created, but we only see activity # on /branches/development, so no commit reported. - + # Revision 7: /trunk is deleted, but again we don't see it. # Revision 8: /branches/development is moved to become the new /trunk. @@ -159,5 +159,35 @@ def test_chained_each_commit assert_equal '/helloworld.c', commits[5].diffs.first.path end + # Specifically tests this case: + # Suppose we're importing /myproject/trunk, and the log + # contains the following: + # + # A /myproject (from /all/myproject:1) + # D /all/myproject + # + # We need to make sure we detect the move here, even though + # "/myproject" is not an exact match for "/myproject/trunk". + def test_tree_move + with_svn_repository('svn_with_tree_move', '/myproject/trunk') do |svn| + assert_equal svn.url, svn.root + '/myproject/trunk' + assert_equal svn.branch_name, '/myproject/trunk' + + p = svn.parent_svn + assert_equal p.url, svn.root + '/all/myproject/trunk' + assert_equal p.branch_name, '/all/myproject/trunk' + assert_equal p.final_token, 1 + + assert_equal [1, 2], svn.commit_tokens + end + end + + def test_new_branch_name + svn = Scm::Adapters::SvnAdapter.new(:branch_name => "/trunk") + + assert_equal "/branches/b", svn.new_branch_name(Scm::Diff.new(:action => 'A', + :path => "/trunk", :from_revision => 1, :from_path => "/branches/b")) + end + end end From fe399d54edc9e871d42b4c3f80ccef4756b0dff0 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Fri, 13 Feb 2009 11:30:11 -0800 Subject: [PATCH 016/219] [FIX] Fixes ticket 9. Allow renames to the empty string. --- lib/scm/parsers/bzr_parser.rb | 9 ++++++--- test/unit/bzr_parser_test.rb | 28 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/lib/scm/parsers/bzr_parser.rb b/lib/scm/parsers/bzr_parser.rb index bedfb36b..a693be01 100644 --- a/lib/scm/parsers/bzr_parser.rb +++ b/lib/scm/parsers/bzr_parser.rb @@ -89,10 +89,13 @@ def self.parse_diffs(action, line) case action when :rename # A rename action requires two diffs: one to remove the old filename, - # another to add the new filename - before, after = line.scan(/(.+) => (.+)/).first + # another to add the new filename. + # + # Note that is possible to be renamed to the empty string! + # This happens when a subdirectory is moved to become the root. + before, after = line.scan(/(.+) => ?(.*)/).first [ Scm::Diff.new(:action => 'D', :path => before), - Scm::Diff.new(:action => 'A', :path => after )] + Scm::Diff.new(:action => 'A', :path => after || '' )] else [Scm::Diff.new(:action => action, :path => line)] end.each do |d| diff --git a/test/unit/bzr_parser_test.rb b/test/unit/bzr_parser_test.rb index 59e9060a..ebe6696d 100644 --- a/test/unit/bzr_parser_test.rb +++ b/test/unit/bzr_parser_test.rb @@ -405,5 +405,33 @@ def test_comment_that_contains_dashes assert_equal 1, commits.last.diffs.size assert_equal "helloworld.c", commits.last.diffs.first.path end + + # In this example, directory "test/" is renamed to "/". + # This shows in the log as being renamed to an empty string. + def test_directory_renamed_to_root + log = <<-SAMPLE + ------------------------------------------------------------ + revno: 220.90.1 + revision-id: info@ohloh.net-20081002201109-j4z0r2c8nsgbm2vk + parent: info@ohloh.net-20081002200737-pjao1idjcrxpk4n4 + committer: Ohloh + branch nick: subvertpy + timestamp: Thu 2008-10-02 22:11:09 +0200 + message: + Promote the test directory to the root. + renamed: + test => test-20081002184530-hz9mrr3wqq4l8qdx-1 + SAMPLE + + commits = BzrParser.parse(log) + + assert_equal 1, commits.size + assert_equal 'info@ohloh.net-20081002201109-j4z0r2c8nsgbm2vk', commits.first.token + assert_equal 2, commits.first.diffs.size + assert_equal "D", commits.first.diffs.first.action + assert_equal "test", commits.first.diffs.first.path + assert_equal "A", commits.first.diffs.last.action + assert_equal "", commits.first.diffs.last.path + end end end From f3afb0ae63fb396c9644419e27be41e677b6e605 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Fri, 13 Feb 2009 15:28:15 -0800 Subject: [PATCH 017/219] [NEW] Some quick-and-dirty memoization for Subversion performance --- lib/scm/adapters/svn/chain.rb | 27 +++++++++++++++------------ lib/scm/adapters/svn/misc.rb | 9 ++------- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/lib/scm/adapters/svn/chain.rb b/lib/scm/adapters/svn/chain.rb index 8f67b55e..b5247322 100644 --- a/lib/scm/adapters/svn/chain.rb +++ b/lib/scm/adapters/svn/chain.rb @@ -49,19 +49,22 @@ def chain # Only commits following +since+ are considered, so if the copy or rename # occured on or before +since+, then no parent will be found or returned. def parent_svn(since=0) - parent = nil - c = first_commit(since) - if c - c.diffs.each do |d| - if (b = new_branch_name(d)) - parent = SvnAdapter.new(:url => File.join(root, b), :branch_name => b, - :username => username, :password => password, - :final_token => d.from_revision).normalize - break - end - end + @parent_svn ||={} + @parent_svn[since] ||= begin + parent = nil + c = first_commit(since) + if c + c.diffs.each do |d| + if (b = new_branch_name(d)) + parent = SvnAdapter.new(:url => File.join(root, b), :branch_name => b, + :username => username, :password => password, + :final_token => d.from_revision).normalize + break + end + end + end + parent end - parent end #------------------------------------------------------------------ diff --git a/lib/scm/adapters/svn/misc.rb b/lib/scm/adapters/svn/misc.rb index b1ec20b2..a4d3f323 100644 --- a/lib/scm/adapters/svn/misc.rb +++ b/lib/scm/adapters/svn/misc.rb @@ -2,7 +2,6 @@ module Scm::Adapters class SvnAdapter < AbstractAdapter - # Converts an URL of form file://local/path to simply /local/path. def path case url @@ -58,12 +57,8 @@ def exist? end def info(path=nil, revision=final_token || 'HEAD') - if path || (revision != 'HEAD') - run "svn info -r #{revision} #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.url, path.to_s))}@#{revision}'" - else - # Cache the default info query for performance - @info ||= run "svn info -r #{revision} #{opt_auth} '#{SvnAdapter.uri_encode(self.url)}@#{revision}'" - end + @info ||= {} + @info[[path, revision]] ||= run "svn info -r #{revision} #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.url, path.to_s))}@#{revision}'" end def root From 41e13b8ef0dfd72c48af31b0ed9e3b13c05d4fc8 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 17 Feb 2009 10:47:22 -0800 Subject: [PATCH 018/219] [CHANGE] Some cleanups in preparation for merge with production --- lib/scm/adapters/svn/chain.rb | 51 ++++------------------- lib/scm/adapters/svn/commits.rb | 24 +++++++---- test/unit/svn_chain_test.rb | 74 +++++++++++++++------------------ 3 files changed, 59 insertions(+), 90 deletions(-) diff --git a/lib/scm/adapters/svn/chain.rb b/lib/scm/adapters/svn/chain.rb index b5247322..5f6435a3 100644 --- a/lib/scm/adapters/svn/chain.rb +++ b/lib/scm/adapters/svn/chain.rb @@ -23,7 +23,7 @@ class SvnAdapter < AbstractAdapter # A /trunk (from /branches/beta:100) # # A single SvnAdapter pointed at today's /trunk will only see revisions 101 - # to HEAD, because /trunk didn't even exist before revision 101. + # through HEAD, because /trunk didn't even exist before revision 101. # # To capture the prior history, we need to create *another* SvnAdapter # which points at /branches/beta, and which considers revisions from 1 to 100. @@ -35,10 +35,10 @@ class SvnAdapter < AbstractAdapter # # This behavior recurses ("chains") all the way back to revision 1. # - # It only works if the *entire branch* changes names. We don't chain when + # It only works if the *entire branch* moves. We don't chain when # subdirectories or individual files are copied. - # Returns the entire parent ancestry chain as a simple array. + # Returns the entire SvnAdapter ancestry chain as a simple array. def chain (parent_svn ? parent_svn.chain : []) << self end @@ -49,15 +49,16 @@ def chain # Only commits following +since+ are considered, so if the copy or rename # occured on or before +since+, then no parent will be found or returned. def parent_svn(since=0) - @parent_svn ||={} + @parent_svn ||={} # Poor man's memoize + @parent_svn[since] ||= begin parent = nil c = first_commit(since) if c c.diffs.each do |d| - if (b = new_branch_name(d)) + if (b = parent_branch_name(d)) parent = SvnAdapter.new(:url => File.join(root, b), :branch_name => b, - :username => username, :password => password, + :username => username, :password => password, :final_token => d.from_revision).normalize break end @@ -67,42 +68,6 @@ def parent_svn(since=0) end end - #------------------------------------------------------------------ - # Recursive or "chained" versions of the commit accessors. - # - # These methods recurse through the chain of ancestors for this - # adapter, calling the base_* method in turn for each ancestor. - #------------------------------------------------------------------ - - # Returns the count of commits following revision number 'since'. - def chained_commit_count(since=0) - (parent_svn ? parent_svn.chained_commit_count(since) : 0) + base_commit_count(since) - end - - # Returns an array of revision numbers for all commits following revision number 'since'. - def chained_commit_tokens(since=0) - (parent_svn(since) ? parent_svn.chained_commit_tokens(since) : []) + base_commit_tokens(since) - end - - # Returns an array of commits following revision number 'since'. - def chained_commits(since=0) - (parent_svn(since) ? parent_svn.chained_commits(since) : []) + base_commits(since) - end - - # Yield verbose commits following revision number 'since', one at a time. - def chained_each_commit(since=0, &block) - parent_svn.chained_each_commit(since, &block) if parent_svn - base_each_commit(since) do |commit| - block.call commit - end - end - - def chained_verbose_commit(since=0) - parent_svn(since) ? parent_svn.chained_verbose_commit(since) : base_verbose_commit(since) - end - - # Helper methods for parent_svn - def first_token(since=0) c = first_commit(since) c && c.token @@ -121,7 +86,7 @@ def next_revision_xml(since=0) # If the passed diff represents the wholesale movement of the entire # code tree from one directory to another, this method returns the name # of the previous directory. - def new_branch_name(d) + def parent_branch_name(d) if d.action == 'A' && branch_name[0, d.path.size] == d.path && d.from_path && d.from_revision d.from_path + branch_name[d.path.size..-1] end diff --git a/lib/scm/adapters/svn/commits.rb b/lib/scm/adapters/svn/commits.rb index e9566530..9170f852 100644 --- a/lib/scm/adapters/svn/commits.rb +++ b/lib/scm/adapters/svn/commits.rb @@ -20,27 +20,37 @@ class SvnAdapter < AbstractAdapter attr_accessor :final_token #------------------------------------------------------------------ - # Commit accessors are now redirected to recursive "chained" versions + # Recursive or "chained" versions of the commit accessors. + # + # These methods recurse through the chain of ancestors for this + # adapter, calling the base_* method in turn for each ancestor. #------------------------------------------------------------------ + # Returns the count of commits following revision number 'since'. def commit_count(since=0) - chained_commit_count(since) + (parent_svn ? parent_svn.commit_count(since) : 0) + base_commit_count(since) end + # Returns an array of revision numbers for all commits following revision number 'since'. def commit_tokens(since=0) - chained_commit_tokens(since) + (parent_svn(since) ? parent_svn.commit_tokens(since) : []) + base_commit_tokens(since) end + # Returns an array of commits following revision number 'since'. def commits(since=0) - chained_commits(since) + (parent_svn(since) ? parent_svn.commits(since) : []) + base_commits(since) end - def each_commit(since=0) - chained_each_commit(since) { |commit| yield commit } + # Yield verbose commits following revision number 'since', one at a time. + def each_commit(since=0, &block) + parent_svn.each_commit(since, &block) if parent_svn + base_each_commit(since) do |commit| + block.call commit + end end def verbose_commit(since=0) - chained_verbose_commit(since) + parent_svn(since) ? parent_svn.verbose_commit(since) : base_verbose_commit(since) end #------------------------------------------------------------------ diff --git a/test/unit/svn_chain_test.rb b/test/unit/svn_chain_test.rb index 52e593b9..eaaef8e7 100644 --- a/test/unit/svn_chain_test.rb +++ b/test/unit/svn_chain_test.rb @@ -55,47 +55,47 @@ def test_parent_svn def test_chained_commit_tokens with_svn_repository('svn_with_branching', '/trunk') do |svn| - assert_equal [1,2,4,5,8,9], svn.chained_commit_tokens - assert_equal [2,4,5,8,9], svn.chained_commit_tokens(1) - assert_equal [4,5,8,9], svn.chained_commit_tokens(2) - assert_equal [4,5,8,9], svn.chained_commit_tokens(3) - assert_equal [5,8,9], svn.chained_commit_tokens(4) - assert_equal [8,9], svn.chained_commit_tokens(5) - assert_equal [8,9], svn.chained_commit_tokens(6) - assert_equal [8,9], svn.chained_commit_tokens(7) - assert_equal [9], svn.chained_commit_tokens(8) - assert_equal [], svn.chained_commit_tokens(9) - assert_equal [], svn.chained_commit_tokens(10) + assert_equal [1,2,4,5,8,9], svn.commit_tokens + assert_equal [2,4,5,8,9], svn.commit_tokens(1) + assert_equal [4,5,8,9], svn.commit_tokens(2) + assert_equal [4,5,8,9], svn.commit_tokens(3) + assert_equal [5,8,9], svn.commit_tokens(4) + assert_equal [8,9], svn.commit_tokens(5) + assert_equal [8,9], svn.commit_tokens(6) + assert_equal [8,9], svn.commit_tokens(7) + assert_equal [9], svn.commit_tokens(8) + assert_equal [], svn.commit_tokens(9) + assert_equal [], svn.commit_tokens(10) end end def test_chained_commit_count with_svn_repository('svn_with_branching', '/trunk') do |svn| - assert_equal 6, svn.chained_commit_count - assert_equal 5, svn.chained_commit_count(1) - assert_equal 4, svn.chained_commit_count(2) - assert_equal 4, svn.chained_commit_count(3) - assert_equal 3, svn.chained_commit_count(4) - assert_equal 2, svn.chained_commit_count(5) - assert_equal 2, svn.chained_commit_count(6) - assert_equal 2, svn.chained_commit_count(7) - assert_equal 1, svn.chained_commit_count(8) - assert_equal 0, svn.chained_commit_count(9) + assert_equal 6, svn.commit_count + assert_equal 5, svn.commit_count(1) + assert_equal 4, svn.commit_count(2) + assert_equal 4, svn.commit_count(3) + assert_equal 3, svn.commit_count(4) + assert_equal 2, svn.commit_count(5) + assert_equal 2, svn.commit_count(6) + assert_equal 2, svn.commit_count(7) + assert_equal 1, svn.commit_count(8) + assert_equal 0, svn.commit_count(9) end end def test_chained_commits with_svn_repository('svn_with_branching', '/trunk') do |svn| - assert_equal [1,2,4,5,8,9], svn.chained_commits.collect { |c| c.token } - assert_equal [2,4,5,8,9], svn.chained_commits(1).collect { |c| c.token } - assert_equal [4,5,8,9], svn.chained_commits(2).collect { |c| c.token } - assert_equal [4,5,8,9], svn.chained_commits(3).collect { |c| c.token } - assert_equal [5,8,9], svn.chained_commits(4).collect { |c| c.token } - assert_equal [8,9], svn.chained_commits(5).collect { |c| c.token } - assert_equal [8,9], svn.chained_commits(6).collect { |c| c.token } - assert_equal [8,9], svn.chained_commits(7).collect { |c| c.token } - assert_equal [9], svn.chained_commits(8).collect { |c| c.token } - assert_equal [], svn.chained_commits(9).collect { |c| c.token } + assert_equal [1,2,4,5,8,9], svn.commits.collect { |c| c.token } + assert_equal [2,4,5,8,9], svn.commits(1).collect { |c| c.token } + assert_equal [4,5,8,9], svn.commits(2).collect { |c| c.token } + assert_equal [4,5,8,9], svn.commits(3).collect { |c| c.token } + assert_equal [5,8,9], svn.commits(4).collect { |c| c.token } + assert_equal [8,9], svn.commits(5).collect { |c| c.token } + assert_equal [8,9], svn.commits(6).collect { |c| c.token } + assert_equal [8,9], svn.commits(7).collect { |c| c.token } + assert_equal [9], svn.commits(8).collect { |c| c.token } + assert_equal [], svn.commits(9).collect { |c| c.token } end end @@ -107,13 +107,7 @@ def test_chained_commits def test_chained_each_commit commits = [] with_svn_repository('svn_with_branching', '/trunk') do |svn| - svn.chained_each_commit do |c| - commits << c - # puts "r#{c.token} #{c.message}" - c.diffs.each do |d| - # puts "\t#{d.action} #{d.path}" - end - end + svn.each_commit { |c| commits << c } end assert_equal [1,2,4,5,8,9], commits.collect { |c| c.token } @@ -182,10 +176,10 @@ def test_tree_move end end - def test_new_branch_name + def test_parent_branch_name svn = Scm::Adapters::SvnAdapter.new(:branch_name => "/trunk") - assert_equal "/branches/b", svn.new_branch_name(Scm::Diff.new(:action => 'A', + assert_equal "/branches/b", svn.parent_branch_name(Scm::Diff.new(:action => 'A', :path => "/trunk", :from_revision => 1, :from_path => "/branches/b")) end From 5d63d1205274771af2ce4cc48a4125c252a42a4d Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 17 Feb 2009 14:27:39 -0800 Subject: [PATCH 019/219] [CHANGE] Move the Subversion chaining functionality into a dedicated subclass. This preserves the original --stop-on-copy basic behavior in its own class. * This keeps the base SvnAdapter class uncomplicated. * The base SvnAdapter can still be used if desired. * I can foresee another, better Subversion importer built around svnsync that will not require chaining. --- lib/scm.rb | 1 + lib/scm/adapters/svn/cat_file.rb | 4 - lib/scm/adapters/svn/chain.rb | 95 -------------- lib/scm/adapters/svn/commits.rb | 60 ++------- lib/scm/adapters/svn_adapter.rb | 1 - lib/scm/adapters/svn_chain/cat_file.rb | 8 ++ lib/scm/adapters/svn_chain/chain.rb | 59 +++++++++ lib/scm/adapters/svn_chain/commits.rb | 37 ++++++ lib/scm/adapters/svn_chain_adapter.rb | 44 +++++++ test/test_helper.rb | 9 ++ test/unit/svn_cat_file_test.rb | 18 --- test/unit/svn_chain_cat_file_test.rb | 24 ++++ test/unit/svn_chain_commits_test.rb | 168 +++++++++++++++++++++++++ test/unit/svn_chain_test.rb | 135 +------------------- test/unit/svn_commits_test.rb | 117 ++++++----------- 15 files changed, 398 insertions(+), 382 deletions(-) delete mode 100644 lib/scm/adapters/svn/chain.rb create mode 100644 lib/scm/adapters/svn_chain/cat_file.rb create mode 100644 lib/scm/adapters/svn_chain/chain.rb create mode 100644 lib/scm/adapters/svn_chain/commits.rb create mode 100644 lib/scm/adapters/svn_chain_adapter.rb create mode 100644 test/unit/svn_chain_cat_file_test.rb create mode 100644 test/unit/svn_chain_commits_test.rb diff --git a/lib/scm.rb b/lib/scm.rb index 3089c090..8702a65e 100644 --- a/lib/scm.rb +++ b/lib/scm.rb @@ -13,6 +13,7 @@ module Scm require 'lib/scm/adapters/abstract_adapter' require 'lib/scm/adapters/cvs_adapter' require 'lib/scm/adapters/svn_adapter' +require 'lib/scm/adapters/svn_chain_adapter' require 'lib/scm/adapters/git_adapter' require 'lib/scm/adapters/hg_adapter' require 'lib/scm/adapters/bzr_adapter' diff --git a/lib/scm/adapters/svn/cat_file.rb b/lib/scm/adapters/svn/cat_file.rb index fb2a8d11..45a87398 100644 --- a/lib/scm/adapters/svn/cat_file.rb +++ b/lib/scm/adapters/svn/cat_file.rb @@ -9,10 +9,6 @@ def cat_file_parent(commit, diff) end def cat(path, revision) - parent_svn(revision) ? parent_svn.cat(path, revision) : base_cat(path, revision) - end - - def base_cat(path, revision) begin run "svn cat -r #{revision} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name.to_s, path.to_s))}@#{revision}'" rescue diff --git a/lib/scm/adapters/svn/chain.rb b/lib/scm/adapters/svn/chain.rb deleted file mode 100644 index 5f6435a3..00000000 --- a/lib/scm/adapters/svn/chain.rb +++ /dev/null @@ -1,95 +0,0 @@ -module Scm::Adapters - class SvnAdapter < AbstractAdapter - - # Some explanation is in order about "chaining." - # - # First, realize that a base SvnAdapter only tracks the history of a single - # subdirectory. If you point an adapter at /trunk, then that adapter is - # going to ignore eveything in /branches and /tags. - # - # The problem with this is that directories often get moved about. What is - # called "/trunk" today might have been in a branch directory at some point - # in the past. But since we completely ignore other directories, we never see - # that old history. - # - # Suppose for example that from revisions 1 to 100, development occured in - # /branches/beta. Then at revision 101, /trunk was created by copying - # /branches/beta, and this /trunk lives on to this day. - # - # The log for revision 101 is going to look something like this: - # - # Changed paths: - # D /branches/beta - # A /trunk (from /branches/beta:100) - # - # A single SvnAdapter pointed at today's /trunk will only see revisions 101 - # through HEAD, because /trunk didn't even exist before revision 101. - # - # To capture the prior history, we need to create *another* SvnAdapter - # which points at /branches/beta, and which considers revisions from 1 to 100. - # - # That's what chaining is: when we find that the first commit of an adapter - # indicates the wholesale renaming or copying of the entire tree from - # another location, then we generate a new SvnAdapter that points to that - # prior location, and process that SvnAdapter as well. - # - # This behavior recurses ("chains") all the way back to revision 1. - # - # It only works if the *entire branch* moves. We don't chain when - # subdirectories or individual files are copied. - - # Returns the entire SvnAdapter ancestry chain as a simple array. - def chain - (parent_svn ? parent_svn.chain : []) << self - end - - # If this adapter's branch was created by copying or renaming another branch, - # then return a new adapter that points to that prior branch. - # - # Only commits following +since+ are considered, so if the copy or rename - # occured on or before +since+, then no parent will be found or returned. - def parent_svn(since=0) - @parent_svn ||={} # Poor man's memoize - - @parent_svn[since] ||= begin - parent = nil - c = first_commit(since) - if c - c.diffs.each do |d| - if (b = parent_branch_name(d)) - parent = SvnAdapter.new(:url => File.join(root, b), :branch_name => b, - :username => username, :password => password, - :final_token => d.from_revision).normalize - break - end - end - end - parent - end - end - - def first_token(since=0) - c = first_commit(since) - c && c.token - end - - def first_commit(since=0) - Scm::Parsers::SvnXmlParser.parse(next_revision_xml(since)).first - end - - # Returns the first commit with a revision number greater than the provided revision number - def next_revision_xml(since=0) - return "" if since.to_i >= head_token - run "svn log --verbose --xml --stop-on-copy -r #{since.to_i+1}:#{final_token || 'HEAD'} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}'" - end - - # If the passed diff represents the wholesale movement of the entire - # code tree from one directory to another, this method returns the name - # of the previous directory. - def parent_branch_name(d) - if d.action == 'A' && branch_name[0, d.path.size] == d.path && d.from_path && d.from_revision - d.from_path + branch_name[d.path.size..-1] - end - end - end -end diff --git a/lib/scm/adapters/svn/commits.rb b/lib/scm/adapters/svn/commits.rb index 9170f852..29d64627 100644 --- a/lib/scm/adapters/svn/commits.rb +++ b/lib/scm/adapters/svn/commits.rb @@ -19,56 +19,15 @@ class SvnAdapter < AbstractAdapter # this adapter ever return information regarding commits after this point. attr_accessor :final_token - #------------------------------------------------------------------ - # Recursive or "chained" versions of the commit accessors. - # - # These methods recurse through the chain of ancestors for this - # adapter, calling the base_* method in turn for each ancestor. - #------------------------------------------------------------------ - # Returns the count of commits following revision number 'since'. def commit_count(since=0) - (parent_svn ? parent_svn.commit_count(since) : 0) + base_commit_count(since) - end - - # Returns an array of revision numbers for all commits following revision number 'since'. - def commit_tokens(since=0) - (parent_svn(since) ? parent_svn.commit_tokens(since) : []) + base_commit_tokens(since) - end - - # Returns an array of commits following revision number 'since'. - def commits(since=0) - (parent_svn(since) ? parent_svn.commits(since) : []) + base_commits(since) - end - - # Yield verbose commits following revision number 'since', one at a time. - def each_commit(since=0, &block) - parent_svn.each_commit(since, &block) if parent_svn - base_each_commit(since) do |commit| - block.call commit - end - end - - def verbose_commit(since=0) - parent_svn(since) ? parent_svn.verbose_commit(since) : base_verbose_commit(since) - end - - #------------------------------------------------------------------ - # Base versions of the commit accessors. - # - # These are the original, simple commit accessors that are - # unaware of branch "chaining". - #------------------------------------------------------------------ - - # Returns the count of commits following revision number 'since'. - def base_commit_count(since=0) since ||= 0 return 0 if final_token && since >= final_token run("svn log -q -r #{since.to_i + 1}:#{final_token || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{final_token || 'HEAD'}' | grep -E -e '^r[0-9]+ ' | wc -l").strip.to_i end # Returns an array of revision numbers for all commits following revision number 'since'. - def base_commit_tokens(since=0) + def commit_tokens(since=0) since ||= 0 return [] if final_token && since >= final_token cmd = "svn log -q -r #{since.to_i + 1}:#{final_token || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{final_token || 'HEAD'}' | grep -E -e '^r[0-9]+ ' | cut -f 1 -d '|' | cut -c 2-" @@ -77,7 +36,7 @@ def base_commit_tokens(since=0) # Returns an array of commits following revision number 'since'. # These commit objects do not include diffs. - def base_commits(since=0) + def commits(since=0) list = [] open_log_file(since) do |io| list = Scm::Parsers::SvnXmlParser.parse(io) @@ -93,9 +52,9 @@ def base_commits(since=0) # directories, the complexity (and time) of this method comes in expanding directories with a recursion # through every file in the directory. # - def base_each_commit(since=nil) - base_commit_tokens(since).each do |rev| - yield base_verbose_commit(rev) + def each_commit(since=nil) + commit_tokens(since).each do |rev| + yield verbose_commit(rev) end end @@ -134,12 +93,7 @@ def deepen_diff(diff, rev) # Note that if the directory was deleted, we have to look at the previous revision to see what it held. recurse_rev = (diff.action == 'D') ? rev-1 : rev - if diff.action == 'A' && diff.path == '' && rev == first_token && parent_svn - # A very special case. This is the first commit, and the entire tree is being - # copied from somewhere else. In this case, there isn't actually any change, just - # a change of branch_name. Return no diffs at all. - nil - elsif (diff.action == 'D' or diff.action == 'A') && is_directory?(diff.path, recurse_rev) + if (diff.action == 'D' or diff.action == 'A') && is_directory?(diff.path, recurse_rev) # Deleting or adding a directory. Expand it out to show every file. recurse_files(diff.path, recurse_rev).collect do |f| Scm::Diff.new(:action => diff.action, :path => File.join(diff.path, f)) @@ -178,7 +132,7 @@ def strip_path_branch(path) end end - def base_verbose_commit(rev) + def verbose_commit(rev) c = Scm::Parsers::SvnXmlParser.parse(single_revision_xml(rev)).first c.scm = self deepen_commit(strip_commit_branch(c)) diff --git a/lib/scm/adapters/svn_adapter.rb b/lib/scm/adapters/svn_adapter.rb index bd57f41b..cb2569fc 100644 --- a/lib/scm/adapters/svn_adapter.rb +++ b/lib/scm/adapters/svn_adapter.rb @@ -13,4 +13,3 @@ def english_name require 'lib/scm/adapters/svn/pull' require 'lib/scm/adapters/svn/head' require 'lib/scm/adapters/svn/misc' -require 'lib/scm/adapters/svn/chain' diff --git a/lib/scm/adapters/svn_chain/cat_file.rb b/lib/scm/adapters/svn_chain/cat_file.rb new file mode 100644 index 00000000..26657f7b --- /dev/null +++ b/lib/scm/adapters/svn_chain/cat_file.rb @@ -0,0 +1,8 @@ +module Scm::Adapters + class SvnChainAdapter < SvnAdapter + def cat(path, revision) + parent_svn(revision) ? parent_svn.cat(path, revision) : super(path, revision) + end + end +end + diff --git a/lib/scm/adapters/svn_chain/chain.rb b/lib/scm/adapters/svn_chain/chain.rb new file mode 100644 index 00000000..210add29 --- /dev/null +++ b/lib/scm/adapters/svn_chain/chain.rb @@ -0,0 +1,59 @@ +module Scm::Adapters + class SvnChainAdapter < SvnAdapter + + # Returns the entire SvnAdapter ancestry chain as a simple array. + def chain + (parent_svn ? parent_svn.chain : []) << self + end + + # If this adapter's branch was created by copying or renaming another branch, + # then return a new adapter that points to that prior branch. + # + # Only commits following +since+ are considered, so if the copy or rename + # occured on or before +since+, then no parent will be found or returned. + def parent_svn(since=0) + @parent_svn ||={} # Poor man's memoize + + @parent_svn[since] ||= begin + parent = nil + c = first_commit(since) + if c + c.diffs.each do |d| + if (b = parent_branch_name(d)) + parent = SvnChainAdapter.new( + :url => File.join(root, b), :branch_name => b, + :username => username, :password => password, + :final_token => d.from_revision).normalize + break + end + end + end + parent + end + end + + def first_token(since=0) + c = first_commit(since) + c && c.token + end + + def first_commit(since=0) + Scm::Parsers::SvnXmlParser.parse(next_revision_xml(since)).first + end + + # Returns the first commit with a revision number greater than the provided revision number + def next_revision_xml(since=0) + return "" if since.to_i >= head_token + run "svn log --verbose --xml --stop-on-copy -r #{since.to_i+1}:#{final_token || 'HEAD'} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}'" + end + + # If the passed diff represents the wholesale movement of the entire + # code tree from one directory to another, this method returns the name + # of the previous directory. + def parent_branch_name(d) + if d.action == 'A' && branch_name[0, d.path.size] == d.path && d.from_path && d.from_revision + d.from_path + branch_name[d.path.size..-1] + end + end + end +end diff --git a/lib/scm/adapters/svn_chain/commits.rb b/lib/scm/adapters/svn_chain/commits.rb new file mode 100644 index 00000000..4c9c6a2b --- /dev/null +++ b/lib/scm/adapters/svn_chain/commits.rb @@ -0,0 +1,37 @@ +module Scm::Adapters + class SvnChainAdapter < SvnAdapter + + # Returns the count of commits following revision number 'since'. + def commit_count(since=0) + (parent_svn ? parent_svn.commit_count(since) : 0) + super(since) + end + + # Returns an array of revision numbers for all commits following revision number 'since'. + def commit_tokens(since=0) + (parent_svn(since) ? parent_svn.commit_tokens(since) : []) + super(since) + end + + # Returns an array of commits following revision number 'since'. + def commits(since=0) + (parent_svn(since) ? parent_svn.commits(since) : []) + super(since) + end + + def verbose_commit(since=0) + parent_svn(since) ? parent_svn.verbose_commit(since) : super(since) + end + + # If the diff points to a file, simply returns the diff. + # If the diff points to a directory, returns an array of diffs for every file in the directory. + def deepen_diff(diff, rev) + if diff.action == 'A' && diff.path == '' && parent_svn && rev == first_token + # A very special case that is important for chaining. + # This is the first commit, and the entire tree is being created by copying from parent_svn. + # In this case, there isn't actually any change, just + # a change of branch_name. Return no diffs at all. + nil + else + super(diff, rev) + end + end + end +end diff --git a/lib/scm/adapters/svn_chain_adapter.rb b/lib/scm/adapters/svn_chain_adapter.rb new file mode 100644 index 00000000..674e6f0e --- /dev/null +++ b/lib/scm/adapters/svn_chain_adapter.rb @@ -0,0 +1,44 @@ +module Scm::Adapters + # Some explanation is in order about "chaining." + # + # First, realize that a base SvnAdapter only tracks the history of a single + # subdirectory. If you point an adapter at /trunk, then that adapter is + # going to ignore eveything in /branches and /tags. + # + # The problem with this is that directories often get moved about. What is + # called "/trunk" today might have been in a branch directory at some point + # in the past. But since we completely ignore other directories, we never see + # that old history. + # + # Suppose for example that from revisions 1 to 100, development occured in + # /branches/beta. Then at revision 101, /trunk was created by copying + # /branches/beta, and this /trunk lives on to this day. + # + # The log for revision 101 is going to look something like this: + # + # Changed paths: + # D /branches/beta + # A /trunk (from /branches/beta:100) + # + # A single SvnAdapter pointed at today's /trunk will only see revisions 101 + # through HEAD, because /trunk didn't even exist before revision 101. + # + # To capture the prior history, we need to create *another* SvnAdapter + # which points at /branches/beta, and which considers revisions from 1 to 100. + # + # That's what chaining is: when we find that the first commit of an adapter + # indicates the wholesale renaming or copying of the entire tree from + # another location, then we generate a new SvnAdapter that points to that + # prior location, and process that SvnAdapter as well. + # + # This behavior recurses ("chains") all the way back to revision 1. + # + # It only works if the *entire branch* moves. We don't chain when + # subdirectories or individual files are copied. + class SvnChainAdapter < SvnAdapter + end +end + +require 'lib/scm/adapters/svn_chain/chain' +require 'lib/scm/adapters/svn_chain/commits' +require 'lib/scm/adapters/svn_chain/cat_file' diff --git a/test/test_helper.rb b/test/test_helper.rb index c84fa243..3c8651c3 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -69,6 +69,15 @@ def with_svn_repository(name, branch_name='') end end + def with_svn_chain_repository(name, branch_name='') + with_repository(Scm::Adapters::SvnChainAdapter, name) do |svn| + svn.branch_name = branch_name + svn.url = File.join(svn.root, svn.branch_name) + svn.url = svn.url[0..-2] if svn.url[-1..-1] == '/' # Strip trailing / + yield svn + end + end + def with_cvs_repository(name) with_repository(Scm::Adapters::CvsAdapter, name) { |cvs| yield cvs } end diff --git a/test/unit/svn_cat_file_test.rb b/test/unit/svn_cat_file_test.rb index 188ad624..f7e47ea0 100644 --- a/test/unit/svn_cat_file_test.rb +++ b/test/unit/svn_cat_file_test.rb @@ -18,23 +18,5 @@ def test_cat_file assert_equal nil, svn.cat_file(Scm::Commit.new(:token => 1), Scm::Diff.new(:path => "file not found")) end end - - def test_cat_file_with_chaining -goodbye = <<-EXPECTED -#include -main() -{ - printf("Goodbye, world!\\n"); -} -EXPECTED - with_svn_repository('svn_with_branching', '/trunk') do |svn| - # The first case asks for the file on the HEAD, so it should easily be found - assert_equal goodbye, svn.cat_file(Scm::Commit.new(:token => 8), Scm::Diff.new(:path => "goodbyeworld.c")) - - # The next test asks for the file as it appeared before /branches/development was moved to /trunk, - # so this request requires traversal up the chain to the parent SvnAdapter. - assert_equal goodbye, svn.cat_file(Scm::Commit.new(:token => 5), Scm::Diff.new(:path => "goodbyeworld.c")) - end - end end end diff --git a/test/unit/svn_chain_cat_file_test.rb b/test/unit/svn_chain_cat_file_test.rb new file mode 100644 index 00000000..579397f6 --- /dev/null +++ b/test/unit/svn_chain_cat_file_test.rb @@ -0,0 +1,24 @@ +require File.dirname(__FILE__) + '/../test_helper' + +module Scm::Adapters + class SvnChainCatFileTest < Scm::Test + + def test_cat_file_with_chaining +goodbye = <<-EXPECTED +#include +main() +{ + printf("Goodbye, world!\\n"); +} +EXPECTED + with_svn_chain_repository('svn_with_branching', '/trunk') do |svn| + # The first case asks for the file on the HEAD, so it should easily be found + assert_equal goodbye, svn.cat_file(Scm::Commit.new(:token => 8), Scm::Diff.new(:path => "goodbyeworld.c")) + + # The next test asks for the file as it appeared before /branches/development was moved to /trunk, + # so this request requires traversal up the chain to the parent SvnAdapter. + assert_equal goodbye, svn.cat_file(Scm::Commit.new(:token => 5), Scm::Diff.new(:path => "goodbyeworld.c")) + end + end + end +end diff --git a/test/unit/svn_chain_commits_test.rb b/test/unit/svn_chain_commits_test.rb new file mode 100644 index 00000000..77266b26 --- /dev/null +++ b/test/unit/svn_chain_commits_test.rb @@ -0,0 +1,168 @@ +require File.dirname(__FILE__) + '/../test_helper' + +module Scm::Parsers + class SvnChainTest < Scm::Test + + def test_chained_commit_tokens + with_svn_chain_repository('svn_with_branching', '/trunk') do |svn| + assert_equal [1,2,4,5,8,9], svn.commit_tokens + assert_equal [2,4,5,8,9], svn.commit_tokens(1) + assert_equal [4,5,8,9], svn.commit_tokens(2) + assert_equal [4,5,8,9], svn.commit_tokens(3) + assert_equal [5,8,9], svn.commit_tokens(4) + assert_equal [8,9], svn.commit_tokens(5) + assert_equal [8,9], svn.commit_tokens(6) + assert_equal [8,9], svn.commit_tokens(7) + assert_equal [9], svn.commit_tokens(8) + assert_equal [], svn.commit_tokens(9) + assert_equal [], svn.commit_tokens(10) + end + end + + def test_chained_commit_count + with_svn_chain_repository('svn_with_branching', '/trunk') do |svn| + assert_equal 6, svn.commit_count + assert_equal 5, svn.commit_count(1) + assert_equal 4, svn.commit_count(2) + assert_equal 4, svn.commit_count(3) + assert_equal 3, svn.commit_count(4) + assert_equal 2, svn.commit_count(5) + assert_equal 2, svn.commit_count(6) + assert_equal 2, svn.commit_count(7) + assert_equal 1, svn.commit_count(8) + assert_equal 0, svn.commit_count(9) + end + end + + def test_chained_commits + with_svn_chain_repository('svn_with_branching', '/trunk') do |svn| + assert_equal [1,2,4,5,8,9], svn.commits.collect { |c| c.token } + assert_equal [2,4,5,8,9], svn.commits(1).collect { |c| c.token } + assert_equal [4,5,8,9], svn.commits(2).collect { |c| c.token } + assert_equal [4,5,8,9], svn.commits(3).collect { |c| c.token } + assert_equal [5,8,9], svn.commits(4).collect { |c| c.token } + assert_equal [8,9], svn.commits(5).collect { |c| c.token } + assert_equal [8,9], svn.commits(6).collect { |c| c.token } + assert_equal [8,9], svn.commits(7).collect { |c| c.token } + assert_equal [9], svn.commits(8).collect { |c| c.token } + assert_equal [], svn.commits(9).collect { |c| c.token } + end + end + + # This test is primarly concerned with the checking the diffs + # of commits. Specifically, when an entire branch is moved + # to a new name, we should not see any diffs. From our + # point of view the code is unchanged; only the base directory + # has moved. + def test_chained_each_commit + commits = [] + with_svn_chain_repository('svn_with_branching', '/trunk') do |svn| + svn.each_commit do |c| + assert c.scm # To support checkout of chained commits, the + # commit must include a link to its containing adapter. + commits << c + end + end + + assert_equal [1,2,4,5,8,9], commits.collect { |c| c.token } + + # This repository spends a lot of energy moving directories around. + # File edits actually occur in just 3 commits. + + # Revision 1: /trunk directory created, but it is empty + assert_equal 0, commits[0].diffs.size + + # Revision 2: /trunk/helloworld.c is added + assert_equal 1, commits[1].diffs.size + assert_equal 'A', commits[1].diffs.first.action + assert_equal '/helloworld.c', commits[1].diffs.first.path + + # Revision 3: /trunk is deleted. We can't see this revision. + + # Revision 4: /trunk is re-created by copying it from revision 2. + # From our point of view, there has been no change at all, and thus no diffs. + assert_equal 0, commits[2].diffs.size + + # Revision 5: /branches/development is created by copying /trunk. + # From our point of view, the contents of the repository are unchanged, so + # no diffs result from the copy. + # However, /branches/development/goodbyeworld.c is also created, so we should + # have a diff for that. + assert_equal 1, commits[3].diffs.size + assert_equal 'A', commits[3].diffs.first.action + assert_equal '/goodbyeworld.c', commits[3].diffs.first.path + + # Revision 6: /trunk/goodbyeworld.c is created, but we only see activity + # on /branches/development, so no commit reported. + + # Revision 7: /trunk is deleted, but again we don't see it. + + # Revision 8: /branches/development is moved to become the new /trunk. + # The directory contents are unchanged, so no diffs result. + assert_equal 0, commits[4].diffs.size + + # Revision 9: an edit to /trunk/helloworld.c + assert_equal 1, commits[5].diffs.size + assert_equal 'M', commits[5].diffs.first.action + assert_equal '/helloworld.c', commits[5].diffs.first.path + end + + # Specifically tests this case: + # Suppose we're importing /myproject/trunk, and the log + # contains the following: + # + # A /myproject (from /all/myproject:1) + # D /all/myproject + # + # We need to make sure we detect the move here, even though + # "/myproject" is not an exact match for "/myproject/trunk". + def test_tree_move + with_svn_chain_repository('svn_with_tree_move', '/myproject/trunk') do |svn| + assert_equal svn.url, svn.root + '/myproject/trunk' + assert_equal svn.branch_name, '/myproject/trunk' + + p = svn.parent_svn + assert_equal p.url, svn.root + '/all/myproject/trunk' + assert_equal p.branch_name, '/all/myproject/trunk' + assert_equal p.final_token, 1 + + assert_equal [1, 2], svn.commit_tokens + end + end + + def test_verbose_commit_with_chaining + with_svn_chain_repository('svn_with_branching','/trunk') do |svn| + + c = svn.verbose_commit(9) + assert_equal 'modified helloworld.c', c.message + assert_equal ['/helloworld.c'], c.diffs.collect { |d| d.path } + assert_equal '/trunk', c.scm.branch_name + + c = svn.verbose_commit(8) + assert_equal [], c.diffs + assert_equal '/trunk', c.scm.branch_name + + # Reaching these commits requires chaining + c = svn.verbose_commit(5) + assert_equal 'add a new branch, with goodbyeworld.c', c.message + assert_equal ['/goodbyeworld.c'], c.diffs.collect { |d| d.path } + assert_equal '/branches/development', c.scm.branch_name + + # Reaching these commits requires chaining twice + c = svn.verbose_commit(4) + assert_equal [], c.diffs + assert_equal '/trunk', c.scm.branch_name + + # And now a fourth chain (to skip over /trunk deletion in rev 3) + c = svn.verbose_commit(2) + assert_equal 'Added helloworld.c to trunk', c.message + assert_equal ['/helloworld.c'], c.diffs.collect { |d| d.path } + assert_equal '/trunk', c.scm.branch_name + + c = svn.verbose_commit(1) + assert_equal [], c.diffs + assert_equal '/trunk', c.scm.branch_name + end + end + end +end diff --git a/test/unit/svn_chain_test.rb b/test/unit/svn_chain_test.rb index eaaef8e7..22a74da3 100644 --- a/test/unit/svn_chain_test.rb +++ b/test/unit/svn_chain_test.rb @@ -4,7 +4,7 @@ module Scm::Parsers class SvnChainTest < Scm::Test def test_chain - with_svn_repository('svn_with_branching', '/trunk') do |svn| + with_svn_chain_repository('svn_with_branching', '/trunk') do |svn| chain = svn.chain assert_equal 4, chain.size @@ -33,12 +33,10 @@ def test_chain end def test_parent_svn - with_svn_repository('svn_with_branching', '/trunk') do |svn| + with_svn_chain_repository('svn_with_branching', '/trunk') do |svn| # In this repository, /branches/development becomes - # the /trunk in revision 8. So there should be no record - # before revision 8 in the 'traditional' base commit parser. - assert_equal [8,9], svn.base_commit_tokens - + # the /trunk in revision 8. So there should be a parent + # will final_token 7. p1 = svn.parent_svn assert_equal p1.url, svn.root + '/branches/development' assert_equal p1.branch_name, '/branches/development' @@ -53,131 +51,8 @@ def test_parent_svn end end - def test_chained_commit_tokens - with_svn_repository('svn_with_branching', '/trunk') do |svn| - assert_equal [1,2,4,5,8,9], svn.commit_tokens - assert_equal [2,4,5,8,9], svn.commit_tokens(1) - assert_equal [4,5,8,9], svn.commit_tokens(2) - assert_equal [4,5,8,9], svn.commit_tokens(3) - assert_equal [5,8,9], svn.commit_tokens(4) - assert_equal [8,9], svn.commit_tokens(5) - assert_equal [8,9], svn.commit_tokens(6) - assert_equal [8,9], svn.commit_tokens(7) - assert_equal [9], svn.commit_tokens(8) - assert_equal [], svn.commit_tokens(9) - assert_equal [], svn.commit_tokens(10) - end - end - - def test_chained_commit_count - with_svn_repository('svn_with_branching', '/trunk') do |svn| - assert_equal 6, svn.commit_count - assert_equal 5, svn.commit_count(1) - assert_equal 4, svn.commit_count(2) - assert_equal 4, svn.commit_count(3) - assert_equal 3, svn.commit_count(4) - assert_equal 2, svn.commit_count(5) - assert_equal 2, svn.commit_count(6) - assert_equal 2, svn.commit_count(7) - assert_equal 1, svn.commit_count(8) - assert_equal 0, svn.commit_count(9) - end - end - - def test_chained_commits - with_svn_repository('svn_with_branching', '/trunk') do |svn| - assert_equal [1,2,4,5,8,9], svn.commits.collect { |c| c.token } - assert_equal [2,4,5,8,9], svn.commits(1).collect { |c| c.token } - assert_equal [4,5,8,9], svn.commits(2).collect { |c| c.token } - assert_equal [4,5,8,9], svn.commits(3).collect { |c| c.token } - assert_equal [5,8,9], svn.commits(4).collect { |c| c.token } - assert_equal [8,9], svn.commits(5).collect { |c| c.token } - assert_equal [8,9], svn.commits(6).collect { |c| c.token } - assert_equal [8,9], svn.commits(7).collect { |c| c.token } - assert_equal [9], svn.commits(8).collect { |c| c.token } - assert_equal [], svn.commits(9).collect { |c| c.token } - end - end - - # This test is primarly concerned with the checking the diffs - # of commits. Specifically, when an entire branch is moved - # to a new name, we should not see any diffs. From our - # point of view the code is unchanged; only the base directory - # has moved. - def test_chained_each_commit - commits = [] - with_svn_repository('svn_with_branching', '/trunk') do |svn| - svn.each_commit { |c| commits << c } - end - - assert_equal [1,2,4,5,8,9], commits.collect { |c| c.token } - - # This repository spends a lot of energy moving directories around. - # File edits actually occur in just 3 commits. - - # Revision 1: /trunk directory created, but it is empty - assert_equal 0, commits[0].diffs.size - - # Revision 2: /trunk/helloworld.c is added - assert_equal 1, commits[1].diffs.size - assert_equal 'A', commits[1].diffs.first.action - assert_equal '/helloworld.c', commits[1].diffs.first.path - - # Revision 3: /trunk is deleted. We can't see this revision. - - # Revision 4: /trunk is re-created by copying it from revision 2. - # From our point of view, there has been no change at all, and thus no diffs. - assert_equal 0, commits[2].diffs.size - - # Revision 5: /branches/development is created by copying /trunk. - # From our point of view, the contents of the repository are unchanged, so - # no diffs result from the copy. - # However, /branches/development/goodbyeworld.c is also created, so we should - # have a diff for that. - assert_equal 1, commits[3].diffs.size - assert_equal 'A', commits[3].diffs.first.action - assert_equal '/goodbyeworld.c', commits[3].diffs.first.path - - # Revision 6: /trunk/goodbyeworld.c is created, but we only see activity - # on /branches/development, so no commit reported. - - # Revision 7: /trunk is deleted, but again we don't see it. - - # Revision 8: /branches/development is moved to become the new /trunk. - # The directory contents are unchanged, so no diffs result. - assert_equal 0, commits[4].diffs.size - - # Revision 9: an edit to /trunk/helloworld.c - assert_equal 1, commits[5].diffs.size - assert_equal 'M', commits[5].diffs.first.action - assert_equal '/helloworld.c', commits[5].diffs.first.path - end - - # Specifically tests this case: - # Suppose we're importing /myproject/trunk, and the log - # contains the following: - # - # A /myproject (from /all/myproject:1) - # D /all/myproject - # - # We need to make sure we detect the move here, even though - # "/myproject" is not an exact match for "/myproject/trunk". - def test_tree_move - with_svn_repository('svn_with_tree_move', '/myproject/trunk') do |svn| - assert_equal svn.url, svn.root + '/myproject/trunk' - assert_equal svn.branch_name, '/myproject/trunk' - - p = svn.parent_svn - assert_equal p.url, svn.root + '/all/myproject/trunk' - assert_equal p.branch_name, '/all/myproject/trunk' - assert_equal p.final_token, 1 - - assert_equal [1, 2], svn.commit_tokens - end - end - def test_parent_branch_name - svn = Scm::Adapters::SvnAdapter.new(:branch_name => "/trunk") + svn = Scm::Adapters::SvnChainAdapter.new(:branch_name => "/trunk") assert_equal "/branches/b", svn.parent_branch_name(Scm::Diff.new(:action => 'A', :path => "/trunk", :from_revision => 1, :from_path => "/branches/b")) diff --git a/test/unit/svn_commits_test.rb b/test/unit/svn_commits_test.rb index 6f051d81..ef90191f 100644 --- a/test/unit/svn_commits_test.rb +++ b/test/unit/svn_commits_test.rb @@ -121,40 +121,19 @@ def test_deep_commits # The full repository contains 4 revisions... assert_equal 4, svn.commit_count - # ..however, looking only at the history of /trunk@4 shows 3 revisions. - # - # That's because /trunk@3 was created by copying /branches/b@1 + # ...however, the current trunk contains only revisions 3 and 4. + # That's because the branch was moved to replace the trunk at revision 3. # - # I hope the following diagram helps to explain: - # - # r1 | r2 | r3 | r4 - # ----------------|----------------|---------------------|--------------- - # | | | - # /trunk(x) ------|-> deleted(x) | /--> /trunk(*) --|--> /trunk(*) - # | | / | - # /branches/b(*)--|----------------|--/ | - # | | | - # - # (*) activity we track - # (x) activity we ignore + # Even though there was a different trunk directory present in + # revisions 1 and 2, it is not visible to Ohloh. trunk = SvnAdapter.new(:url => File.join(svn.url,'trunk'), :branch_name => '/trunk').normalize - assert_equal 3, trunk.commit_count - assert_equal [1,3,4], trunk.commit_tokens - - commits = [] - trunk.each_commit { |c| commits << c } + assert_equal 2, trunk.commit_count + assert_equal [3,4], trunk.commit_tokens - # The first commit we should see is /branches/b@1. - # It should contain two files. - assert_equal 1, commits.first.token - assert_equal 2, commits.first.diffs.size # Two files seen - - assert_equal 'A', commits.first.diffs[0].action - assert_equal '/subdir/bar.rb', commits.first.diffs[0].path - assert_equal 'A', commits.first.diffs[1].action - assert_equal '/subdir/foo.rb', commits.first.diffs[1].path + deep_commits = [] + trunk.each_commit { |c| deep_commits << c } # When the branch is moved to replace the trunk in revision 3, # the Subversion log shows @@ -162,34 +141,46 @@ def test_deep_commits # D /branches/b # A /trunk (from /branches/b:2) # - # The branch_name changes at this point, but none of the file contents - # actually change. So there are no diffs to report at this point. - assert_equal 3, commits[1].token - assert_equal 0, commits[1].diffs.size + # However, there are files in those directories. Make sure the commits + # that we generate include all of those files not shown by the log. + # + # Also, our commits do not include diffs for the actual directories; + # only the files within those directories. + # + # Also, since we are only tracking the /trunk and not /branches/b, then + # there should not be anything referring to activity in /branches/b. - # In Revision 4, a subdirectory is renamed. This shows in the Subversion log as + assert_equal 3, deep_commits.first.token # Make sure this is the right revision + assert_equal 2, deep_commits.first.diffs.size # Two files seen + + assert_equal 'A', deep_commits.first.diffs[0].action + assert_equal '/subdir/bar.rb', deep_commits.first.diffs[0].path + assert_equal 'A', deep_commits.first.diffs[1].action + assert_equal '/subdir/foo.rb', deep_commits.first.diffs[1].path + + # In Revision 4, a directory is renamed. This shows in the Subversion log as # # A /trunk/newdir (from /trunk/subdir:3) # D /trunk/subdir # - # There are files in this directory, so make sure our commit includes + # Again, there are files in this directory, so make sure our commit includes # both delete and add events for all of the files in this directory, but does # not actually refer to the directories themselves. - assert_equal 4, commits.last.token + assert_equal 4, deep_commits.last.token # Make sure we're checking the right revision # There should be 2 files removed and two files added - assert_equal 4, commits.last.diffs.size + assert_equal 4, deep_commits.last.diffs.size - assert_equal 'A', commits.last.diffs[0].action - assert_equal '/newdir/bar.rb', commits.last.diffs[0].path - assert_equal 'A', commits.last.diffs[1].action - assert_equal '/newdir/foo.rb', commits.last.diffs[1].path + assert_equal 'A', deep_commits.last.diffs[0].action + assert_equal '/newdir/bar.rb', deep_commits.last.diffs[0].path + assert_equal 'A', deep_commits.last.diffs[1].action + assert_equal '/newdir/foo.rb', deep_commits.last.diffs[1].path - assert_equal 'D', commits.last.diffs[2].action - assert_equal '/subdir/bar.rb', commits.last.diffs[2].path - assert_equal 'D', commits.last.diffs[3].action - assert_equal '/subdir/foo.rb', commits.last.diffs[3].path + assert_equal 'D', deep_commits.last.diffs[2].action + assert_equal '/subdir/bar.rb', deep_commits.last.diffs[2].path + assert_equal 'D', deep_commits.last.diffs[3].action + assert_equal '/subdir/foo.rb', deep_commits.last.diffs[3].path end end @@ -209,7 +200,6 @@ def test_each_commit assert d.action.length == 1 assert d.path.length > 0 end - assert_equal svn, e.scm # Commit points back to its containing scm. end assert !FileTest.exist?(svn.log_filename) # Make sure we cleaned up after ourselves end @@ -254,40 +244,5 @@ def test_each_commit assert_equal '/trunk/COPYING', commits[4].diffs[1].path end - def test_verbose_commit_with_chaining - with_svn_repository('svn_with_branching','/trunk') do |svn| - - c = svn.verbose_commit(9) - assert_equal 'modified helloworld.c', c.message - assert_equal ['/helloworld.c'], c.diffs.collect { |d| d.path } - assert_equal '/trunk', c.scm.branch_name - - c = svn.verbose_commit(8) - assert_equal [], c.diffs - assert_equal '/trunk', c.scm.branch_name - - # Reaching these commits requires chaining - c = svn.verbose_commit(5) - assert_equal 'add a new branch, with goodbyeworld.c', c.message - assert_equal ['/goodbyeworld.c'], c.diffs.collect { |d| d.path } - assert_equal '/branches/development', c.scm.branch_name - - # Reaching these commits requires chaining twice - c = svn.verbose_commit(4) - assert_equal [], c.diffs - assert_equal '/trunk', c.scm.branch_name - - # And now a fourth chain (to skip over /trunk deletion in rev 3) - c = svn.verbose_commit(2) - assert_equal 'Added helloworld.c to trunk', c.message - assert_equal ['/helloworld.c'], c.diffs.collect { |d| d.path } - assert_equal '/trunk', c.scm.branch_name - - c = svn.verbose_commit(1) - assert_equal [], c.diffs - assert_equal '/trunk', c.scm.branch_name - end - end - end end From 165ce0cba6a9568bdc22f643022855c0880b996e Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 17 Feb 2009 14:48:45 -0800 Subject: [PATCH 020/219] [NEW] memoize SvnChainAdapter#first_commit for performance --- lib/scm/adapters/svn_chain/chain.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/scm/adapters/svn_chain/chain.rb b/lib/scm/adapters/svn_chain/chain.rb index 210add29..ea144788 100644 --- a/lib/scm/adapters/svn_chain/chain.rb +++ b/lib/scm/adapters/svn_chain/chain.rb @@ -38,7 +38,8 @@ def first_token(since=0) end def first_commit(since=0) - Scm::Parsers::SvnXmlParser.parse(next_revision_xml(since)).first + @first_commit ||={} # Poor man's memoize + @first_commit[since] ||= Scm::Parsers::SvnXmlParser.parse(next_revision_xml(since)).first end # Returns the first commit with a revision number greater than the provided revision number From 7d9ae8e72bcf8cde79b02a02cba8605ad7a29ea3 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 17 Feb 2009 15:39:48 -0800 Subject: [PATCH 021/219] [FIX] Hack -- ohloh_token is a string; cast to int in SvnAdapter.commits() --- lib/scm/adapters/svn/commits.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scm/adapters/svn/commits.rb b/lib/scm/adapters/svn/commits.rb index 29d64627..fc166ddc 100644 --- a/lib/scm/adapters/svn/commits.rb +++ b/lib/scm/adapters/svn/commits.rb @@ -38,7 +38,7 @@ def commit_tokens(since=0) # These commit objects do not include diffs. def commits(since=0) list = [] - open_log_file(since) do |io| + open_log_file(since.to_i) do |io| list = Scm::Parsers::SvnXmlParser.parse(io) end list.each { |c| c.scm = self } From 639691ec3b7833d4650976b28760e74ca6bcc5c4 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Wed, 18 Feb 2009 14:43:14 -0800 Subject: [PATCH 022/219] [FIX] String vs. Int comparison in SvnAdapter --- lib/scm/adapters/svn/commits.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/scm/adapters/svn/commits.rb b/lib/scm/adapters/svn/commits.rb index fc166ddc..1b2b3f0d 100644 --- a/lib/scm/adapters/svn/commits.rb +++ b/lib/scm/adapters/svn/commits.rb @@ -22,14 +22,14 @@ class SvnAdapter < AbstractAdapter # Returns the count of commits following revision number 'since'. def commit_count(since=0) since ||= 0 - return 0 if final_token && since >= final_token + return 0 if final_token && since.to_i >= final_token run("svn log -q -r #{since.to_i + 1}:#{final_token || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{final_token || 'HEAD'}' | grep -E -e '^r[0-9]+ ' | wc -l").strip.to_i end # Returns an array of revision numbers for all commits following revision number 'since'. def commit_tokens(since=0) since ||= 0 - return [] if final_token && since >= final_token + return [] if final_token && since.to_i >= final_token cmd = "svn log -q -r #{since.to_i + 1}:#{final_token || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{final_token || 'HEAD'}' | grep -E -e '^r[0-9]+ ' | cut -f 1 -d '|' | cut -c 2-" run(cmd).split.collect { |r| r.to_i } end From a4e674a7e74c9cabb3cd788ac394abb7b3ee210d Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Thu, 19 Feb 2009 10:53:30 -0800 Subject: [PATCH 023/219] [FIX] Enclose Bazaar revid in quotes, since it seems that revids can include bash-sensitive chars --- lib/scm/adapters/bzr/misc.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scm/adapters/bzr/misc.rb b/lib/scm/adapters/bzr/misc.rb index 856fad62..ead665ba 100644 --- a/lib/scm/adapters/bzr/misc.rb +++ b/lib/scm/adapters/bzr/misc.rb @@ -24,7 +24,7 @@ def to_rev_param(r=nil) when /^\d+$/ r else - "revid:#{r.to_s}" + "'revid:#{r.to_s}'" end end From e967b1c731ee7a3236e948a466eff18cd46eab74 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Fri, 20 Feb 2009 08:51:05 -0800 Subject: [PATCH 024/219] [FIX] remove deprecated autorequire from gem spec --- Rakefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Rakefile b/Rakefile index c6c75d15..0b49d124 100644 --- a/Rakefile +++ b/Rakefile @@ -15,7 +15,6 @@ spec = Gem::Specification.new do |s| s.summary = 'Ohloh Source Control Management Library' s.files = FileList['README', 'COPYING', '{bin,lib,test}/**/*'] s.require_path = 'lib' - s.autorequire = 'scm' s.executables = 'ohlog' s.has_rdoc = true s.extra_rdoc_files = ['README'] From 0edc2defdc5e7b3cf5616ae952e6f124bfb5ebc4 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 24 Feb 2009 12:17:49 -0800 Subject: [PATCH 025/219] [FIX] SvnAdapter: url not always == root + branch_name Fix info() and ls() to strictly use root + branch_name --- lib/scm/adapters/svn/misc.rb | 12 +++++++++--- test/unit/svn_misc_test.rb | 12 ++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/lib/scm/adapters/svn/misc.rb b/lib/scm/adapters/svn/misc.rb index a4d3f323..960055f8 100644 --- a/lib/scm/adapters/svn/misc.rb +++ b/lib/scm/adapters/svn/misc.rb @@ -32,7 +32,8 @@ def restrict_url_to_trunk return self.url unless list if list.include? 'trunk/' - self.url = self.url + '/trunk' + self.url += '/trunk' + self.branch_name += '/trunk' return restrict_url_to_trunk elsif list.size == 1 and list.first[-1..-1] == '/' self.url = self.url + '/' + list.first[0..-2] @@ -58,7 +59,12 @@ def exist? def info(path=nil, revision=final_token || 'HEAD') @info ||= {} - @info[[path, revision]] ||= run "svn info -r #{revision} #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.url, path.to_s))}@#{revision}'" + uri = if path + File.join(root, branch_name.to_s, path) + else + url + end + @info[[path, revision]] ||= run "svn info -r #{revision} #{opt_auth} '#{SvnAdapter.uri_encode(uri)}@#{revision}'" end def root @@ -76,7 +82,7 @@ def uuid # A nil result means that the call failed and the remote server could not be queried. def ls(path=nil, revision=final_token || 'HEAD') begin - stdout = run "svn ls -r #{revision} #{opt_auth} '#{SvnAdapter.uri_encode(File.join(url, path.to_s))}@#{revision}'" + stdout = run "svn ls -r #{revision} #{opt_auth} '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s, path.to_s))}@#{revision}'" rescue return nil end diff --git a/test/unit/svn_misc_test.rb b/test/unit/svn_misc_test.rb index 16bd06c5..fd476ddb 100644 --- a/test/unit/svn_misc_test.rb +++ b/test/unit/svn_misc_test.rb @@ -60,5 +60,17 @@ def test_is_directory assert !svn.is_directory?('trunk/helloworld.c') end end + + def test_restrict_url_to_trunk + with_svn_repository('svn') do |svn| + assert_equal svn.root, svn.url + assert_equal '', svn.branch_name + + svn.restrict_url_to_trunk + + assert_equal svn.root + '/trunk', svn.url + assert_equal "/trunk", svn.branch_name + end + end end end From e1814f68567f3f2b75f710394747c4552fdab174 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Thu, 26 Feb 2009 10:23:12 -0800 Subject: [PATCH 026/219] [FIX] Endless loop in SvnAdapter.restrict_url_to_trunk --- lib/scm/adapters/svn/misc.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/scm/adapters/svn/misc.rb b/lib/scm/adapters/svn/misc.rb index 960055f8..6629f50a 100644 --- a/lib/scm/adapters/svn/misc.rb +++ b/lib/scm/adapters/svn/misc.rb @@ -25,18 +25,19 @@ def hostname # (2) If the current directory is empty except for a single subdirectory, go there. # Repeat until neither rule is satisfied. # - # The url of this object will be updated with the selected location. + # The url and branch_name of this object will be updated with the selected location. # The url will be unmodified if there is a problem connecting to the server. def restrict_url_to_trunk list = ls return self.url unless list if list.include? 'trunk/' - self.url += '/trunk' - self.branch_name += '/trunk' + self.url = File.join(self.url, 'trunk') + self.branch_name = File.join(self.branch_name, 'trunk') return restrict_url_to_trunk elsif list.size == 1 and list.first[-1..-1] == '/' - self.url = self.url + '/' + list.first[0..-2] + self.url = File.join(self.url, list.first[0..-2]) + self.branch_name = File.join(self.branch_name, list.first[0..-2]) return restrict_url_to_trunk end self.url From df27837ba706f2afff896f83007466c3c02fd4bb Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 3 Mar 2009 09:57:43 -0800 Subject: [PATCH 027/219] [FIX] Escape parentheses () when they appear in Hg filenames --- lib/scm/adapters/hg/cat_file.rb | 2 +- test/unit/hg_cat_file_test.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/scm/adapters/hg/cat_file.rb b/lib/scm/adapters/hg/cat_file.rb index 6985066f..ceaa04bc 100644 --- a/lib/scm/adapters/hg/cat_file.rb +++ b/lib/scm/adapters/hg/cat_file.rb @@ -20,7 +20,7 @@ def cat(revision, path) # Example: # "Foo Bar & Baz" => "Foo\ Bar\ \&\ Baz" def escape(path) - path.gsub(/[ '"&]/) { |c| '\\' + c } + path.gsub(/[ '"&()]/) { |c| '\\' + c } end end end diff --git a/test/unit/hg_cat_file_test.rb b/test/unit/hg_cat_file_test.rb index b44a9c5f..c9f1be2c 100644 --- a/test/unit/hg_cat_file_test.rb +++ b/test/unit/hg_cat_file_test.rb @@ -31,7 +31,7 @@ def test_cat_file def test_funny_file_name_chars Scm::ScratchDir.new do |dir| # Make a file with a problematic filename - funny_name = 'file_name_&\'"' + funny_name = 'file_name (&\'")' File.open(File.join(dir, funny_name), 'w') { |f| f.write "contents" } # Add it to an hg repository From 958617bf7916ce61a4cf0eef8db4214bb6d82061 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 10 Mar 2009 15:29:52 -0700 Subject: [PATCH 028/219] [FIX] "Should" fix ticket 11. Run an `hg revert --all` before a pull to avoid merge conflicts. --- lib/scm/adapters/hg/pull.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scm/adapters/hg/pull.rb b/lib/scm/adapters/hg/pull.rb index f57b4639..b24fa83c 100644 --- a/lib/scm/adapters/hg/pull.rb +++ b/lib/scm/adapters/hg/pull.rb @@ -12,7 +12,7 @@ def pull(from, &block) run "rm -rf '#{self.url}'" run "hg clone -U '#{from.url}' '#{self.url}'" else - run "cd '#{self.url}' && hg pull -u -y '#{from.url}'" + run "cd '#{self.url}' && hg revert --all && hg pull -u -y '#{from.url}'" end yield(1,1) if block_given? # Progress bar callback From c7f28cf29fd674e22c37e7645fd8ad8a9d4ec2e6 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Mon, 16 Mar 2009 10:36:52 -0700 Subject: [PATCH 029/219] [FIX] SvnAdapter: Ensure that the branch_name is correct before calling ls() --- lib/scm/adapters/svn/validation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scm/adapters/svn/validation.rb b/lib/scm/adapters/svn/validation.rb index 347c44d9..15dabde0 100644 --- a/lib/scm/adapters/svn/validation.rb +++ b/lib/scm/adapters/svn/validation.rb @@ -33,7 +33,7 @@ def validate_server_connection @errors << [:failed, "The server did not respond to a 'svn info' command. Is the URL correct?"] elsif self.url[0..root.length-1] != root @errors << [:failed, "The URL did not match the Subversion root #{root}. Is the URL correct?"] - elsif ls.nil? + elsif recalc_branch_name && ls.nil? @errors << [:failed, "The server did not respond to a 'svn ls' command. Is the URL correct?"] end rescue From 6b568484af5fcb139d9868836aa8f2a350b4c1cf Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Fri, 20 Mar 2009 14:07:15 -0700 Subject: [PATCH 030/219] [FIX] SvnChainAdapter: It is possible for a single Subversion commit to include multiple copies/renames of a directory. When selected path for the parent_svn, choose the best (longest) path among all possible candidates. --- lib/scm/adapters/svn_chain/chain.rb | 48 ++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/lib/scm/adapters/svn_chain/chain.rb b/lib/scm/adapters/svn_chain/chain.rb index ea144788..e7b9d632 100644 --- a/lib/scm/adapters/svn_chain/chain.rb +++ b/lib/scm/adapters/svn_chain/chain.rb @@ -15,20 +15,40 @@ def parent_svn(since=0) @parent_svn ||={} # Poor man's memoize @parent_svn[since] ||= begin - parent = nil - c = first_commit(since) - if c - c.diffs.each do |d| - if (b = parent_branch_name(d)) - parent = SvnChainAdapter.new( - :url => File.join(root, b), :branch_name => b, - :username => username, :password => password, - :final_token => d.from_revision).normalize - break - end - end - end - parent + parent = nil + c = first_commit(since) + if c + # === Long explanation of real head-scratching bug fix. === + # + # It is possible for some Subversion commits to include *multiple* + # renames/copies of a source directory. For example: + # + # A /foo (from /trunk:1) + # D /foo/my_branch + # A /foo/bar (from /trunk:1) + # D /trunk + # + # If we simply processed these entries in the order given, then + # we would conclude that /foo/bar/my_branch has parent + # /trunk/bar/my_branch (because the first A matches) and exit. + # + # This is incorrect! We must look for the *longest* A that matches + # our path, and follow that one. In the example above, the correct + # parent for /foo/bar/my_branch is /trunk/my_branch. + # + # Therefore, we must sort diffs by descending filename length, so + # that we choose the longest match. + c.diffs.sort { |a,b| b.path.length <=> a.path.length }.each do |d| + if (b = parent_branch_name(d)) + parent = SvnChainAdapter.new( + :url => File.join(root, b), :branch_name => b, + :username => username, :password => password, + :final_token => d.from_revision).normalize + break + end + end + end + parent end end From eca9bfc3380586892568e0821bf5e8414827cf33 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Thu, 2 Apr 2009 11:48:06 -0700 Subject: [PATCH 031/219] [FIX] BzrAdapter: cat_file(): Fix case where filename includes a single quote --- lib/scm/adapters/bzr/cat_file.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/scm/adapters/bzr/cat_file.rb b/lib/scm/adapters/bzr/cat_file.rb index c12d7311..c3ca2ed8 100644 --- a/lib/scm/adapters/bzr/cat_file.rb +++ b/lib/scm/adapters/bzr/cat_file.rb @@ -17,8 +17,9 @@ def cat(revision, path) end # Bzr doesn't like it when the filename includes a colon + # Also, fix the case where the filename includes a single quote def escape(path) - path.gsub(/[:]/) { |c| '\\' + c } + path.gsub(/[:]/) { |c| '\\' + c }.gsub("'", "''") end end end From 6b8c0589411e3425e006ff0342dd13830dca2e3e Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Thu, 23 Apr 2009 09:35:56 -0700 Subject: [PATCH 032/219] [FIX] Svn: export should not attempt to load external references --- lib/scm/adapters/svn/misc.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scm/adapters/svn/misc.rb b/lib/scm/adapters/svn/misc.rb index 6629f50a..7fc20ac5 100644 --- a/lib/scm/adapters/svn/misc.rb +++ b/lib/scm/adapters/svn/misc.rb @@ -119,7 +119,7 @@ def checkout(rev, dest_dir) def export(dest_dir, commit_id = final_token || 'HEAD') FileUtils.mkdir_p(File.dirname(dest_dir)) unless FileTest.exist?(File.dirname(dest_dir)) - run "svn export --force -r #{commit_id} '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}' '#{dest_dir}'" + run "svn export --ignore-externals --force -r #{commit_id} '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}' '#{dest_dir}'" end def ls_tree(token) From 6e419a16d50c153e7f6a9dd7ae3d9fef0713e5d4 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Thu, 23 Apr 2009 09:53:10 -0700 Subject: [PATCH 033/219] [NEW] Hg: Implement export --- lib/scm/adapters/hg/misc.rb | 8 +++++++- test/unit/hg_misc_test.rb | 9 +++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/scm/adapters/hg/misc.rb b/lib/scm/adapters/hg/misc.rb index 0542df7a..f2091f27 100644 --- a/lib/scm/adapters/hg/misc.rb +++ b/lib/scm/adapters/hg/misc.rb @@ -10,7 +10,13 @@ def exist? end def ls_tree(token) - run("cd #{path} && hg manifest -r #{token}").split("\n") + run("cd '#{path}' && hg manifest -r #{token}").split("\n") + end + + def export(dest_dir, token='tip') + run("cd '#{path}' && hg archive -r #{token} '#{dest_dir}'") + # Hg leaves a little cookie crumb in the export directory. Remove it. + File.delete(File.join(dest_dir, '.hg_archival.txt')) if File.exist?(File.join(dest_dir, '.hg_archival.txt')) end end end diff --git a/test/unit/hg_misc_test.rb b/test/unit/hg_misc_test.rb index 49e1b885..ce436a5e 100644 --- a/test/unit/hg_misc_test.rb +++ b/test/unit/hg_misc_test.rb @@ -18,5 +18,14 @@ def test_ls_tree end end + def test_export + with_hg_repository('hg') do |hg| + Scm::ScratchDir.new do |dir| + hg.export(dir) + assert_equal ['.', '..', 'README', 'makefile'], Dir.entries(dir).sort + end + end + end + end end From 0f25bca3d27c253af7efce12e9c5011443ec3653 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Thu, 23 Apr 2009 10:06:26 -0700 Subject: [PATCH 034/219] [NEW] Bzr: Implement export --- lib/scm/adapters/bzr/misc.rb | 9 +++++++++ test/unit/bzr_misc_test.rb | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/lib/scm/adapters/bzr/misc.rb b/lib/scm/adapters/bzr/misc.rb index ead665ba..38312098 100644 --- a/lib/scm/adapters/bzr/misc.rb +++ b/lib/scm/adapters/bzr/misc.rb @@ -31,5 +31,14 @@ def to_rev_param(r=nil) def is_merge_commit?(commit) parent_tokens(commit).size > 1 end + + def export(dest_dir, token=head_token) + # Unlike other SCMs, Bzr doesn't simply place the contents into dest_dir. + # It actually *creates* dest_dir. Since it should already exist at this point, + # first we have to delete it. + Dir.delete(dest_dir) if File.exist?(dest_dir) + + run "cd '#{url}' && bzr export --format=dir -r #{to_rev_param(token)} '#{dest_dir}'" + end end end diff --git a/test/unit/bzr_misc_test.rb b/test/unit/bzr_misc_test.rb index 14f87d8d..a1d4c3a4 100644 --- a/test/unit/bzr_misc_test.rb +++ b/test/unit/bzr_misc_test.rb @@ -22,5 +22,14 @@ def test_ls_tree end end + def test_export + with_bzr_repository('bzr') do |bzr| + Scm::ScratchDir.new do |dir| + bzr.export(dir) + assert_equal ['.', '..', 'file1.txt', 'file3.txt', 'file4.txt', 'file5.txt'], Dir.entries(dir).sort + end + end + end + end end From c4f026ee202bfec10c483903d693a3c33d4e90b4 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Wed, 13 May 2009 09:37:37 -0700 Subject: [PATCH 035/219] [NEW] GitParser can parse a generic git log (that is, doesn't require our custom formatter). Note that this parser cannot be used with Ohloh because it does not emit the SHA1 hash of modified blobs. --- bin/ohlog | 7 ++++ lib/scm.rb | 1 + lib/scm/parsers/git_parser.rb | 67 +++++++++++++++++++++++++++++++++++ test/unit/git_parser_test.rb | 59 ++++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+) create mode 100644 lib/scm/parsers/git_parser.rb create mode 100644 test/unit/git_parser_test.rb diff --git a/bin/ohlog b/bin/ohlog index d46b7a52..311530b9 100755 --- a/bin/ohlog +++ b/bin/ohlog @@ -26,6 +26,7 @@ Ohloh source control log parser [option] can be one of the following: --cvs Parse a CVS rlog + --git Parse a Git log (generated with or without --name-status option) --svn Parse a Subversion log --svn-xml Parse a Subversion XML log --hg Parse a Mercurial log @@ -56,6 +57,10 @@ HELP parse CvsParser end + def git + parse GitParser + end + def svn parse SvnParser end @@ -101,6 +106,8 @@ HELP case option when '--cvs' self.subcommand = :cvs + when '--git' + self.subcommand = :git when '--svn' self.subcommand = :svn when '--svn-xml' diff --git a/lib/scm.rb b/lib/scm.rb index 8702a65e..c89c6487 100644 --- a/lib/scm.rb +++ b/lib/scm.rb @@ -24,6 +24,7 @@ module Scm require 'lib/scm/parsers/cvs_parser' require 'lib/scm/parsers/svn_parser' require 'lib/scm/parsers/svn_xml_parser' +require 'lib/scm/parsers/git_parser' require 'lib/scm/parsers/git_styled_parser' require 'lib/scm/parsers/hg_parser' require 'lib/scm/parsers/hg_styled_parser' diff --git a/lib/scm/parsers/git_parser.rb b/lib/scm/parsers/git_parser.rb new file mode 100644 index 00000000..14269e91 --- /dev/null +++ b/lib/scm/parsers/git_parser.rb @@ -0,0 +1,67 @@ +module Scm::Parsers + class GitParser < Parser + def self.scm + 'git' + end + + ANONYMOUS = "(no author)" unless defined?(ANONYMOUS) + + def self.internal_parse(io, opts) + e = nil + state = :key_values + + io.each do |line| + line.chomp! + + # Kind of a hack: the diffs section is not always present. + # Also, we don't know when the next commit is going to begin, + # so we may need to make an unexpected state change. + if line =~ /^commit ([a-z0-9]{40,40})$/ + state = :key_values + elsif state == :message and line =~ /^[ADM]\s+(.+)$/ + state = :diffs + end + + if state == :key_values + case line + when /^commit ([a-z0-9]{40,40})$/ + sha1 = $1 + yield e if e + e = Scm::Commit.new + e.diffs = [] + e.token = sha1 + e.author_name = ANONYMOUS + when /^Author: (.+) <(.*)>$/ + # In the rare case that the Git repository does not contain any names (see OpenEmbedded for example) + # we use the email instead. + e.author_name = $1 || $2 + e.author_email = $2 + when /^Date: (.*)$/ + e.author_date = Time.parse($1).utc # Note strongly: MUST be RFC2822 format to parse properly + state = :message + end + + elsif state == :message + case line + when / (.*)/ + if e.message + e.message << "\n" << $1 + else + e.message = $1 + end + end + + elsif state == :diffs + if line =~ /^([ADM])\t(.+)$/ + e.diffs << Scm::Diff.new( :action => $1, :path => $2) + end + + else + raise RuntimeError("Unknown parser state #{state.to_s}") + end + end + + yield e if e + end + end +end diff --git a/test/unit/git_parser_test.rb b/test/unit/git_parser_test.rb new file mode 100644 index 00000000..68370a55 --- /dev/null +++ b/test/unit/git_parser_test.rb @@ -0,0 +1,59 @@ +require File.dirname(__FILE__) + '/../test_helper' + +module Scm::Parsers + class GitParserTest < Scm::Test + + def test_empty_array + assert_equal([], GitParser.parse('')) + end + + def test_log_parser_default +sample_log = < +Date: Fri Jul 14 16:07:15 2006 -0700 + + moving COPYING + +A COPYING + +commit 2e9366dd7a786fdb35f211fff1c8ea05c51968b1 +Author: Robin Luckey +Date: Sun Jun 11 11:34:17 2006 -0700 + + added some documentation and licensing info + +M README +D helloworld.c +SAMPLE + + commits = GitParser.parse(sample_log) + + assert commits + assert_equal 2, commits.size + + assert_equal '1df547800dcd168e589bb9b26b4039bff3a7f7e4', commits[0].token + assert_equal 'Jason Allen', commits[0].author_name + assert_equal 'jason@ohloh.net', commits[0].author_email + assert_equal "moving COPYING", commits[0].message + assert_equal Time.utc(2006,7,14,23,7,15), commits[0].author_date + assert_equal 1, commits[0].diffs.size + + assert_equal "A", commits[0].diffs[0].action + assert_equal "COPYING", commits[0].diffs[0].path + + assert_equal '2e9366dd7a786fdb35f211fff1c8ea05c51968b1', commits[1].token + assert_equal 'Robin Luckey', commits[1].author_name + assert_equal 'robin@ohloh.net', commits[1].author_email + assert_equal "added some documentation and licensing info", commits[1].message # Note \n at end of comment + assert_equal Time.utc(2006,6,11,18,34,17), commits[1].author_date + assert_equal 2, commits[1].diffs.size + + assert_equal "M", commits[1].diffs[0].action + assert_equal "README", commits[1].diffs[0].path + assert_equal "D", commits[1].diffs[1].action + assert_equal "helloworld.c", commits[1].diffs[1].path + end + + end +end From 00854a97dc921bded525b555ba321e8d4725589b Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Wed, 13 May 2009 10:26:59 -0700 Subject: [PATCH 036/219] [FIX] Git: Prevent merge commits from being duplicated. This is sort of a hack, caused by using git-whatchanged to generate our git logs. Long-term, we should try to get away from git-whatchanged, but I couldn't find a combination of options to git-log that would provide the needed blob SHA1s for all of the changed files. --- lib/scm/adapters/git/commits.rb | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/scm/adapters/git/commits.rb b/lib/scm/adapters/git/commits.rb index f7628696..96a645a0 100644 --- a/lib/scm/adapters/git/commits.rb +++ b/lib/scm/adapters/git/commits.rb @@ -20,11 +20,28 @@ def commits(since=nil) result end - # Yields each commit following the commit with SHA1 'since'. + # Yields each commit in the repository following the commit with SHA1 'since'. # These commits are populated with diffs. def each_commit(since=nil) + + # Bug fix (hack) follows. + # + # git-whatchanged emits a merge commit multiple times, once for each parent, giving the + # delta to each parent in turn. + # + # This causes us to emit too many commits, with repeated merge commits. + # + # To fix this, we track the previous commit, and emit a new commit only if it is distinct + # from the previous. + # + # This means that the diffs for a merge commit yielded by this method will be the diffs + # vs. the first parent only, and diffs vs. other parents are lost. For Ohloh, this is fine + # because Ohloh ignores merge diffs anyway. + + previous = nil Scm::Parsers::GitStyledParser.parse(log(since)) do |e| - yield e + yield e unless previous && previous.token == e.token + previous = e end end From e00bde3c5e4bcddafdbfec9be50b83403500a913 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Wed, 13 May 2009 11:08:54 -0700 Subject: [PATCH 037/219] [CHANGE] Svn: Relax validation rules for usernames to allow email addresses. --- lib/scm/adapters/svn/validation.rb | 8 ++++++++ test/unit/svn_validation_test.rb | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/lib/scm/adapters/svn/validation.rb b/lib/scm/adapters/svn/validation.rb index 15dabde0..e31d2683 100644 --- a/lib/scm/adapters/svn/validation.rb +++ b/lib/scm/adapters/svn/validation.rb @@ -16,6 +16,14 @@ def normalize self end + # Subversion usernames have been relaxed from the abstract rules. We allow email names as usernames. + def validate_username + return nil unless @username + return nil if @username.length == 0 + return [:username, "The username must not be longer than 32 characters."] unless @username.length <= 32 + return [:username, "The username contains illegal characters."] unless @username =~ /^\w[\w@\.\+\-]*$/ + end + # If the URL is a simple directory path, make sure it is prefixed by file:// def path_to_file_url(path) url =~ /:\/\// ? url : 'file://' + File.expand_path(path) diff --git a/test/unit/svn_validation_test.rb b/test/unit/svn_validation_test.rb index 6eb07b2d..bb562f65 100644 --- a/test/unit/svn_validation_test.rb +++ b/test/unit/svn_validation_test.rb @@ -2,6 +2,12 @@ module Scm::Adapters class SvnValidationTest < Scm::Test + def test_valid_usernames + [nil,'','joe_36','a'*32,'robin@ohloh.net'].each do |username| + assert !SvnAdapter.new(:username => username).validate_username + end + end + def test_rejected_urls [ nil, "", "foo", "http:/", "http:://", "http://", "sourceforge.net/svn/project/trunk", # missing a protocol prefix From 06b336deb5ceb6c4337ec1f98e1bd2cab2d24e9d Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 19 May 2009 14:26:27 -0700 Subject: [PATCH 038/219] [FIX] Svn: Improve guess_forge() to better recognize rubyforge.org --- lib/scm/adapters/svn/validation.rb | 2 +- test/unit/svn_validation_test.rb | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/scm/adapters/svn/validation.rb b/lib/scm/adapters/svn/validation.rb index e31d2683..382366cf 100644 --- a/lib/scm/adapters/svn/validation.rb +++ b/lib/scm/adapters/svn/validation.rb @@ -62,7 +62,7 @@ def guess_forge u = @url =~ /:\/\/(.*\.?svn\.)?([^\/^:]+)(:\d+)?\// ? $2 : nil case u when /(googlecode\.com$)/, /(tigris\.org$)/, /(sunsource\.net$)/, /(java\.net$)/, - /(openoffice\.org$)/, /(netbeans\.org$)/, /(dev2dev\.bea\.com$)/ + /(openoffice\.org$)/, /(netbeans\.org$)/, /(dev2dev\.bea\.com$)/, /(rubyforge\.org$)/ $1 else u diff --git a/test/unit/svn_validation_test.rb b/test/unit/svn_validation_test.rb index bb562f65..8baef357 100644 --- a/test/unit/svn_validation_test.rb +++ b/test/unit/svn_validation_test.rb @@ -73,6 +73,9 @@ def test_guess_forge svn = SvnAdapter.new(:url => 'svn://rubyforge.org:3960//var/svn/rubyomf2097') assert_equal 'rubyforge.org', svn.guess_forge + svn = SvnAdapter.new(:url => 'http://bivouac.rubyforge.org/svn/trunk') + assert_equal 'rubyforge.org', svn.guess_forge + svn = SvnAdapter.new(:url => 'https://svn.sourceforge.net/svnroot/typo3/CoreDocs/trunk') assert_equal 'sourceforge.net', svn.guess_forge From 59bafdad60970d85c620d54b1d19016a1a817355 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 19 May 2009 15:52:59 -0700 Subject: [PATCH 039/219] [FIX] Hg and Git: better SourceForge detection in guess_forge() --- lib/scm/adapters/cvs/validation.rb | 2 +- lib/scm/adapters/git/validation.rb | 10 ++++++++++ lib/scm/adapters/hg/validation.rb | 10 ++++++++++ test/unit/cvs_validation_test.rb | 6 ++++++ test/unit/git_validation_test.rb | 3 +++ test/unit/hg_validation_test.rb | 6 ++++++ 6 files changed, 36 insertions(+), 1 deletion(-) diff --git a/lib/scm/adapters/cvs/validation.rb b/lib/scm/adapters/cvs/validation.rb index 3cd8ff8d..97a82751 100644 --- a/lib/scm/adapters/cvs/validation.rb +++ b/lib/scm/adapters/cvs/validation.rb @@ -71,7 +71,7 @@ def validate_server_connection # Based on the URL, take a guess about which forge this code is hosted on. def guess_forge - @url =~ /.*pserver.*@(([^\.]+\.)?cvs\.)?(dev\.)?([^:]+):\//i ? $4.downcase : nil + @url =~ /.*pserver.*@(([^\.]+\.)?(cvs|dev)\.)?([^:]+):\//i ? $4.downcase : nil end end end diff --git a/lib/scm/adapters/git/validation.rb b/lib/scm/adapters/git/validation.rb index ef5cc60b..b3607b69 100644 --- a/lib/scm/adapters/git/validation.rb +++ b/lib/scm/adapters/git/validation.rb @@ -18,5 +18,15 @@ def validate_server_connection return unless valid? @errors << [:failed, "The server did not respond to the 'git-ls-remote' command. Is the URL correct?"] unless self.exists? end + + def guess_forge + u = @url =~ /:\/\/(.*\.?git\.)?([^\/^:]+)(:\d+)?\// ? $2 : nil + case u + when /(sourceforge\.net$)/ + $1 + else + u + end + end end end diff --git a/lib/scm/adapters/hg/validation.rb b/lib/scm/adapters/hg/validation.rb index bfeb90fa..e2895474 100644 --- a/lib/scm/adapters/hg/validation.rb +++ b/lib/scm/adapters/hg/validation.rb @@ -12,5 +12,15 @@ def validate_server_connection return unless valid? @errors << [:failed, "The server did not respond to the 'hg id' command. Is the URL correct?"] unless self.exist? end + + def guess_forge + u = @url =~ /:\/\/(.*\.?hg\.)?([^\/^:]+)(:\d+)?\// ? $2 : nil + case u + when /(sourceforge\.net$)/ + $1 + else + u + end + end end end diff --git a/test/unit/cvs_validation_test.rb b/test/unit/cvs_validation_test.rb index c3fe9bc9..a50e016e 100644 --- a/test/unit/cvs_validation_test.rb +++ b/test/unit/cvs_validation_test.rb @@ -130,11 +130,17 @@ def test_guess_forge cvs = CvsAdapter.new(:url => "garbage_in_garbage_out") assert_equal nil, cvs.guess_forge + cvs = CvsAdapter.new(:url => ':pserver:anonymous:@boost.cvs.sourceforge.net:/cvsroot/boost') + assert_equal 'sourceforge.net', cvs.guess_forge + cvs = CvsAdapter.new(:url => ':pserver:guest:@cvs.dev.java.net:/cvs') assert_equal 'java.net', cvs.guess_forge cvs = CvsAdapter.new(:url => ":PSERVER:ANONCVS:@CVS.DEV.JAVA.NET:/cvs") assert_equal 'java.net', cvs.guess_forge + + cvs = CvsAdapter.new(:url => ":pserver:guest:@colorchooser.dev.java.net:/cvs") + assert_equal 'java.net', cvs.guess_forge end end end diff --git a/test/unit/git_validation_test.rb b/test/unit/git_validation_test.rb index a404675c..f30f0202 100644 --- a/test/unit/git_validation_test.rb +++ b/test/unit/git_validation_test.rb @@ -34,6 +34,9 @@ def test_guess_forge git = GitAdapter.new(:url => nil) assert_equal nil, git.guess_forge + git = GitAdapter.new(:url => 'git://methabot.git.sourceforge.net/gitroot/methabot') + assert_equal 'sourceforge.net', git.guess_forge + git = GitAdapter.new( :url => 'http://kernel.org/pub/scm/linux/kernel/git/stable/linux-2.6.17.y.git') assert_equal 'kernel.org', git.guess_forge end diff --git a/test/unit/hg_validation_test.rb b/test/unit/hg_validation_test.rb index 212b441f..f0385afc 100644 --- a/test/unit/hg_validation_test.rb +++ b/test/unit/hg_validation_test.rb @@ -49,6 +49,12 @@ def test_guess_forge hg = HgAdapter.new( :url => 'http://www.selenic.com/repo/hello') assert_equal 'www.selenic.com', hg.guess_forge + + hg = HgAdapter.new( :url => 'http://algoc.hg.sourceforge.net:8000/hgroot/algoc') + assert_equal 'sourceforge.net', hg.guess_forge + + hg = HgAdapter.new( :url => 'http://poliqarp.sourceforge.net/hg/poliqarp/') + assert_equal 'sourceforge.net', hg.guess_forge end end end From d40ab0b092fe17b7ae9585df42ade996b0706534 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Wed, 20 May 2009 18:40:14 -0700 Subject: [PATCH 040/219] [FIX] Svn: Fix a complicated directory renaming case: If a directory is renamed, and then the branch we are tracking is created within that directory *during the same commit*, then the parser would mistakenly think that the branch had been moved. --- lib/scm/adapters/svn_chain/chain.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/lib/scm/adapters/svn_chain/chain.rb b/lib/scm/adapters/svn_chain/chain.rb index e7b9d632..d0662037 100644 --- a/lib/scm/adapters/svn_chain/chain.rb +++ b/lib/scm/adapters/svn_chain/chain.rb @@ -39,6 +39,19 @@ def parent_svn(since=0) # Therefore, we must sort diffs by descending filename length, so # that we choose the longest match. c.diffs.sort { |a,b| b.path.length <=> a.path.length }.each do |d| + + # If this diff actually creates this branch, then a parent is impossible. + # Stop looking for parents. + # + # This check exists because of the following complicated commit: + # http://dendro.cornell.edu/svn/corina/branches/databasing/src/edu/cornell/dendro@813 + # It's long to explain, but basically a directory is renamed and + # then our branch is created within it, all in a single commit. + # Without this check, our code mistakenly thinks there is a parent. + if diff_creates_branch(d) + return nil + end + if (b = parent_branch_name(d)) parent = SvnChainAdapter.new( :url => File.join(root, b), :branch_name => b, @@ -46,6 +59,7 @@ def parent_svn(since=0) :final_token => d.from_revision).normalize break end + end end parent @@ -76,5 +90,11 @@ def parent_branch_name(d) d.from_path + branch_name[d.path.size..-1] end end + + # True if the passed diff represents the initial creation of the + # branch -- not a move or copy from somewhere else. + def diff_creates_branch(d) + d.action == 'A' && branch_name[0, d.path.size] == d.path && !d.from_path + end end end From 148f7424acc601c6bae6bc9a95555a5a092065e8 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Fri, 12 Jun 2009 15:37:47 -0700 Subject: [PATCH 041/219] [CHANGE] Svn: Increase the maximum length of a branch_name to 80 characters --- lib/scm/adapters/abstract/validation.rb | 2 +- test/unit/abstract_adapter_test.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/scm/adapters/abstract/validation.rb b/lib/scm/adapters/abstract/validation.rb index aa3b3c36..15f7f3d6 100644 --- a/lib/scm/adapters/abstract/validation.rb +++ b/lib/scm/adapters/abstract/validation.rb @@ -30,7 +30,7 @@ def validate_url def validate_branch_name return nil if @branch_name.to_s == '' - return [:branch_name, "The branch name must not be longer than 50 characters."] unless @branch_name.length <= 50 + return [:branch_name, "The branch name must not be longer than 80 characters."] unless @branch_name.length <= 80 return [:branch_name, "The branch name may contain only letters, numbers, spaces, and the special characters '_', '-', '+', '/', '^', and '.'"] unless @branch_name =~ /^[A-Za-z0-9_^\-\+\.\/\ ]+$/ end diff --git a/test/unit/abstract_adapter_test.rb b/test/unit/abstract_adapter_test.rb index b6372558..a8440fa4 100644 --- a/test/unit/abstract_adapter_test.rb +++ b/test/unit/abstract_adapter_test.rb @@ -49,13 +49,13 @@ def test_valid_passwords end def test_invalid_branch_names - ['%','a'*51].each do |branch_name| + ['%','a'*81].each do |branch_name| assert AbstractAdapter.new(:branch_name => branch_name).validate_branch_name.any? end end def test_valid_branch_names - [nil,'','/trunk','_','a'*50].each do |branch_name| + [nil,'','/trunk','_','a'*80].each do |branch_name| assert !AbstractAdapter.new(:branch_name => branch_name).validate_branch_name end end From d600daa8e7091c7a7c9020d7708feb0a853b760b Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 7 Jul 2009 10:20:51 -0700 Subject: [PATCH 042/219] [FIX] HgAdapter: Speed improvement for cat_file_parent(). New implementation requires only 2 shell commands (rather than 3). --- lib/scm/adapters/hg/cat_file.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/scm/adapters/hg/cat_file.rb b/lib/scm/adapters/hg/cat_file.rb index ceaa04bc..aa20ff8a 100644 --- a/lib/scm/adapters/hg/cat_file.rb +++ b/lib/scm/adapters/hg/cat_file.rb @@ -5,8 +5,8 @@ def cat_file(commit, diff) end def cat_file_parent(commit, diff) - p = parents(commit) - cat(p.first.token, diff.path) if p.first + p = parent_tokens(commit) + cat(p.first, diff.path) if p.first end def cat(revision, path) From f42e73c33a1daf1c31b85bc80a825cffd652e14b Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Fri, 7 Aug 2009 10:05:49 -0700 Subject: [PATCH 043/219] [FIX] BzrAdapter: Support bzr 1.17 Add the --include-merges flag to the `bzr log` command. Old bzr 1.12 included merges by default; the upgrade requires the flag. --- lib/scm/adapters/bzr/commits.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scm/adapters/bzr/commits.rb b/lib/scm/adapters/bzr/commits.rb index 1511d754..fb70574f 100644 --- a/lib/scm/adapters/bzr/commits.rb +++ b/lib/scm/adapters/bzr/commits.rb @@ -92,7 +92,7 @@ def log_filename end def rev_list_command(since=nil) - "cd '#{self.url}' && bzr log --long --show-id --forward -r #{to_rev_param(since)}.." + "cd '#{self.url}' && bzr log --long --show-id --forward --include-merges -r #{to_rev_param(since)}.." end end end From 44f57851c5ae2a8adba7bc4f48ab0da99ab1ac45 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 11 Aug 2009 12:10:22 -0700 Subject: [PATCH 044/219] [FIX] BzrAdapter: rename + modify in single commit It is possible for Bzr to report that a file has been renamed and then modified in a single commit. This breaks Ohloh, because a 'modify' action triggers a comparison between the old and new files -- but since this file has also been renamed, the old file does not exist (at least not where Ohloh expects it). We adapt the Bazaar system to what Ohloh expects: A rename becomes a simple delete and add, and any subsequent modification is ignored. --- lib/scm/parsers/bzr_parser.rb | 14 ++++++++------ test/unit/bzr_parser_test.rb | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/lib/scm/parsers/bzr_parser.rb b/lib/scm/parsers/bzr_parser.rb index a693be01..739bbc61 100644 --- a/lib/scm/parsers/bzr_parser.rb +++ b/lib/scm/parsers/bzr_parser.rb @@ -107,13 +107,15 @@ def self.strip_trailing_asterisk(path) path[-1..-1] == '*' ? path[0..-2] : path end - # Bazaar may report that a file was both deleted, added, and/or modified all - # in a single commit. - # - # All such cases mean that the path in question still exists, and that some - # kind of modification occured, so we reduce all such multiple cases to - # a single diff with an 'M' action. def self.remove_dupes(diffs) + # Bazaar may report that a file was added and modified in a single commit. + # Reduce these cases to a single 'A' action. + diffs.delete_if do |d| + d.action == 'M' && diffs.select { |x| x.path == d.path && x.action == 'A' }.any? + end + + # Bazaar may report that a file was both deleted and added in a single commit. + # Reduce these cases to a single 'M' action. diffs.each do |d| d.action = 'M' if diffs.select { |x| x.path == d.path }.size > 1 end.uniq diff --git a/test/unit/bzr_parser_test.rb b/test/unit/bzr_parser_test.rb index ebe6696d..19bef084 100644 --- a/test/unit/bzr_parser_test.rb +++ b/test/unit/bzr_parser_test.rb @@ -433,5 +433,30 @@ def test_directory_renamed_to_root assert_equal "A", commits.first.diffs.last.action assert_equal "", commits.first.diffs.last.path end + + # It is possible for Bzr to report a file as both renamed and modified + # in the same commit. We should treat this as only a rename -- that is, we + # should see a simple DELETE from the old location and an ADD to the new location. + def test_rename_and_modify_in_one_commit + log = <<-SAMPLE +------------------------------------------------------------ +revno: 1 +message: + Changed the directory structure +renamed: + oldname => newname +modified: + newname + SAMPLE + + commits = BzrParser.parse(log) + + assert_equal 1, commits.size + assert_equal 2, commits.first.diffs.size + assert_equal "D", commits.first.diffs.first.action + assert_equal "oldname", commits.first.diffs.first.path + assert_equal "A", commits.first.diffs.last.action + assert_equal "newname", commits.first.diffs.last.path + end end end From 18b8f0d5abc7742ad49d46e2590494183831985d Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 11 Aug 2009 12:20:07 -0700 Subject: [PATCH 045/219] [FIX] HgAdapter: Compatibility with hg 1.2.1 Hg now sometimes returns a trailing "+" character after a revid. We need to strip this away. --- lib/scm/adapters/hg/head.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/scm/adapters/hg/head.rb b/lib/scm/adapters/hg/head.rb index e3c39216..9cdaf962 100644 --- a/lib/scm/adapters/hg/head.rb +++ b/lib/scm/adapters/hg/head.rb @@ -3,7 +3,14 @@ class HgAdapter < AbstractAdapter def head_token # This only returns first 12 characters. # How can we make it return the entire hash? - run("hg id -q #{url}").strip + token = run("hg id -q #{url}").strip + + # Recent versions of Hg now somtimes append a '+' char to the token. + # I believe this signifies pending changes... but we don't care. + # Strip the trailing '+', if any. + token = token[0..-2] if token[-1..-1] == '+' + + token end def head From c139ca7ebd70b58c3d69961219ff203d621bda1d Mon Sep 17 00:00:00 2001 From: Andy Verprauskus Date: Mon, 19 Oct 2009 11:12:46 -0700 Subject: [PATCH 046/219] [FIX] as of SVN 1.6.5 or earlier, svn info returns an error code when doing svn info on missing files. Existing code, e.g. deepen_diff(), relies on this returning an empty result with a success code. --- lib/scm/adapters/svn/misc.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/scm/adapters/svn/misc.rb b/lib/scm/adapters/svn/misc.rb index 7fc20ac5..51cf3995 100644 --- a/lib/scm/adapters/svn/misc.rb +++ b/lib/scm/adapters/svn/misc.rb @@ -65,7 +65,11 @@ def info(path=nil, revision=final_token || 'HEAD') else url end - @info[[path, revision]] ||= run "svn info -r #{revision} #{opt_auth} '#{SvnAdapter.uri_encode(uri)}@#{revision}'" + @info[[path, revision]] ||= begin + run "svn info -r #{revision} #{opt_auth} '#{SvnAdapter.uri_encode(uri)}@#{revision}'" + rescue + raise unless $!.message =~ /Not a valid URL/m + end end def root From 43c16127cde8e6c88986723afca8b2f2d4b1d920 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 27 Oct 2009 13:33:54 -0700 Subject: [PATCH 047/219] [FIX] Use Bzr Author name when available Resolves http://thechaw.com/ohloh_scm/tickets/view/19 Parse the author name as well as the committer name from the Bzr log. --- lib/scm/parsers/bzr_parser.rb | 4 ++++ test/unit/bzr_parser_test.rb | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/lib/scm/parsers/bzr_parser.rb b/lib/scm/parsers/bzr_parser.rb index 739bbc61..4e924e1f 100644 --- a/lib/scm/parsers/bzr_parser.rb +++ b/lib/scm/parsers/bzr_parser.rb @@ -40,6 +40,10 @@ def self.internal_parse(buffer, opts) e.token = $1 show_id = true next_state = :data + when /^#{indent}author:\s+(.+?)(\s+<(.+)>)?$/ + e.author_name = $1 + e.author_email = $3 + next_state = :data when /^#{indent}committer:\s+(.+?)(\s+<(.+)>)?$/ e.committer_name = $1 e.committer_email = $3 diff --git a/test/unit/bzr_parser_test.rb b/test/unit/bzr_parser_test.rb index 19bef084..5ed2716c 100644 --- a/test/unit/bzr_parser_test.rb +++ b/test/unit/bzr_parser_test.rb @@ -458,5 +458,26 @@ def test_rename_and_modify_in_one_commit assert_equal "A", commits.first.diffs.last.action assert_equal "newname", commits.first.diffs.last.path end + + def test_different_author_and_committer + log = <<-SAMPLE +------------------------------------------------------------ +revno: 200 +author: Jason Allen +committer: Robin Luckey +branch nick: foo +timestamp: Wed 2009-06-24 19:47:37 +0200 +message: + Just a message + SAMPLE + + commits = BzrParser.parse(log) + + assert_equal 1, commits.size + assert_equal "Jason Allen", commits.first.author_name + assert_equal "jason@ohloh.net", commits.first.author_email + assert_equal "Robin Luckey", commits.first.committer_name + assert_equal "robin@ohloh.net", commits.first.committer_email + end end end From 95331b73ae2eafe2a6a64d281083c8a5e71d3d92 Mon Sep 17 00:00:00 2001 From: Andy Verprauskus Date: Mon, 2 Nov 2009 10:45:41 -0800 Subject: [PATCH 048/219] OH-104 Dont auto-descend beyond /trunk directories --- lib/scm/adapters/svn/misc.rb | 1 - test/unit/svn_misc_test.rb | 12 ++++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/scm/adapters/svn/misc.rb b/lib/scm/adapters/svn/misc.rb index 51cf3995..702fbe9b 100644 --- a/lib/scm/adapters/svn/misc.rb +++ b/lib/scm/adapters/svn/misc.rb @@ -34,7 +34,6 @@ def restrict_url_to_trunk if list.include? 'trunk/' self.url = File.join(self.url, 'trunk') self.branch_name = File.join(self.branch_name, 'trunk') - return restrict_url_to_trunk elsif list.size == 1 and list.first[-1..-1] == '/' self.url = File.join(self.url, list.first[0..-2]) self.branch_name = File.join(self.branch_name, list.first[0..-2]) diff --git a/test/unit/svn_misc_test.rb b/test/unit/svn_misc_test.rb index fd476ddb..0736891d 100644 --- a/test/unit/svn_misc_test.rb +++ b/test/unit/svn_misc_test.rb @@ -61,6 +61,18 @@ def test_is_directory end end + def test_restrict_url_to_trunk_descend_no_further + with_svn_repository('deep_svn') do |svn| + assert_equal svn.root, svn.url + assert_equal '', svn.branch_name + + svn.restrict_url_to_trunk + + assert_equal svn.root + '/trunk', svn.url + assert_equal "/trunk", svn.branch_name + end + end + def test_restrict_url_to_trunk with_svn_repository('svn') do |svn| assert_equal svn.root, svn.url From e5a10dde7278613558b42f03b321680efd08a45e Mon Sep 17 00:00:00 2001 From: Andy Verprauskus Date: Mon, 2 Nov 2009 11:06:10 -0800 Subject: [PATCH 049/219] [FIX] forge detection failing if svn url terminates without a trailing / --- lib/scm/adapters/svn/validation.rb | 2 +- test/unit/svn_validation_test.rb | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/scm/adapters/svn/validation.rb b/lib/scm/adapters/svn/validation.rb index 382366cf..67d77757 100644 --- a/lib/scm/adapters/svn/validation.rb +++ b/lib/scm/adapters/svn/validation.rb @@ -59,7 +59,7 @@ def recalc_branch_name end def guess_forge - u = @url =~ /:\/\/(.*\.?svn\.)?([^\/^:]+)(:\d+)?\// ? $2 : nil + u = @url =~ /:\/\/(.*\.?svn\.)?([^\/^:]+)(:\d+)?(\/|$)/ ? $2 : nil case u when /(googlecode\.com$)/, /(tigris\.org$)/, /(sunsource\.net$)/, /(java\.net$)/, /(openoffice\.org$)/, /(netbeans\.org$)/, /(dev2dev\.bea\.com$)/, /(rubyforge\.org$)/ diff --git a/test/unit/svn_validation_test.rb b/test/unit/svn_validation_test.rb index 8baef357..d3b6ef32 100644 --- a/test/unit/svn_validation_test.rb +++ b/test/unit/svn_validation_test.rb @@ -90,6 +90,9 @@ def test_guess_forge svn = SvnAdapter.new(:url => 'http://moulinette.googlecode.com/svn/trunk') assert_equal 'googlecode.com', svn.guess_forge + + svn = SvnAdapter.new(:url => 'http://moulinette.googlecode.com') + assert_equal 'googlecode.com', svn.guess_forge end def test_sourceforge_requires_https From a6e3b655b6597f0c2ba9580fb4dd1c2ea42fc1c4 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Thu, 5 Nov 2009 09:53:25 -0800 Subject: [PATCH 050/219] [FIX] restict_url_to_trunk fails if already trunk Add a guard to restrict_url_to_trunk() so that it will not do any work if the URL already ends with /trunk --- lib/scm/adapters/svn/misc.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/scm/adapters/svn/misc.rb b/lib/scm/adapters/svn/misc.rb index 702fbe9b..cd296c33 100644 --- a/lib/scm/adapters/svn/misc.rb +++ b/lib/scm/adapters/svn/misc.rb @@ -28,6 +28,8 @@ def hostname # The url and branch_name of this object will be updated with the selected location. # The url will be unmodified if there is a problem connecting to the server. def restrict_url_to_trunk + return self.url if self.url =~ /\/trunk\/?$/ + list = ls return self.url unless list From f5d6ed8c79f7f1674b016dbd8367492a4a173ddc Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Thu, 14 Jan 2010 09:47:58 -0800 Subject: [PATCH 051/219] [FIX] Escape ">" character in Hg filenames --- lib/scm/adapters/hg/cat_file.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scm/adapters/hg/cat_file.rb b/lib/scm/adapters/hg/cat_file.rb index aa20ff8a..829e0e45 100644 --- a/lib/scm/adapters/hg/cat_file.rb +++ b/lib/scm/adapters/hg/cat_file.rb @@ -20,7 +20,7 @@ def cat(revision, path) # Example: # "Foo Bar & Baz" => "Foo\ Bar\ \&\ Baz" def escape(path) - path.gsub(/[ '"&()]/) { |c| '\\' + c } + path.gsub(/[ '"&()<>]/) { |c| '\\' + c } end end end From 5d5d1f37c0da630b086fc324f52cf3386364efe5 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Thu, 20 May 2010 10:23:36 -0700 Subject: [PATCH 052/219] [FIX] Escape "|" character in Hg filenames --- lib/scm/adapters/hg/cat_file.rb | 2 +- test/unit/hg_cat_file_test.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/scm/adapters/hg/cat_file.rb b/lib/scm/adapters/hg/cat_file.rb index 829e0e45..4f8d1e3d 100644 --- a/lib/scm/adapters/hg/cat_file.rb +++ b/lib/scm/adapters/hg/cat_file.rb @@ -20,7 +20,7 @@ def cat(revision, path) # Example: # "Foo Bar & Baz" => "Foo\ Bar\ \&\ Baz" def escape(path) - path.gsub(/[ '"&()<>]/) { |c| '\\' + c } + path.gsub(/[ '"&()<>|]/) { |c| '\\' + c } end end end diff --git a/test/unit/hg_cat_file_test.rb b/test/unit/hg_cat_file_test.rb index c9f1be2c..f856ab76 100644 --- a/test/unit/hg_cat_file_test.rb +++ b/test/unit/hg_cat_file_test.rb @@ -31,7 +31,7 @@ def test_cat_file def test_funny_file_name_chars Scm::ScratchDir.new do |dir| # Make a file with a problematic filename - funny_name = 'file_name (&\'")' + funny_name = '|file_name (&\'")' File.open(File.join(dir, funny_name), 'w') { |f| f.write "contents" } # Add it to an hg repository From 6851c5ca35ff027e772474aa7aa640ccf2fde3d8 Mon Sep 17 00:00:00 2001 From: Robert Schultz Date: Fri, 5 Nov 2010 12:58:18 -0400 Subject: [PATCH 053/219] Fixed a string escape bug for hg --- lib/scm/adapters/hg/cat_file.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scm/adapters/hg/cat_file.rb b/lib/scm/adapters/hg/cat_file.rb index 4f8d1e3d..f3747d85 100644 --- a/lib/scm/adapters/hg/cat_file.rb +++ b/lib/scm/adapters/hg/cat_file.rb @@ -10,7 +10,7 @@ def cat_file_parent(commit, diff) end def cat(revision, path) - out, err = run_with_err("cd '#{url}' && hg cat -r #{revision} #{escape(path)}") + out, err = run_with_err("cd '#{url}' && hg cat -r #{revision} '#{escape(path)}'") return nil if err =~ /No such file in rev/ raise RuntimeError.new(err) unless err.to_s == '' out From af79c7a248296342f8cb8edce6c2404d4a25692e Mon Sep 17 00:00:00 2001 From: Robert Schultz Date: Wed, 8 Dec 2010 09:15:16 -0500 Subject: [PATCH 054/219] Updated SCM to use SVN 1.6's new --trust-server-cert command always --- lib/scm/adapters/svn/cat_file.rb | 2 +- lib/scm/adapters/svn/commits.rb | 12 ++++++------ lib/scm/adapters/svn/head.rb | 2 +- lib/scm/adapters/svn/misc.rb | 10 +++++----- lib/scm/adapters/svn/patch.rb | 2 +- lib/scm/adapters/svn/pull.rb | 8 ++++---- lib/scm/adapters/svn_chain/chain.rb | 2 +- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/lib/scm/adapters/svn/cat_file.rb b/lib/scm/adapters/svn/cat_file.rb index 45a87398..4b2432b6 100644 --- a/lib/scm/adapters/svn/cat_file.rb +++ b/lib/scm/adapters/svn/cat_file.rb @@ -10,7 +10,7 @@ def cat_file_parent(commit, diff) def cat(path, revision) begin - run "svn cat -r #{revision} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name.to_s, path.to_s))}@#{revision}'" + run "svn cat --trust-server-cert --non-interactive -r #{revision} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name.to_s, path.to_s))}@#{revision}'" rescue raise unless $!.message =~ /svn: (File not found|.* is not a directory in filesystem)/ end diff --git a/lib/scm/adapters/svn/commits.rb b/lib/scm/adapters/svn/commits.rb index 1b2b3f0d..f7bf8f20 100644 --- a/lib/scm/adapters/svn/commits.rb +++ b/lib/scm/adapters/svn/commits.rb @@ -23,14 +23,14 @@ class SvnAdapter < AbstractAdapter def commit_count(since=0) since ||= 0 return 0 if final_token && since.to_i >= final_token - run("svn log -q -r #{since.to_i + 1}:#{final_token || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{final_token || 'HEAD'}' | grep -E -e '^r[0-9]+ ' | wc -l").strip.to_i + run("svn log --trust-server-cert --non-interactive -q -r #{since.to_i + 1}:#{final_token || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{final_token || 'HEAD'}' | grep -E -e '^r[0-9]+ ' | wc -l").strip.to_i end # Returns an array of revision numbers for all commits following revision number 'since'. def commit_tokens(since=0) since ||= 0 return [] if final_token && since.to_i >= final_token - cmd = "svn log -q -r #{since.to_i + 1}:#{final_token || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{final_token || 'HEAD'}' | grep -E -e '^r[0-9]+ ' | cut -f 1 -d '|' | cut -c 2-" + cmd = "svn log --trust-server-cert --non-interactive -q -r #{since.to_i + 1}:#{final_token || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{final_token || 'HEAD'}' | grep -E -e '^r[0-9]+ ' | cut -f 1 -d '|' | cut -c 2-" run(cmd).split.collect { |r| r.to_i } end @@ -143,7 +143,7 @@ def verbose_commit(rev) #--------------------------------------------------------------------- def log(since=0) - run "svn log --xml --stop-on-copy -r #{since.to_i + 1}:#{final_token || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name.to_s))}@#{final_token || 'HEAD'}' #{opt_auth}" + run "svn log --trust-server-cert --non-interactive --xml --stop-on-copy -r #{since.to_i + 1}:#{final_token || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name.to_s))}@#{final_token || 'HEAD'}' #{opt_auth}" end def open_log_file(since=0) @@ -153,7 +153,7 @@ def open_log_file(since=0) # As a time optimization, just create an empty file rather than fetch a log we know will be empty. File.open(log_filename, 'w') { |f| f.puts '' } else - run "svn log --xml --stop-on-copy -r #{since.to_i + 1}:#{final_token || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}' #{opt_auth} > #{log_filename}" + run "svn log --trust-server-cert --non-interactive --xml --stop-on-copy -r #{since.to_i + 1}:#{final_token || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}' #{opt_auth} > #{log_filename}" end File.open(log_filename, 'r') { |io| yield io } ensure @@ -167,7 +167,7 @@ def log_filename # Returns one commit with the exact revision number provided def single_revision_xml(revision) - run "svn log --verbose --xml --stop-on-copy -r #{revision} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{revision}'" + run "svn log --trust-server-cert --non-interactive --verbose --xml --stop-on-copy -r #{revision} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{revision}'" end # Recurses the entire repository and returns an array of file names. @@ -177,7 +177,7 @@ def single_revision_xml(revision) # A nil result means that the call failed and the remote server could not be queried. def recurse_files(path=nil, revision=final_token || 'HEAD') begin - stdout = run "svn ls -r #{revision} --recursive #{opt_auth} '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s, path.to_s))}@#{revision}'" + stdout = run "svn ls --trust-server-cert --non-interactive -r #{revision} --recursive #{opt_auth} '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s, path.to_s))}@#{revision}'" rescue puts $!.inspect return nil diff --git a/lib/scm/adapters/svn/head.rb b/lib/scm/adapters/svn/head.rb index 90bc1d87..f95f43fb 100644 --- a/lib/scm/adapters/svn/head.rb +++ b/lib/scm/adapters/svn/head.rb @@ -11,7 +11,7 @@ def head def parents(commit) # Subversion doesn't have an actual "parent" command, so get # a log for this commit and the one preceding it, and keep only the preceding. - log = run "svn log --verbose --xml --stop-on-copy -r #{commit.token}:1 --limit 2 '#{SvnAdapter.uri_encode(self.url)}' #{opt_auth}" + log = run "svn log --trust-server-cert --non-interactive --verbose --xml --stop-on-copy -r #{commit.token}:1 --limit 2 '#{SvnAdapter.uri_encode(self.url)}' #{opt_auth}" [deepen_commit(strip_commit_branch(Scm::Parsers::SvnXmlParser.parse(log).last))] end end diff --git a/lib/scm/adapters/svn/misc.rb b/lib/scm/adapters/svn/misc.rb index cd296c33..4303ceea 100644 --- a/lib/scm/adapters/svn/misc.rb +++ b/lib/scm/adapters/svn/misc.rb @@ -67,7 +67,7 @@ def info(path=nil, revision=final_token || 'HEAD') url end @info[[path, revision]] ||= begin - run "svn info -r #{revision} #{opt_auth} '#{SvnAdapter.uri_encode(uri)}@#{revision}'" + run "svn info --trust-server-cert --non-interactive -r #{revision} #{opt_auth} '#{SvnAdapter.uri_encode(uri)}@#{revision}'" rescue raise unless $!.message =~ /Not a valid URL/m end @@ -88,7 +88,7 @@ def uuid # A nil result means that the call failed and the remote server could not be queried. def ls(path=nil, revision=final_token || 'HEAD') begin - stdout = run "svn ls -r #{revision} #{opt_auth} '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s, path.to_s))}@#{revision}'" + stdout = run "svn ls --trust-server-cert --non-interactive -r #{revision} #{opt_auth} '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s, path.to_s))}@#{revision}'" rescue return nil end @@ -119,16 +119,16 @@ def is_directory?(path=nil, revision=final_token || 'HEAD') def checkout(rev, dest_dir) FileUtils.mkdir_p(File.dirname(dest_dir)) unless FileTest.exist?(File.dirname(dest_dir)) - run "svn checkout -r #{rev.token} '#{SvnAdapter.uri_encode(self.url)}@#{rev.token}' '#{dest_dir}' --ignore-externals #{opt_auth}" + run "svn checkout --trust-server-cert --non-interactive -r #{rev.token} '#{SvnAdapter.uri_encode(self.url)}@#{rev.token}' '#{dest_dir}' --ignore-externals #{opt_auth}" end def export(dest_dir, commit_id = final_token || 'HEAD') FileUtils.mkdir_p(File.dirname(dest_dir)) unless FileTest.exist?(File.dirname(dest_dir)) - run "svn export --ignore-externals --force -r #{commit_id} '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}' '#{dest_dir}'" + run "svn export --trust-server-cert --non-interactive --ignore-externals --force -r #{commit_id} '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}' '#{dest_dir}'" end def ls_tree(token) - run("svn ls -R -r #{token} '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{token}'").split("\n") + run("svn ls --trust-server-cert --non-interactive -R -r #{token} '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{token}'").split("\n") end def opt_auth diff --git a/lib/scm/adapters/svn/patch.rb b/lib/scm/adapters/svn/patch.rb index 394f4264..e9c46c8b 100644 --- a/lib/scm/adapters/svn/patch.rb +++ b/lib/scm/adapters/svn/patch.rb @@ -2,7 +2,7 @@ module Scm::Adapters class SvnAdapter < AbstractAdapter def patch_for_commit(commit) parent = commit.token.to_i - 1 - run("svn diff -r#{parent}:#{commit.token} #{url}") + run("svn diff --trust-server-cert --non-interactive -r#{parent}:#{commit.token} #{url}") end end end diff --git a/lib/scm/adapters/svn/pull.rb b/lib/scm/adapters/svn/pull.rb index 16f42111..58266d89 100644 --- a/lib/scm/adapters/svn/pull.rb +++ b/lib/scm/adapters/svn/pull.rb @@ -50,7 +50,7 @@ def svnadmin_create_remote end def svnsync_init(from) - run "svnsync init #{from.opt_auth} '#{url}' #{from.root}" + run "svnsync init --trust-server-cert --non-interactive #{from.opt_auth} '#{url}' #{from.root}" end def self.svnsync_sync(src, dest) @@ -61,15 +61,15 @@ def self.svnsync_sync(src, dest) dest.propset('sync-from-url', src.root) dest.propset('sync-from-uuid', src.uuid) - run "svnsync sync #{src.opt_auth} --non-interactive '#{SvnAdapter.uri_encode(dest.root)}'" + run "svnsync sync #{src.opt_auth} --trust-server-cert --non-interactive '#{SvnAdapter.uri_encode(dest.root)}'" end def propget(propname) - run("svn propget #{opt_auth} --revprop -r 0 svn:#{propname} '#{SvnAdapter.uri_encode(root)}'").strip! + run("svn propget --trust-server-cert --non-interactive #{opt_auth} --revprop -r 0 svn:#{propname} '#{SvnAdapter.uri_encode(root)}'").strip! end def propset(propname, value) - run("svn propset #{opt_auth} --revprop -r 0 svn:#{propname} #{value} '#{SvnAdapter.uri_encode(root)}'") + run("svn propset --trust-server-cert --non-interactive #{opt_auth} --revprop -r 0 svn:#{propname} #{value} '#{SvnAdapter.uri_encode(root)}'") end end diff --git a/lib/scm/adapters/svn_chain/chain.rb b/lib/scm/adapters/svn_chain/chain.rb index d0662037..b3377d85 100644 --- a/lib/scm/adapters/svn_chain/chain.rb +++ b/lib/scm/adapters/svn_chain/chain.rb @@ -79,7 +79,7 @@ def first_commit(since=0) # Returns the first commit with a revision number greater than the provided revision number def next_revision_xml(since=0) return "" if since.to_i >= head_token - run "svn log --verbose --xml --stop-on-copy -r #{since.to_i+1}:#{final_token || 'HEAD'} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}'" + run "svn log --trust-server-cert --non-interactive --verbose --xml --stop-on-copy -r #{since.to_i+1}:#{final_token || 'HEAD'} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}'" end # If the passed diff represents the wholesale movement of the entire From 47135ef54b4f5dfce1e4fc41ca0f65fe82818ada Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 21 Dec 2010 08:03:24 -0800 Subject: [PATCH 055/219] Specify module name when using CVS test repository During production operation, we always force users to specify a module name. During test our tests, we are using an empty string as the module name. CVSNT has varying behavior when the module name is left empty. In some builds (Mac development machines), leaving out the module name causes rlog to include the CVSROOT directory, while in other builds (production machines) the CVSROOT directory is excluded. The presence or absence of the CVSROOT directory causes a unit test to pass or fail with different cvsnt builds. The flaw here is in the test harness: it should not leave the module name empty, and thus the CVSROOT directory should never be logged. I have modified the test harness to specify the CVS module name everywhere. I have modified the expected responses from CVS to exclude the CVSROOT directory. --- test/test_helper.rb | 7 +++++-- test/unit/adapter_factory_test.rb | 2 +- test/unit/cvs_commits_test.rb | 7 +++---- test/unit/cvs_convert_test.rb | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/test/test_helper.rb b/test/test_helper.rb index 3c8651c3..01a05ecc 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -78,8 +78,11 @@ def with_svn_chain_repository(name, branch_name='') end end - def with_cvs_repository(name) - with_repository(Scm::Adapters::CvsAdapter, name) { |cvs| yield cvs } + def with_cvs_repository(name, module_name='') + with_repository(Scm::Adapters::CvsAdapter, name) do |cvs| + cvs.module_name = module_name + yield cvs + end end def with_git_repository(name) diff --git a/test/unit/adapter_factory_test.rb b/test/unit/adapter_factory_test.rb index f86b7613..71e28622 100644 --- a/test/unit/adapter_factory_test.rb +++ b/test/unit/adapter_factory_test.rb @@ -52,7 +52,7 @@ def test_factory_svn_checkout end def test_factory_from_cvs_checkout - with_cvs_repository('cvs') do |cvs| + with_cvs_repository('cvs', 'simple') do |cvs| Scm::ScratchDir.new do |path| `cd #{path} && cvsnt -d #{File.expand_path(cvs.url)} co simple 2> /dev/null` factory_response = Factory.from_path(File.join(path, 'simple')) diff --git a/test/unit/cvs_commits_test.rb b/test/unit/cvs_commits_test.rb index 442cdb7e..6cd764fb 100644 --- a/test/unit/cvs_commits_test.rb +++ b/test/unit/cvs_commits_test.rb @@ -4,10 +4,9 @@ module Scm::Adapters class CvsCommitsTest < Scm::Test def test_commits - with_cvs_repository('cvs') do |cvs| + with_cvs_repository('cvs', 'simple') do |cvs| - assert_equal ['2006/06/29 16:19:58', - '2006/06/29 16:21:07', + assert_equal ['2006/06/29 16:21:07', '2006/06/29 18:14:47', '2006/06/29 18:45:29', '2006/06/29 18:48:54', @@ -25,7 +24,7 @@ def test_commits end def test_commits_sets_scm - with_cvs_repository('cvs') do |cvs| + with_cvs_repository('cvs', 'simple') do |cvs| cvs.commits.each do |c| assert_equal cvs, c.scm end diff --git a/test/unit/cvs_convert_test.rb b/test/unit/cvs_convert_test.rb index 9a3da406..644ac025 100644 --- a/test/unit/cvs_convert_test.rb +++ b/test/unit/cvs_convert_test.rb @@ -4,7 +4,7 @@ module Scm::Adapters class CvsConvertTest < Scm::Test def test_basic_convert - with_cvs_repository('cvs') do |src| + with_cvs_repository('cvs', 'simple') do |src| Scm::ScratchDir.new do |dest_dir| dest = GitAdapter.new(:url => dest_dir).normalize assert !dest.exist? From c3de1b0b27d7440625a31f851733a2f3e80cccc2 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 11 Jan 2011 11:45:17 -0800 Subject: [PATCH 056/219] Perform Bzr revert before push, pull This is a backport of Ohloh commit a2d86034. It has been live in production since Nov 2009, but was never applied to the lib/scm repository. --- lib/scm/adapters/bzr/pull.rb | 2 +- lib/scm/adapters/bzr/push.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/scm/adapters/bzr/pull.rb b/lib/scm/adapters/bzr/pull.rb index 196b5c06..f7456031 100644 --- a/lib/scm/adapters/bzr/pull.rb +++ b/lib/scm/adapters/bzr/pull.rb @@ -12,7 +12,7 @@ def pull(from, &block) run "rm -rf '#{self.url}'" run "bzr branch '#{from.url}' '#{self.url}'" else - run "cd '#{self.url}' && bzr pull --overwrite '#{from.url}'" + run "cd '#{self.url}' && bzr pull && bzr pull --overwrite '#{from.url}'" end yield(1,1) if block_given? # Progress bar callback diff --git a/lib/scm/adapters/bzr/push.rb b/lib/scm/adapters/bzr/push.rb index e6875b9e..cff83d75 100644 --- a/lib/scm/adapters/bzr/push.rb +++ b/lib/scm/adapters/bzr/push.rb @@ -16,7 +16,7 @@ def push(to, &block) run "scp -rpqB #{bzr_path} #{to.hostname}:#{to.path}" end else - run "cd '#{self.url}' && bzr push '#{to.url}'" + run "cd '#{self.url}' && bzr revert && bzr push '#{to.url}'" end yield(1,1) if block_given? # Progress bar callback From b662a68634566c624b8c3a646518ed28b71767b4 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 11 Jan 2011 11:49:19 -0800 Subject: [PATCH 057/219] support lp: syntax in Bzr This is a backport of Ohloh commit f9b0c4be, ticket OTWO-16. --- lib/scm/adapters/bzr/validation.rb | 4 ++-- test/unit/bzr_validation_test.rb | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/scm/adapters/bzr/validation.rb b/lib/scm/adapters/bzr/validation.rb index 113b0539..a29282be 100644 --- a/lib/scm/adapters/bzr/validation.rb +++ b/lib/scm/adapters/bzr/validation.rb @@ -1,11 +1,11 @@ module Scm::Adapters class BzrAdapter < AbstractAdapter def self.url_regex - /^((http|https|bzr|bzr\+ssh|file):\/\/((\w+@)?[A-Za-z0-9_\-\.]+(:\d+)?\/)?)?[A-Za-z0-9_\-\.\/\~\+]*$/ + /^((((http|https|bzr|bzr\+ssh|file):\/\/((\w+@)?[A-Za-z0-9_\-\.]+(:\d+)?\/)?)|(lp:[A-Za-z0-9_\-\.\~])))?[A-Za-z0-9_\-\.\/\~\+]*$/ end def self.public_url_regex - /^(http|https|bzr):\/\/(\w+@)?[A-Za-z0-9_\-\.]+(:\d+)?\/[A-Za-z0-9_\-\.\/\~\+]*$/ + /^(((http|https|bzr):\/\/(\w+@)?[A-Za-z0-9_\-\.]+(:\d+)?\/)|(lp:[A-Za-z0-9_\-\.\~]))[A-Za-z0-9_\-\.\/\~\+]*$/ end def validate_server_connection diff --git a/test/unit/bzr_validation_test.rb b/test/unit/bzr_validation_test.rb index 1a17beb9..8702542f 100644 --- a/test/unit/bzr_validation_test.rb +++ b/test/unit/bzr_validation_test.rb @@ -8,10 +8,11 @@ def test_rejected_urls "http://www.selenic.com/repo/hello%20world", # no encoded strings allowed "http://www.selenic.com/repo/hello world", # no spaces allowed "git://www.selenic.com/repo/hello", # git protocol not allowed - "svn://www.selenic.com/repo/hello" # svn protocol not allowed + "svn://www.selenic.com/repo/hello", # svn protocol not allowed + "lp://foobar", # lp requires no "//" after colon ].each do |url| bzr = BzrAdapter.new(:url => url, :public_urls_only => true) - assert bzr.validate_url.any? + assert bzr.validate_url.to_a.any?, "Didn't expect #{ url } to validate" end end @@ -20,6 +21,8 @@ def test_accepted_urls "http://www.selenic.com:80/repo/hello", "https://www.selenic.com/repo/hello", "bzr://www.selenic.com/repo/hello", + "lp:foobar", + "lp:~foobar/bar", ].each do |url| bzr = BzrAdapter.new(:url => url, :public_urls_only => true) assert !bzr.validate_url From e3716025561c8f9a70bbf849196e3371f9406d79 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 11 Jan 2011 11:57:31 -0800 Subject: [PATCH 058/219] Enables :ext protocol for CVS This is a backport of Ohloh commit fa1c6f7d, OTWO-55 --- lib/scm/adapters/cvs/commits.rb | 1 + lib/scm/adapters/cvs/misc.rb | 34 +++++++++++++++++++++++++++++- lib/scm/adapters/cvs/validation.rb | 6 +++--- test/unit/cvs_misc_test.rb | 12 +++++++++++ test/unit/cvs_validation_test.rb | 6 ++++-- 5 files changed, 53 insertions(+), 6 deletions(-) diff --git a/lib/scm/adapters/cvs/commits.rb b/lib/scm/adapters/cvs/commits.rb index db3770ed..edc87604 100644 --- a/lib/scm/adapters/cvs/commits.rb +++ b/lib/scm/adapters/cvs/commits.rb @@ -59,6 +59,7 @@ def commits(since=nil) # That's better than missing revisions completely! Just be sure to check for duplicates. def open_log_file(since=nil) begin + ensure_host_key run "cvsnt -d #{self.url} rlog #{opt_branch} #{opt_time(since)} '#{self.module_name}' > #{rlog_filename}" File.open(rlog_filename, 'r') do |file| yield file diff --git a/lib/scm/adapters/cvs/misc.rb b/lib/scm/adapters/cvs/misc.rb index c95d8858..7068468c 100644 --- a/lib/scm/adapters/cvs/misc.rb +++ b/lib/scm/adapters/cvs/misc.rb @@ -12,6 +12,8 @@ def ls(path=nil) cmd = "cvsnt -q -d #{url} ls -e '#{path}'" + ensure_host_key + stdout, stderr = run_with_err(cmd) files = [] @@ -64,12 +66,14 @@ def ls(path=nil) end def log(most_recent_token=nil) + ensure_host_key run "cvsnt -d #{self.url} rlog #{opt_branch} #{opt_time(most_recent_token)} '#{self.module_name}'" end def checkout(r, local_directory) opt_D = r.token ? "-D'#{r.token}Z'" : "" + ensure_host_key if FileTest.exists?(local_directory + '/CVS/Root') # We already have a local enlistment, so do a quick update. if r.directories.size > 0 @@ -146,7 +150,7 @@ def trim_directory(d) end def root - "#{$2}/#{self.module_name}/" if self.url =~ /^:pserver:.*@[^:]+:(\d+)?(\/.*)$/ + "#{$3}/#{self.module_name}/" if self.url =~ /^:(pserver|ext):.*@[^:]+:(\d+)?(\/.*)$/ end def opt_branch @@ -156,5 +160,33 @@ def opt_branch "-b -r1:" end end + + # returns the host this adapter is connecting to + def host + @host ||= begin + self.url =~ /@([^:]*):/ + $1 + end + end + + # returns the protocol this adapter connects with + def protocol + @protocol ||= case self.url + when /^:pserver/ then :pserver + when /^:ext/ then :ext + end + end + + # using :ext (ssh) protocol might trigger ssh to confirm accepting the host's + # ssh key. This causes the UI to hang asking for manual confirmation. To avoid + # this we pre-populate the ~/.ssh/known_hosts file with the host's key. + def ensure_host_key + if self.protocol == :ext + ensure_key_file = File.dirname(__FILE__) + "/../../../../bin/ensure_key" + cmd = "#{ensure_key_file} '#{ self.host }'" + File.new("/home/jallen/LOG", "w+").write("RUNNING: '#{cmd}'") + stdout, stderr = run_with_err(cmd) + end + end end end diff --git a/lib/scm/adapters/cvs/validation.rb b/lib/scm/adapters/cvs/validation.rb index 97a82751..9677514c 100644 --- a/lib/scm/adapters/cvs/validation.rb +++ b/lib/scm/adapters/cvs/validation.rb @@ -1,11 +1,11 @@ module Scm::Adapters class CvsAdapter def self.url_regex - /^(:pserver:[\w\-\+\_]*(:[\w\-\+\_]*)?@[A-Za-z0-9_\-\+\.]+:[0-9]*)?\/[A-Za-z0-9_\-\+\.\/]*$/ + /^(:(pserver|ext):[\w\-\+\_]*(:[\w\-\+\_]*)?@[A-Za-z0-9_\-\+\.]+:[0-9]*)?\/[A-Za-z0-9_\-\+\.\/]*$/ end def self.public_url_regex - /^:pserver:[\w\-\+\_]*(:[\w\-\+\_]*)?@[A-Za-z0-9_\-\+\.]+:[0-9]*\/[A-Za-z0-9_\-\+\.\/]*$/ + /^:(pserver|ext):[\w\-\+\_]*(:[\w\-\+\_]*)?@[A-Za-z0-9_\-\+\.]+:[0-9]*\/[A-Za-z0-9_\-\+\.\/]*$/ end def validate @@ -71,7 +71,7 @@ def validate_server_connection # Based on the URL, take a guess about which forge this code is hosted on. def guess_forge - @url =~ /.*pserver.*@(([^\.]+\.)?(cvs|dev)\.)?([^:]+):\//i ? $4.downcase : nil + @url =~ /.*(pserver|ext).*@(([^\.]+\.)?(cvs|dev)\.)?([^:]+):\//i ? $5.downcase : nil end end end diff --git a/test/unit/cvs_misc_test.rb b/test/unit/cvs_misc_test.rb index 59e7ece7..e1b0768e 100644 --- a/test/unit/cvs_misc_test.rb +++ b/test/unit/cvs_misc_test.rb @@ -45,5 +45,17 @@ def test_ordered_directory_list_ignores_Attic assert_equal "hello", l[2] assert_equal "foo/bar", l[3] end + + def host + r = CvsAdapter.new(:url => ':ext:anonymous:@moodle.cvs.sourceforge.net:/cvsroot/moodle', :module_name => 'contrib') + assert_equal 'moodle.cvs.sourceforge.net', r.host + end + + def protocol + assert_equal :pserver, CvsAdapter.new(:url => ':pserver:foo:@foo.com:/cvsroot/a', :module_name => 'b') + assert_equal :ext, CvsAdapter.new(:url => ':ext:foo:@foo.com:/cvsroot/a', :module_name => 'b') + assert_equal :pserver, CvsAdapter.new(:url => ':pserver:ext:@foo.com:/cvsroot/a', :module_name => 'b') + end + end end diff --git a/test/unit/cvs_validation_test.rb b/test/unit/cvs_validation_test.rb index a50e016e..7047144b 100644 --- a/test/unit/cvs_validation_test.rb +++ b/test/unit/cvs_validation_test.rb @@ -19,7 +19,8 @@ def test_rejected_urls "sourceforge.net/svn/project/trunk", # missing a protocol prefix "file:///home/robin/cvs", # file protocol is not allowed "http://svn.sourceforge.net", # http protocol is not allowed - "git://kernel.org/whatever/linux.git" # git protocol is not allowed + "git://kernel.org/whatever/linux.git", # git protocol is not allowed + "ext@kernel.org/whatever/linux.git" # ext protocol allowed, but starts with ':' ].each do |url| # Rejected for both internal and public use [true, false].each do |p| @@ -42,7 +43,8 @@ def test_accepted_urls ":pserver:anonymous:@sc2.cvs.sourceforge.net:/cvsroot/sc2", ":pserver:cool-dev:@sc2.cvs.sourceforge.net:/cvsroot/sc2", # Hyphen should be OK in username ":pserver:cvs_anon:@cvs.scms.waikato.ac.nz:/usr/local/global-cvs/ml_cvs", # Underscores should be ok in path - ":pserver:anonymous:freefem++@idared.ann.jussieu.fr:/Users/pubcvs/cvs" # Pluses should be OK + ":pserver:anonymous:freefem++@idared.ann.jussieu.fr:/Users/pubcvs/cvs", # Pluses should be OK + ":ext:anoncvs@opensource.conformal.com:/anoncvs/scrotwm" # scrotwm is a real life example ].each do |url| # Valid for both internal and public use [true, false].each do |p| From b3b3c5792d84cbda06bd56568f12da9d1d42f290 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 11 Jan 2011 12:10:31 -0800 Subject: [PATCH 059/219] Fixes incorrect time format in Git parser test Backport of Ohloh commit 4341cd0c. --- test/unit/git_parser_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/git_parser_test.rb b/test/unit/git_parser_test.rb index 68370a55..e1293d39 100644 --- a/test/unit/git_parser_test.rb +++ b/test/unit/git_parser_test.rb @@ -11,7 +11,7 @@ def test_log_parser_default sample_log = < -Date: Fri Jul 14 16:07:15 2006 -0700 +Date: Fri, 14 Jul 2006 16:07:15 -0700 moving COPYING @@ -19,7 +19,7 @@ def test_log_parser_default commit 2e9366dd7a786fdb35f211fff1c8ea05c51968b1 Author: Robin Luckey -Date: Sun Jun 11 11:34:17 2006 -0700 +Date: Sun, 11 Jun 2006 11:34:17 -0700 added some documentation and licensing info From e5a6ea9eb321b17892c7541bf297d734701b3d0f Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 11 Jan 2011 12:21:03 -0800 Subject: [PATCH 060/219] OTWO-171 Fixes hg filenames that include '#' char Rolls back 6851c5ca and applies alternate fix. Unit tests now pass. --- lib/scm/adapters/hg/cat_file.rb | 4 ++-- test/unit/hg_cat_file_test.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/scm/adapters/hg/cat_file.rb b/lib/scm/adapters/hg/cat_file.rb index f3747d85..5e1679cf 100644 --- a/lib/scm/adapters/hg/cat_file.rb +++ b/lib/scm/adapters/hg/cat_file.rb @@ -10,7 +10,7 @@ def cat_file_parent(commit, diff) end def cat(revision, path) - out, err = run_with_err("cd '#{url}' && hg cat -r #{revision} '#{escape(path)}'") + out, err = run_with_err("cd '#{url}' && hg cat -r #{revision} #{escape(path)}") return nil if err =~ /No such file in rev/ raise RuntimeError.new(err) unless err.to_s == '' out @@ -20,7 +20,7 @@ def cat(revision, path) # Example: # "Foo Bar & Baz" => "Foo\ Bar\ \&\ Baz" def escape(path) - path.gsub(/[ '"&()<>|]/) { |c| '\\' + c } + path.gsub(/[ '"&()<>|#]/) { |c| '\\' + c } end end end diff --git a/test/unit/hg_cat_file_test.rb b/test/unit/hg_cat_file_test.rb index f856ab76..a2df16d6 100644 --- a/test/unit/hg_cat_file_test.rb +++ b/test/unit/hg_cat_file_test.rb @@ -31,7 +31,7 @@ def test_cat_file def test_funny_file_name_chars Scm::ScratchDir.new do |dir| # Make a file with a problematic filename - funny_name = '|file_name (&\'")' + funny_name = '#|file_name (&\'")#' File.open(File.join(dir, funny_name), 'w') { |f| f.write "contents" } # Add it to an hg repository From 98dcc5d1b3a06e492ee3c0d9b85748d8007a991c Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Wed, 12 Jan 2011 12:21:37 -0500 Subject: [PATCH 061/219] Adds compatibility with hg 1.7.2 The error text returned by `hg cat` changed in recent hg builds. This patch allows ohloh_scm to accept either old or new error text. --- lib/scm/adapters/hg/cat_file.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scm/adapters/hg/cat_file.rb b/lib/scm/adapters/hg/cat_file.rb index 5e1679cf..09158b47 100644 --- a/lib/scm/adapters/hg/cat_file.rb +++ b/lib/scm/adapters/hg/cat_file.rb @@ -11,7 +11,7 @@ def cat_file_parent(commit, diff) def cat(revision, path) out, err = run_with_err("cd '#{url}' && hg cat -r #{revision} #{escape(path)}") - return nil if err =~ /No such file in rev/ + return nil if err =~ /No such file in rev/i raise RuntimeError.new(err) unless err.to_s == '' out end From b7f6ea70ea9111b2a322e49a0d87190661a81c9f Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Thu, 13 Jan 2011 09:23:48 -0800 Subject: [PATCH 062/219] OTWO-277 Enables GitAdapter to walk trunk only Rather than always return all commits on all branches, the GitAdapter can now restrict its result to show only 'trunk' (--first-parent) commits. NOTE 1. This version of ohloh_scm will not work with Ohloh. This patch introduces a change to the public interface, which has only been implemented on the GitAdapter. All other adapters (and Ohloh itself) must now be updated to match the new interface. NOTE 2. This patch introduces the --always flag to git-whatchanged. To correct the negative line count issue, Ohloh must now account merges, and include the line count delta from a merge commit's first parent. So as part of the work to fix OTWO-31, Ohloh will begin reporting merge commits for the first time. Previously, if a merge commit caused no changes at all to the code tree, it would be excluded from the list of commits seen by ohloh_scm. Since Ohloh ignored all merge commits anyway, this was OK. That will change. It is confusing to return some merges (those that have code changes) and not others (those that do not have code changes). Therefore, we will now return *all* merge commits to Ohloh, and thus we use the --always flag. --- lib/scm/adapters/git/commits.rb | 37 +++++++----- lib/scm/parsers/git_styled_parser.rb | 2 +- test/repositories/git_dupe_delete.tgz | Bin 0 -> 10790 bytes test/unit/git_commits_test.rb | 84 +++++++++++++++++++++++--- test/unit/git_rev_list_test.rb | 25 +++++++- 5 files changed, 123 insertions(+), 25 deletions(-) create mode 100644 test/repositories/git_dupe_delete.tgz diff --git a/lib/scm/adapters/git/commits.rb b/lib/scm/adapters/git/commits.rb index 96a645a0..5d41bb26 100644 --- a/lib/scm/adapters/git/commits.rb +++ b/lib/scm/adapters/git/commits.rb @@ -2,28 +2,29 @@ module Scm::Adapters class GitAdapter < AbstractAdapter # Returns the number of commits in the repository following the commit with SHA1 'since'. - def commit_count(since=nil) - run("#{rev_list_command(since)} | wc -l").to_i + def commit_count(opts={}) + run("#{rev_list_command(opts)} | wc -l").to_i end # Returns the SHA1 hash for every commit in the repository following the commit with SHA1 'since'. - def commit_tokens(since=nil, up_to=branch_name) - run(rev_list_command(since, up_to)).split("\n") + def commit_tokens(opts={}) + run(rev_list_command(opts)).split("\n") end # Yields each commit following the commit with SHA1 'since'. - # Officially, this method isn't required to provide diffs with these commits, and the Subversion equivalent of this method does not, + # Officially, this method isn't required to provide diffs with these commits, + # and the Subversion equivalent of this method does not, # so if you really require the diffs you should be using each_commit() instead. - def commits(since=nil) + def commits(opts={}) result = [] - each_commit(since) { |c| result << c } + each_commit(opts) { |c| result << c } result end # Yields each commit in the repository following the commit with SHA1 'since'. # These commits are populated with diffs. - def each_commit(since=nil) - + def each_commit(opts={}) + # Bug fix (hack) follows. # # git-whatchanged emits a merge commit multiple times, once for each parent, giving the @@ -39,7 +40,7 @@ def each_commit(since=nil) # because Ohloh ignores merge diffs anyway. previous = nil - Scm::Parsers::GitStyledParser.parse(log(since)) do |e| + Scm::Parsers::GitStyledParser.parse(log(opts)) do |e| yield e unless previous && previous.token == e.token previous = e end @@ -52,21 +53,25 @@ def verbose_commit(token) # Retrieves the git log in the format expected by GitStyledParser. # We get the log forward chronological order (oldest first) - def log(since=nil) + def log(opts={}) if has_branch? - if since && since==self.head_token + if opts[:since] && opts[:since]==self.head_token '' # Nothing new. else - run "#{rev_list_command(since)} | xargs -n 1 #{Scm::Parsers::GitStyledParser.whatchanged}" + run "#{rev_list_command(opts)} | xargs -n 1 #{Scm::Parsers::GitStyledParser.whatchanged}" end else '' end end - def rev_list_command(since=nil, up_to=branch_name) - range = since ? "#{since}..#{up_to}" : up_to - "cd '#{url}' && git rev-list --topo-order --reverse #{range}" + def rev_list_command(opts={}) + up_to = opts[:up_to] || branch_name + range = opts[:since] ? "#{opts[:since]}..#{up_to}" : up_to + + trunk_only = opts[:trunk_only] ? "--first-parent" : "" + + "cd '#{url}' && git rev-list --topo-order --reverse #{trunk_only} #{range}" end end end diff --git a/lib/scm/parsers/git_styled_parser.rb b/lib/scm/parsers/git_styled_parser.rb index 7f020c7b..a52ac8e5 100644 --- a/lib/scm/parsers/git_styled_parser.rb +++ b/lib/scm/parsers/git_styled_parser.rb @@ -7,7 +7,7 @@ def self.scm end def self.whatchanged - "git whatchanged --root -m --abbrev=40 --max-count=1 --pretty=#{format}" + "git whatchanged --root -m --abbrev=40 --max-count=1 --always --pretty=#{format}" end def self.format diff --git a/test/repositories/git_dupe_delete.tgz b/test/repositories/git_dupe_delete.tgz new file mode 100644 index 0000000000000000000000000000000000000000..e6bbc0c0490d982dfb6d02b7c8cf499f3f844715 GIT binary patch literal 10790 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 literal 0 HcmV?d00001 diff --git a/test/unit/git_commits_test.rb b/test/unit/git_commits_test.rb index dc2c8ae8..2a3457e8 100644 --- a/test/unit/git_commits_test.rb +++ b/test/unit/git_commits_test.rb @@ -3,33 +3,103 @@ module Scm::Adapters class GitCommitsTest < Scm::Test - def test_commit + def test_commit_count with_git_repository('git') do |git| assert_equal 4, git.commit_count - assert_equal 2, git.commit_count('b6e9220c3cabe53a4ed7f32952aeaeb8a822603d') - assert_equal 0, git.commit_count('1df547800dcd168e589bb9b26b4039bff3a7f7e4') + assert_equal 2, git.commit_count(:since => 'b6e9220c3cabe53a4ed7f32952aeaeb8a822603d') + assert_equal 0, git.commit_count(:since => '1df547800dcd168e589bb9b26b4039bff3a7f7e4') + end + end + def test_commit_tokens + with_git_repository('git') do |git| assert_equal ['089c527c61235bd0793c49109b5bd34d439848c6', 'b6e9220c3cabe53a4ed7f32952aeaeb8a822603d', '2e9366dd7a786fdb35f211fff1c8ea05c51968b1', '1df547800dcd168e589bb9b26b4039bff3a7f7e4'], git.commit_tokens assert_equal ['1df547800dcd168e589bb9b26b4039bff3a7f7e4'], - git.commit_tokens('2e9366dd7a786fdb35f211fff1c8ea05c51968b1') + git.commit_tokens(:since => '2e9366dd7a786fdb35f211fff1c8ea05c51968b1') - assert_equal [], git.commit_tokens('1df547800dcd168e589bb9b26b4039bff3a7f7e4') + assert_equal [], git.commit_tokens(:since => '1df547800dcd168e589bb9b26b4039bff3a7f7e4') + end + end + def test_commits + with_git_repository('git') do |git| assert_equal ['089c527c61235bd0793c49109b5bd34d439848c6', 'b6e9220c3cabe53a4ed7f32952aeaeb8a822603d', '2e9366dd7a786fdb35f211fff1c8ea05c51968b1', '1df547800dcd168e589bb9b26b4039bff3a7f7e4'], git.commits.collect { |c| c.token } assert_equal ['1df547800dcd168e589bb9b26b4039bff3a7f7e4'], - git.commits('2e9366dd7a786fdb35f211fff1c8ea05c51968b1').collect { |c| c.token } + git.commits(:since => '2e9366dd7a786fdb35f211fff1c8ea05c51968b1').collect { |c| c.token } - assert_equal [], git.commits('1df547800dcd168e589bb9b26b4039bff3a7f7e4') + assert_equal [], git.commits(:since => '1df547800dcd168e589bb9b26b4039bff3a7f7e4') end end + def test_trunk_only_commit_count + with_git_repository('git_dupe_delete') do |git| + assert_equal 4, git.commit_count(:trunk_only => false) + assert_equal 3, git.commit_count(:trunk_only => true) + end + end + + def test_trunk_only_commit_tokens + with_git_repository('git_dupe_delete') do |git| + assert_equal ['a0a2b8623941562031a7d7f95d984feb4a2d719c', + 'ad6bb43112706c462e53a9a8a8cd3b05f8e9260f', + '6126337d2497806528fd8657181d5d4afadd72a4', # On branch + '41c4b1044ebffc968d363e5f5e883134e624f846'], + git.commit_tokens(:trunk_only => false) + + assert_equal ['a0a2b8623941562031a7d7f95d984feb4a2d719c', + 'ad6bb43112706c462e53a9a8a8cd3b05f8e9260f', + # '6126337d2497806528fd8657181d5d4afadd72a4', # On branch + '41c4b1044ebffc968d363e5f5e883134e624f846'], + git.commit_tokens(:trunk_only => true) + end + end + + def test_trunk_only_commit_tokens_using_since + with_git_repository('git_dupe_delete') do |git| + assert_equal ['ad6bb43112706c462e53a9a8a8cd3b05f8e9260f', + '41c4b1044ebffc968d363e5f5e883134e624f846'], + git.commit_tokens( + :since => 'a0a2b8623941562031a7d7f95d984feb4a2d719c', + :trunk_only => true) + + # All trunk commit_tokens, with :since == HEAD + assert_equal [], git.commit_tokens( + :since => '41c4b1044ebffc968d363e5f5e883134e624f846', + :trunk_only => true) + end + end + + def test_trunk_only_commits + with_git_repository('git_dupe_delete') do |git| + assert_equal ['a0a2b8623941562031a7d7f95d984feb4a2d719c', + 'ad6bb43112706c462e53a9a8a8cd3b05f8e9260f', + # The following commit is on a branch and should be excluded + # '6126337d2497806528fd8657181d5d4afadd72a4', + '41c4b1044ebffc968d363e5f5e883134e624f846'], + git.commits(:trunk_only => true).collect { |c| c.token } + end + end + + def test_trunk_only_commits_using_since + with_git_repository('git_dupe_delete') do |git| + assert_equal ['ad6bb43112706c462e53a9a8a8cd3b05f8e9260f', + '41c4b1044ebffc968d363e5f5e883134e624f846'], + git.commits(:since => 'a0a2b8623941562031a7d7f95d984feb4a2d719c', + :trunk_only => true).collect { |c| c.token } + + assert_equal [], git.commit_tokens( + :since => '41c4b1044ebffc968d363e5f5e883134e624f846', + :trunk_only => true) + end + end + end end diff --git a/test/unit/git_rev_list_test.rb b/test/unit/git_rev_list_test.rb index 4b48aa3f..693b2fbd 100644 --- a/test/unit/git_rev_list_test.rb +++ b/test/unit/git_rev_list_test.rb @@ -32,10 +32,33 @@ def test_rev_list end end + def test_trunk_only_rev_list + with_git_repository('git_walk') do |git| + # Full history to a commit + assert_equal [:A], rev_list_trunk(git, nil, :A) + assert_equal [:A, :B], rev_list_trunk(git, nil, :B) + assert_equal [:A, :B, :C], rev_list_trunk(git, nil, :C) + assert_equal [:A, :B, :C, :D], rev_list_trunk(git, nil, :D) + + # Limited history from one commit to another + assert_equal [], rev_list_trunk(git, :A, :A) + assert_equal [:B], rev_list_trunk(git, :A, :B) + assert_equal [:B, :C], rev_list_trunk(git, :A, :C) + assert_equal [:B, :C, :D], rev_list_trunk(git, :A, :D) + assert_equal [:C, :D], rev_list_trunk(git, :B, :D) + assert_equal [:D], rev_list_trunk(git, :C, :D) + end + end + protected def rev_list_helper(git, from, to) - to_labels(git.commit_tokens(from_label(from), from_label(to))) + to_labels(git.commit_tokens(:since => from_label(from), :up_to => from_label(to))) + end + + def rev_list_trunk(git, from, to) + to_labels(git.commit_tokens(:since => from_label(from), :up_to => from_label(to), + :trunk_only => true)) end def commit_labels From b5515edd511428d4b94e0c79245fccf9a8e1df1e Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Thu, 13 Jan 2011 11:21:38 -0800 Subject: [PATCH 063/219] OTWO-277 Update all adapters to use new interface All adapters now accept a hash of options as the sole parameter to the commits() methods. --- lib/scm/adapters/bzr/commits.rb | 31 ++++++++------- lib/scm/adapters/cvs/commits.rb | 13 ++++--- lib/scm/adapters/git/pull.rb | 2 +- lib/scm/adapters/hg/commits.rb | 24 ++++++++---- lib/scm/adapters/svn/commits.rb | 31 ++++++++------- lib/scm/adapters/svn_chain/commits.rb | 16 ++++---- test/unit/bzr_commits_test.rb | 16 ++++---- test/unit/cvs_commits_test.rb | 8 ++-- test/unit/hg_commits_test.rb | 14 +++---- test/unit/hg_rev_list_test.rb | 2 +- test/unit/svn_chain_commits_test.rb | 56 +++++++++++++-------------- test/unit/svn_commits_test.rb | 12 +++--- 12 files changed, 122 insertions(+), 103 deletions(-) diff --git a/lib/scm/adapters/bzr/commits.rb b/lib/scm/adapters/bzr/commits.rb index fb70574f..10ec609d 100644 --- a/lib/scm/adapters/bzr/commits.rb +++ b/lib/scm/adapters/bzr/commits.rb @@ -2,13 +2,14 @@ module Scm::Adapters class BzrAdapter < AbstractAdapter # Return the number of commits in the repository following +since+. - def commit_count(since=nil) - commit_tokens(since).size + def commit_count(opts={}) + commit_tokens(opts).size end # Return the list of commit tokens following +since+. - def commit_tokens(since=nil) - tokens = run("#{rev_list_command(since)} | grep -E -e '^( *)revision-id: ' | cut -f2 -d':' | cut -c 2-").split("\n") + def commit_tokens(opts={}) + since = opts[:since] + tokens = run("#{rev_list_command(opts)} | grep -E -e '^( *)revision-id: ' | cut -f2 -d':' | cut -c 2-").split("\n") # Bzr returns everything after *and including* since. # We want to exclude it. @@ -24,8 +25,9 @@ def commit_tokens(since=nil) # we encounter massive repositories. If you need all commits # including diffs, you should use the each_commit() iterator, # which only holds one commit in memory at a time. - def commits(since=nil) - log = run("#{rev_list_command(since)} | cat") + def commits(opts={}) + since = opts[:since] + log = run("#{rev_list_command(opts)} | cat") a = Scm::Parsers::BzrParser.parse(log) if a.any? && a.first.token == since @@ -46,8 +48,9 @@ def verbose_commit(token) # This is designed to prevent excessive RAM usage when we # encounter a massive repository. Only a single commit is ever # held in memory at once. - def each_commit(since=nil) - open_log_file(since) do |io| + def each_commit(opts={}) + since = opts[:since] + open_log_file(opts) do |io| Scm::Parsers::BzrParser.parse(io) do |commit| yield remove_directories(commit) if block_given? && commit.token != since end @@ -63,8 +66,8 @@ def remove_directories(commit) # Not used by Ohloh proper, but handy for debugging and testing - def log(since=nil) - run "#{rev_list_command(since)} -v" + def log(opts={}) + run "#{rev_list_command(opts)} -v" end # Returns a file handle to the log. @@ -72,14 +75,15 @@ def log(since=nil) # +since+. However, bzr doesn't work that way; it returns # everything after and INCLUDING +since+. Therefore, consumers # of this file should check for and reject the duplicate commit. - def open_log_file(since=nil) + def open_log_file(opts={}) + since = opts[:since] begin if since == head_token # There are no new commits # As a time optimization, just create an empty # file rather than fetch a log we know will be empty. File.open(log_filename, 'w') { } else - run "#{rev_list_command(since)} -v > #{log_filename}" + run "#{rev_list_command(opts)} -v > #{log_filename}" end File.open(log_filename, 'r') { |io| yield io } ensure @@ -91,7 +95,8 @@ def log_filename File.join('/tmp', (self.url).gsub(/\W/,'') + '.log') end - def rev_list_command(since=nil) + def rev_list_command(opts={}) + since = opts[:since] "cd '#{self.url}' && bzr log --long --show-id --forward --include-merges -r #{to_rev_param(since)}.." end end diff --git a/lib/scm/adapters/cvs/commits.rb b/lib/scm/adapters/cvs/commits.rb index edc87604..fc476a2b 100644 --- a/lib/scm/adapters/cvs/commits.rb +++ b/lib/scm/adapters/cvs/commits.rb @@ -1,13 +1,15 @@ module Scm::Adapters class CvsAdapter - def commits(since=nil) + def commits(opts={}) + since = opts[:since] result = [] - open_log_file(since) do |io| + + open_log_file(opts) do |io| result = Scm::Parsers::CvsParser.parse(io, :branch_name => branch_name) end - + # Git converter needs a backpointer to the scm for each commit - result.each { |c| c.scm = self } + result.each { |c| c.scm = self } return result if result.size == 0 # Nothing found; we're done here. return result if since.to_s == '' # We requested everything, so just return everything. @@ -57,7 +59,8 @@ def commits(since=nil) # In any case, to be sure not to miss any commits, this method subtracts 10 seconds from the provided timestamp. # This means that the returned log might actually contain a few revisions that predate the requested time. # That's better than missing revisions completely! Just be sure to check for duplicates. - def open_log_file(since=nil) + def open_log_file(opts={}) + since = opts[:since] begin ensure_host_key run "cvsnt -d #{self.url} rlog #{opt_branch} #{opt_time(since)} '#{self.module_name}' > #{rlog_filename}" diff --git a/lib/scm/adapters/git/pull.rb b/lib/scm/adapters/git/pull.rb index c57d17d6..27cbf5a5 100644 --- a/lib/scm/adapters/git/pull.rb +++ b/lib/scm/adapters/git/pull.rb @@ -72,7 +72,7 @@ def convert(source_scm) yield(0,1) if block_given? # Progress bar callback # Any new work to be done since last time we were here? - commits = source_scm.commits(read_token) + commits = source_scm.commits(:since => read_token) if commits and commits.size > 0 # Start by making sure we are in a known good state. Set up our working directory. clean_up_disk diff --git a/lib/scm/adapters/hg/commits.rb b/lib/scm/adapters/hg/commits.rb index e3284b2a..864b61f6 100644 --- a/lib/scm/adapters/hg/commits.rb +++ b/lib/scm/adapters/hg/commits.rb @@ -2,12 +2,15 @@ module Scm::Adapters class HgAdapter < AbstractAdapter # Return the number of commits in the repository following +since+. - def commit_count(since=0) - commit_tokens(since || 0).size + def commit_count(opts={}) + commit_tokens(opts).size end # Return the list of commit tokens following +since+. - def commit_tokens(since=0, up_to='tip') + def commit_tokens(opts={}) + since = opts[:since] || 0 + up_to = opts[:up_to] || 'tip' + # We reverse the final result in Ruby, rather than passing the --reverse flag to hg. # That's because the -f (follow) flag doesn't behave the same in both directions. # Basically, we're trying very hard to make this act just like Git. The hg_rev_list_test checks this. @@ -26,8 +29,10 @@ def commit_tokens(since=0, up_to='tip') # Not including the diffs is meant to be a memory savings when we encounter massive repositories. # If you need all commits including diffs, you should use the each_commit() iterator, which only holds one commit # in memory at a time. - def commits(since=0) - log = run("cd '#{self.url}' && hg log -f -v -r tip:#{since || 0} --style #{Scm::Parsers::HgStyledParser.style_path}") + def commits(opts={}) + since = opts[:since] || 0 + + log = run("cd '#{self.url}' && hg log -f -v -r tip:#{since} --style #{Scm::Parsers::HgStyledParser.style_path}") a = Scm::Parsers::HgStyledParser.parse(log).reverse if a.any? && a.first.token == since @@ -47,7 +52,8 @@ def verbose_commit(token) # The log is stored in a temporary file. # This is designed to prevent excessive RAM usage when we encounter a massive repository. # Only a single commit is ever held in memory at once. - def each_commit(since=0) + def each_commit(opts={}) + since = opts[:since] || 0 open_log_file(since) do |io| Scm::Parsers::HgStyledParser.parse(io) do |commit| yield commit if block_given? && commit.token != since @@ -56,7 +62,8 @@ def each_commit(since=0) end # Not used by Ohloh proper, but handy for debugging and testing - def log(since=0) + def log(opts={}) + since = opts[:since] || 0 run "cd '#{url}' && hg log -f -v -r tip:#{since}" end @@ -64,7 +71,8 @@ def log(since=0) # In our standard, the log should include everything AFTER +since+. However, hg doesn't work that way; # it returns everything after and INCLUDING +since+. Therefore, consumers of this file should check for # and reject the duplicate commit. - def open_log_file(since=0) + def open_log_file(opts={}) + since = opts[:since] || 0 begin if since == head_token # There are no new commits # As a time optimization, just create an empty file rather than fetch a log we know will be empty. diff --git a/lib/scm/adapters/svn/commits.rb b/lib/scm/adapters/svn/commits.rb index f7bf8f20..897c239c 100644 --- a/lib/scm/adapters/svn/commits.rb +++ b/lib/scm/adapters/svn/commits.rb @@ -20,25 +20,25 @@ class SvnAdapter < AbstractAdapter attr_accessor :final_token # Returns the count of commits following revision number 'since'. - def commit_count(since=0) - since ||= 0 - return 0 if final_token && since.to_i >= final_token + def commit_count(opts={}) + since = (opts[:since] || 0).to_i + return 0 if final_token && since >= final_token run("svn log --trust-server-cert --non-interactive -q -r #{since.to_i + 1}:#{final_token || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{final_token || 'HEAD'}' | grep -E -e '^r[0-9]+ ' | wc -l").strip.to_i end # Returns an array of revision numbers for all commits following revision number 'since'. - def commit_tokens(since=0) - since ||= 0 - return [] if final_token && since.to_i >= final_token - cmd = "svn log --trust-server-cert --non-interactive -q -r #{since.to_i + 1}:#{final_token || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{final_token || 'HEAD'}' | grep -E -e '^r[0-9]+ ' | cut -f 1 -d '|' | cut -c 2-" + def commit_tokens(opts={}) + since = (opts[:since] || 0).to_i + return [] if final_token && since >= final_token + cmd = "svn log --trust-server-cert --non-interactive -q -r #{since + 1}:#{final_token || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{final_token || 'HEAD'}' | grep -E -e '^r[0-9]+ ' | cut -f 1 -d '|' | cut -c 2-" run(cmd).split.collect { |r| r.to_i } end # Returns an array of commits following revision number 'since'. # These commit objects do not include diffs. - def commits(since=0) + def commits(opts={}) list = [] - open_log_file(since.to_i) do |io| + open_log_file(opts) do |io| list = Scm::Parsers::SvnXmlParser.parse(io) end list.each { |c| c.scm = self } @@ -52,8 +52,8 @@ def commits(since=0) # directories, the complexity (and time) of this method comes in expanding directories with a recursion # through every file in the directory. # - def each_commit(since=nil) - commit_tokens(since).each do |rev| + def each_commit(opts={}) + commit_tokens(opts).each do |rev| yield verbose_commit(rev) end end @@ -142,18 +142,19 @@ def verbose_commit(rev) # Log-related code ; get log for entire file or single revision #--------------------------------------------------------------------- - def log(since=0) + def log(opts={}) + since = (opts[:since] || 0).to_i run "svn log --trust-server-cert --non-interactive --xml --stop-on-copy -r #{since.to_i + 1}:#{final_token || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name.to_s))}@#{final_token || 'HEAD'}' #{opt_auth}" end - def open_log_file(since=0) - since ||= 0 + def open_log_file(opts={}) + since = (opts[:since] || 0).to_i begin if (final_token && since >= final_token) || since >= head_token # As a time optimization, just create an empty file rather than fetch a log we know will be empty. File.open(log_filename, 'w') { |f| f.puts '' } else - run "svn log --trust-server-cert --non-interactive --xml --stop-on-copy -r #{since.to_i + 1}:#{final_token || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}' #{opt_auth} > #{log_filename}" + run "svn log --trust-server-cert --non-interactive --xml --stop-on-copy -r #{since + 1}:#{final_token || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}' #{opt_auth} > #{log_filename}" end File.open(log_filename, 'r') { |io| yield io } ensure diff --git a/lib/scm/adapters/svn_chain/commits.rb b/lib/scm/adapters/svn_chain/commits.rb index 4c9c6a2b..c4672c6f 100644 --- a/lib/scm/adapters/svn_chain/commits.rb +++ b/lib/scm/adapters/svn_chain/commits.rb @@ -2,22 +2,22 @@ module Scm::Adapters class SvnChainAdapter < SvnAdapter # Returns the count of commits following revision number 'since'. - def commit_count(since=0) - (parent_svn ? parent_svn.commit_count(since) : 0) + super(since) + def commit_count(opts={}) + (parent_svn(opts[:since]) ? parent_svn(opts[:since]).commit_count(opts) : 0) + super(opts) end # Returns an array of revision numbers for all commits following revision number 'since'. - def commit_tokens(since=0) - (parent_svn(since) ? parent_svn.commit_tokens(since) : []) + super(since) + def commit_tokens(opts={}) + (parent_svn(opts[:since]) ? parent_svn(opts[:since]).commit_tokens(opts) : []) + super(opts) end # Returns an array of commits following revision number 'since'. - def commits(since=0) - (parent_svn(since) ? parent_svn.commits(since) : []) + super(since) + def commits(opts={}) + (parent_svn(opts[:since]) ? parent_svn(opts[:since]).commits(opts) : []) + super(opts) end - def verbose_commit(since=0) - parent_svn(since) ? parent_svn.verbose_commit(since) : super(since) + def verbose_commit(rev=0) + parent_svn(rev) ? parent_svn.verbose_commit(rev) : super(rev) end # If the diff points to a file, simply returns the diff. diff --git a/test/unit/bzr_commits_test.rb b/test/unit/bzr_commits_test.rb index 12350c8a..8005543f 100644 --- a/test/unit/bzr_commits_test.rb +++ b/test/unit/bzr_commits_test.rb @@ -6,9 +6,9 @@ class BzrCommitsTest < Scm::Test def test_commit_count with_bzr_repository('bzr') do |bzr| assert_equal 6, bzr.commit_count - assert_equal 5, bzr.commit_count(revision_ids.first) - assert_equal 1, bzr.commit_count(revision_ids[4]) - assert_equal 0, bzr.commit_count(revision_ids.last) + assert_equal 5, bzr.commit_count(:since => revision_ids.first) + assert_equal 1, bzr.commit_count(:since => revision_ids[4]) + assert_equal 0, bzr.commit_count(:since => revision_ids.last) end end @@ -22,17 +22,17 @@ def test_commit_count_with_branches def test_commit_tokens with_bzr_repository('bzr') do |bzr| assert_equal revision_ids, bzr.commit_tokens - assert_equal revision_ids[1..5], bzr.commit_tokens(revision_ids.first) - assert_equal revision_ids[5..5], bzr.commit_tokens(revision_ids[4]) - assert_equal [], bzr.commit_tokens(revision_ids.last) + assert_equal revision_ids[1..5], bzr.commit_tokens(:since => revision_ids.first) + assert_equal revision_ids[5..5], bzr.commit_tokens(:since => revision_ids[4]) + assert_equal [], bzr.commit_tokens(:since => revision_ids.last) end end def test_commits with_bzr_repository('bzr') do |bzr| assert_equal revision_ids, bzr.commits.collect { |c| c.token } - assert_equal revision_ids[5..5], bzr.commits(revision_ids[4]).collect { |c| c.token } - assert_equal [], bzr.commits(revision_ids.last).collect { |c| c.token } + assert_equal revision_ids[5..5], bzr.commits(:since => revision_ids[4]).collect { |c| c.token } + assert_equal [], bzr.commits(:since => revision_ids.last).collect { |c| c.token } # Check that the diffs are not populated assert_equal [], bzr.commits.first.diffs diff --git a/test/unit/cvs_commits_test.rb b/test/unit/cvs_commits_test.rb index 6cd764fb..8497aff1 100644 --- a/test/unit/cvs_commits_test.rb +++ b/test/unit/cvs_commits_test.rb @@ -13,13 +13,15 @@ def test_commits '2006/06/29 18:52:23'], cvs.commits.collect { |c| c.token } assert_equal ['2006/06/29 18:48:54', - '2006/06/29 18:52:23'], cvs.commits('2006/06/29 18:45:29').collect { |c| c.token } + '2006/06/29 18:52:23'], + cvs.commits(:since => '2006/06/29 18:45:29').collect { |c| c.token } # Make sure we are date format agnostic (2008/01/01 is the same as 2008-01-01) assert_equal ['2006/06/29 18:48:54', - '2006/06/29 18:52:23'], cvs.commits('2006-06-29 18:45:29').collect { |c| c.token } + '2006/06/29 18:52:23'], + cvs.commits(:since => '2006-06-29 18:45:29').collect { |c| c.token } - assert_equal [], cvs.commits('2006/06/29 18:52:23').collect { |c| c.token } + assert_equal [], cvs.commits(:since => '2006/06/29 18:52:23').collect { |c| c.token } end end diff --git a/test/unit/hg_commits_test.rb b/test/unit/hg_commits_test.rb index 9b14aa10..439882ed 100644 --- a/test/unit/hg_commits_test.rb +++ b/test/unit/hg_commits_test.rb @@ -6,8 +6,8 @@ class HgCommitsTest < Scm::Test def test_commit with_hg_repository('hg') do |hg| assert_equal 4, hg.commit_count - assert_equal 2, hg.commit_count('b14fa4692f949940bd1e28da6fb4617de2615484') - assert_equal 0, hg.commit_count('75532c1e1f1de55c2271f6fd29d98efbe35397c4') + assert_equal 2, hg.commit_count(:since => 'b14fa4692f949940bd1e28da6fb4617de2615484') + assert_equal 0, hg.commit_count(:since => '75532c1e1f1de55c2271f6fd29d98efbe35397c4') assert_equal ['01101d8ef3cea7da9ac6e9a226d645f4418f05c9', 'b14fa4692f949940bd1e28da6fb4617de2615484', @@ -15,9 +15,9 @@ def test_commit '75532c1e1f1de55c2271f6fd29d98efbe35397c4'], hg.commit_tokens assert_equal ['75532c1e1f1de55c2271f6fd29d98efbe35397c4'], - hg.commit_tokens('468336c6671cbc58237a259d1b7326866afc2817') + hg.commit_tokens(:since => '468336c6671cbc58237a259d1b7326866afc2817') - assert_equal [], hg.commit_tokens('75532c1e1f1de55c2271f6fd29d98efbe35397c4') + assert_equal [], hg.commit_tokens(:since => '75532c1e1f1de55c2271f6fd29d98efbe35397c4') assert_equal ['01101d8ef3cea7da9ac6e9a226d645f4418f05c9', 'b14fa4692f949940bd1e28da6fb4617de2615484', @@ -25,12 +25,12 @@ def test_commit '75532c1e1f1de55c2271f6fd29d98efbe35397c4'], hg.commits.collect { |c| c.token } assert_equal ['75532c1e1f1de55c2271f6fd29d98efbe35397c4'], - hg.commits('468336c6671cbc58237a259d1b7326866afc2817').collect { |c| c.token } + hg.commits(:since => '468336c6671cbc58237a259d1b7326866afc2817').collect { |c| c.token } # Check that the diffs are not populated - assert_equal [], hg.commits('468336c6671cbc58237a259d1b7326866afc2817').first.diffs + assert_equal [], hg.commits(:since => '468336c6671cbc58237a259d1b7326866afc2817').first.diffs - assert_equal [], hg.commits('75532c1e1f1de55c2271f6fd29d98efbe35397c4') + assert_equal [], hg.commits(:since => '75532c1e1f1de55c2271f6fd29d98efbe35397c4') end end diff --git a/test/unit/hg_rev_list_test.rb b/test/unit/hg_rev_list_test.rb index b5036cb3..389870d3 100644 --- a/test/unit/hg_rev_list_test.rb +++ b/test/unit/hg_rev_list_test.rb @@ -33,7 +33,7 @@ def test_rev_list protected def rev_list_helper(hg, from, to) - to_labels(hg.commit_tokens(from_label(from), from_label(to))) + to_labels(hg.commit_tokens(:since => from_label(from), :up_to => from_label(to))) end def commit_labels diff --git a/test/unit/svn_chain_commits_test.rb b/test/unit/svn_chain_commits_test.rb index 77266b26..897d12e7 100644 --- a/test/unit/svn_chain_commits_test.rb +++ b/test/unit/svn_chain_commits_test.rb @@ -6,46 +6,46 @@ class SvnChainTest < Scm::Test def test_chained_commit_tokens with_svn_chain_repository('svn_with_branching', '/trunk') do |svn| assert_equal [1,2,4,5,8,9], svn.commit_tokens - assert_equal [2,4,5,8,9], svn.commit_tokens(1) - assert_equal [4,5,8,9], svn.commit_tokens(2) - assert_equal [4,5,8,9], svn.commit_tokens(3) - assert_equal [5,8,9], svn.commit_tokens(4) - assert_equal [8,9], svn.commit_tokens(5) - assert_equal [8,9], svn.commit_tokens(6) - assert_equal [8,9], svn.commit_tokens(7) - assert_equal [9], svn.commit_tokens(8) - assert_equal [], svn.commit_tokens(9) - assert_equal [], svn.commit_tokens(10) + assert_equal [2,4,5,8,9], svn.commit_tokens(:since => 1) + assert_equal [4,5,8,9], svn.commit_tokens(:since => 2) + assert_equal [4,5,8,9], svn.commit_tokens(:since => 3) + assert_equal [5,8,9], svn.commit_tokens(:since => 4) + assert_equal [8,9], svn.commit_tokens(:since => 5) + assert_equal [8,9], svn.commit_tokens(:since => 6) + assert_equal [8,9], svn.commit_tokens(:since => 7) + assert_equal [9], svn.commit_tokens(:since => 8) + assert_equal [], svn.commit_tokens(:since => 9) + assert_equal [], svn.commit_tokens(:since => 10) end end def test_chained_commit_count with_svn_chain_repository('svn_with_branching', '/trunk') do |svn| assert_equal 6, svn.commit_count - assert_equal 5, svn.commit_count(1) - assert_equal 4, svn.commit_count(2) - assert_equal 4, svn.commit_count(3) - assert_equal 3, svn.commit_count(4) - assert_equal 2, svn.commit_count(5) - assert_equal 2, svn.commit_count(6) - assert_equal 2, svn.commit_count(7) - assert_equal 1, svn.commit_count(8) - assert_equal 0, svn.commit_count(9) + assert_equal 5, svn.commit_count(:since => 1) + assert_equal 4, svn.commit_count(:since => 2) + assert_equal 4, svn.commit_count(:since => 3) + assert_equal 3, svn.commit_count(:since => 4) + assert_equal 2, svn.commit_count(:since => 5) + assert_equal 2, svn.commit_count(:since => 6) + assert_equal 2, svn.commit_count(:since => 7) + assert_equal 1, svn.commit_count(:since => 8) + assert_equal 0, svn.commit_count(:since => 9) end end def test_chained_commits with_svn_chain_repository('svn_with_branching', '/trunk') do |svn| assert_equal [1,2,4,5,8,9], svn.commits.collect { |c| c.token } - assert_equal [2,4,5,8,9], svn.commits(1).collect { |c| c.token } - assert_equal [4,5,8,9], svn.commits(2).collect { |c| c.token } - assert_equal [4,5,8,9], svn.commits(3).collect { |c| c.token } - assert_equal [5,8,9], svn.commits(4).collect { |c| c.token } - assert_equal [8,9], svn.commits(5).collect { |c| c.token } - assert_equal [8,9], svn.commits(6).collect { |c| c.token } - assert_equal [8,9], svn.commits(7).collect { |c| c.token } - assert_equal [9], svn.commits(8).collect { |c| c.token } - assert_equal [], svn.commits(9).collect { |c| c.token } + assert_equal [2,4,5,8,9], svn.commits(:since => 1).collect { |c| c.token } + assert_equal [4,5,8,9], svn.commits(:since => 2).collect { |c| c.token } + assert_equal [4,5,8,9], svn.commits(:since => 3).collect { |c| c.token } + assert_equal [5,8,9], svn.commits(:since => 4).collect { |c| c.token } + assert_equal [8,9], svn.commits(:since => 5).collect { |c| c.token } + assert_equal [8,9], svn.commits(:since => 6).collect { |c| c.token } + assert_equal [8,9], svn.commits(:since => 7).collect { |c| c.token } + assert_equal [9], svn.commits(:since => 8).collect { |c| c.token } + assert_equal [], svn.commits(:since => 9).collect { |c| c.token } end end diff --git a/test/unit/svn_commits_test.rb b/test/unit/svn_commits_test.rb index ef90191f..b66d54af 100644 --- a/test/unit/svn_commits_test.rb +++ b/test/unit/svn_commits_test.rb @@ -6,16 +6,16 @@ class SvnCommitsTest < Scm::Test def test_commits with_svn_repository('svn') do |svn| assert_equal 5, svn.commit_count - assert_equal 3, svn.commit_count(2) - assert_equal 0, svn.commit_count(1000) + assert_equal 3, svn.commit_count(:since => 2) + assert_equal 0, svn.commit_count(:since => 1000) assert_equal [1,2,3,4,5], svn.commit_tokens - assert_equal [3,4,5], svn.commit_tokens(2) - assert_equal [], svn.commit_tokens(1000) + assert_equal [3,4,5], svn.commit_tokens(:since => 2) + assert_equal [], svn.commit_tokens(:since => 1000) assert_equal [1,2,3,4,5], svn.commits.collect { |c| c.token } - assert_equal [3,4,5], svn.commits(2).collect { |c| c.token } - assert_equal [], svn.commits(1000) + assert_equal [3,4,5], svn.commits(:since => 2).collect { |c| c.token } + assert_equal [], svn.commits(:since => 1000) assert !FileTest.exist?(svn.log_filename) end end From 6f1e16c42100bc2c32a9a9d48f3277f8f5095a01 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Thu, 13 Jan 2011 11:27:24 -0800 Subject: [PATCH 064/219] Rename parameter 'since' to 'after' --- lib/scm/adapters/bzr/commits.rb | 32 +++++++-------- lib/scm/adapters/cvs/commits.rb | 30 +++++++------- lib/scm/adapters/git/commits.rb | 12 +++--- lib/scm/adapters/git/pull.rb | 4 +- lib/scm/adapters/hg/commits.rb | 40 +++++++++---------- lib/scm/adapters/svn/commits.rb | 32 +++++++-------- lib/scm/adapters/svn_chain/chain.rb | 24 ++++++------ lib/scm/adapters/svn_chain/commits.rb | 12 +++--- lib/scm/adapters/svn_chain_adapter.rb | 2 +- test/unit/bzr_commits_test.rb | 16 ++++---- test/unit/cvs_commits_test.rb | 6 +-- test/unit/git_commits_test.rb | 26 ++++++------- test/unit/git_rev_list_test.rb | 4 +- test/unit/hg_commits_test.rb | 14 +++---- test/unit/hg_rev_list_test.rb | 2 +- test/unit/svn_chain_commits_test.rb | 56 +++++++++++++-------------- test/unit/svn_commits_test.rb | 14 +++---- 17 files changed, 163 insertions(+), 163 deletions(-) diff --git a/lib/scm/adapters/bzr/commits.rb b/lib/scm/adapters/bzr/commits.rb index 10ec609d..d3ee64bb 100644 --- a/lib/scm/adapters/bzr/commits.rb +++ b/lib/scm/adapters/bzr/commits.rb @@ -1,19 +1,19 @@ module Scm::Adapters class BzrAdapter < AbstractAdapter - # Return the number of commits in the repository following +since+. + # Return the number of commits in the repository following +after+. def commit_count(opts={}) commit_tokens(opts).size end - # Return the list of commit tokens following +since+. + # Return the list of commit tokens following +after+. def commit_tokens(opts={}) - since = opts[:since] + after = opts[:after] tokens = run("#{rev_list_command(opts)} | grep -E -e '^( *)revision-id: ' | cut -f2 -d':' | cut -c 2-").split("\n") - # Bzr returns everything after *and including* since. + # Bzr returns everything after *and including* after. # We want to exclude it. - if tokens.any? && tokens.first == since + if tokens.any? && tokens.first == after tokens[1..-1] else tokens @@ -26,11 +26,11 @@ def commit_tokens(opts={}) # including diffs, you should use the each_commit() iterator, # which only holds one commit in memory at a time. def commits(opts={}) - since = opts[:since] + after = opts[:after] log = run("#{rev_list_command(opts)} | cat") a = Scm::Parsers::BzrParser.parse(log) - if a.any? && a.first.token == since + if a.any? && a.first.token == after a[1..-1] else a @@ -43,16 +43,16 @@ def verbose_commit(token) Scm::Parsers::BzrParser.parse(log).first end - # Yields each commit after +since+, including its diffs. + # Yields each commit after +after+, including its diffs. # The log is stored in a temporary file. # This is designed to prevent excessive RAM usage when we # encounter a massive repository. Only a single commit is ever # held in memory at once. def each_commit(opts={}) - since = opts[:since] + after = opts[:after] open_log_file(opts) do |io| Scm::Parsers::BzrParser.parse(io) do |commit| - yield remove_directories(commit) if block_given? && commit.token != since + yield remove_directories(commit) if block_given? && commit.token != after end end end @@ -72,13 +72,13 @@ def log(opts={}) # Returns a file handle to the log. # In our standard, the log should include everything AFTER - # +since+. However, bzr doesn't work that way; it returns - # everything after and INCLUDING +since+. Therefore, consumers + # +after+. However, bzr doesn't work that way; it returns + # everything after and INCLUDING +after+. Therefore, consumers # of this file should check for and reject the duplicate commit. def open_log_file(opts={}) - since = opts[:since] + after = opts[:after] begin - if since == head_token # There are no new commits + if after == head_token # There are no new commits # As a time optimization, just create an empty # file rather than fetch a log we know will be empty. File.open(log_filename, 'w') { } @@ -96,8 +96,8 @@ def log_filename end def rev_list_command(opts={}) - since = opts[:since] - "cd '#{self.url}' && bzr log --long --show-id --forward --include-merges -r #{to_rev_param(since)}.." + after = opts[:after] + "cd '#{self.url}' && bzr log --long --show-id --forward --include-merges -r #{to_rev_param(after)}.." end end end diff --git a/lib/scm/adapters/cvs/commits.rb b/lib/scm/adapters/cvs/commits.rb index fc476a2b..bfb9dd1f 100644 --- a/lib/scm/adapters/cvs/commits.rb +++ b/lib/scm/adapters/cvs/commits.rb @@ -1,7 +1,7 @@ module Scm::Adapters class CvsAdapter def commits(opts={}) - since = opts[:since] + after = opts[:after] result = [] open_log_file(opts) do |io| @@ -12,23 +12,23 @@ def commits(opts={}) result.each { |c| c.scm = self } return result if result.size == 0 # Nothing found; we're done here. - return result if since.to_s == '' # We requested everything, so just return everything. + return result if after.to_s == '' # We requested everything, so just return everything. # We must now remove any duplicates caused by timestamp fudge factors, - # and only return commits with timestamp > since. + # and only return commits with timestamp > after. - # If the first commit is newer than since, then the whole list is new and we can simply return. - return result if parse_time(result.first.token) > parse_time(since) + # If the first commit is newer than after, then the whole list is new and we can simply return. + return result if parse_time(result.first.token) > parse_time(after) # Walk the list of commits to find the first new one, throwing away all of the old ones. # I want to string-compare timestamps without converting to dates objects (I think it's faster). # Some CVS servers print dates as 2006/01/02 03:04:05, others as 2006-01-02 03:04:05. # To work around this, we'll build a regex that matches either date format. - re = Regexp.new(since.gsub(/[\/-]/, '.')) + re = Regexp.new(after.gsub(/[\/-]/, '.')) result.each_index do |i| - if result[i].token =~ re # We found the match for since + if result[i].token =~ re # We found the match for after if i == result.size-1 return [] # There aren't any new commits. else @@ -37,7 +37,7 @@ def commits(opts={}) end end - # Something bad is going on: 'since' does not match any timestamp in the rlog. + # Something bad is going on: 'after' does not match any timestamp in the rlog. # This is very rare, but it can happen. # # Often this means that the *last* time we ran commits(), there was some kind of @@ -46,8 +46,8 @@ def commits(opts={}) # # There's no work around for this condition here in the code, but there are some things # you can try manually to fix the problem. Typically, you can try throwing way the - # commit associated with 'since' and fetching it again (git reset --hard HEAD^). - raise RuntimeError.new("token '#{since}' not found in rlog.") + # commit associated with 'after' and fetching it again (git reset --hard HEAD^). + raise RuntimeError.new("token '#{after}' not found in rlog.") end # Gets the rlog of the repository and saves it in a temporary file. @@ -60,10 +60,10 @@ def commits(opts={}) # This means that the returned log might actually contain a few revisions that predate the requested time. # That's better than missing revisions completely! Just be sure to check for duplicates. def open_log_file(opts={}) - since = opts[:since] + after = opts[:after] begin ensure_host_key - run "cvsnt -d #{self.url} rlog #{opt_branch} #{opt_time(since)} '#{self.module_name}' > #{rlog_filename}" + run "cvsnt -d #{self.url} rlog #{opt_branch} #{opt_time(after)} '#{self.module_name}' > #{rlog_filename}" File.open(rlog_filename, 'r') do |file| yield file end @@ -72,9 +72,9 @@ def open_log_file(opts={}) end end - def opt_time(since=nil) - if since - most_recent_time = parse_time(since) - 10 + def opt_time(after=nil) + if after + most_recent_time = parse_time(after) - 10 " -d '#{most_recent_time.strftime('%Y-%m-%d %H:%M:%S')}Z<#{Time.now.utc.strftime('%Y-%m-%d %H:%M:%S')}Z' " else "" diff --git a/lib/scm/adapters/git/commits.rb b/lib/scm/adapters/git/commits.rb index 5d41bb26..9a13394a 100644 --- a/lib/scm/adapters/git/commits.rb +++ b/lib/scm/adapters/git/commits.rb @@ -1,17 +1,17 @@ module Scm::Adapters class GitAdapter < AbstractAdapter - # Returns the number of commits in the repository following the commit with SHA1 'since'. + # Returns the number of commits in the repository following the commit with SHA1 'after'. def commit_count(opts={}) run("#{rev_list_command(opts)} | wc -l").to_i end - # Returns the SHA1 hash for every commit in the repository following the commit with SHA1 'since'. + # Returns the SHA1 hash for every commit in the repository following the commit with SHA1 'after'. def commit_tokens(opts={}) run(rev_list_command(opts)).split("\n") end - # Yields each commit following the commit with SHA1 'since'. + # Yields each commit following the commit with SHA1 'after'. # Officially, this method isn't required to provide diffs with these commits, # and the Subversion equivalent of this method does not, # so if you really require the diffs you should be using each_commit() instead. @@ -21,7 +21,7 @@ def commits(opts={}) result end - # Yields each commit in the repository following the commit with SHA1 'since'. + # Yields each commit in the repository following the commit with SHA1 'after'. # These commits are populated with diffs. def each_commit(opts={}) @@ -55,7 +55,7 @@ def verbose_commit(token) # We get the log forward chronological order (oldest first) def log(opts={}) if has_branch? - if opts[:since] && opts[:since]==self.head_token + if opts[:after] && opts[:after]==self.head_token '' # Nothing new. else run "#{rev_list_command(opts)} | xargs -n 1 #{Scm::Parsers::GitStyledParser.whatchanged}" @@ -67,7 +67,7 @@ def log(opts={}) def rev_list_command(opts={}) up_to = opts[:up_to] || branch_name - range = opts[:since] ? "#{opts[:since]}..#{up_to}" : up_to + range = opts[:after] ? "#{opts[:after]}..#{up_to}" : up_to trunk_only = opts[:trunk_only] ? "--first-parent" : "" diff --git a/lib/scm/adapters/git/pull.rb b/lib/scm/adapters/git/pull.rb index 27cbf5a5..6ea560f4 100644 --- a/lib/scm/adapters/git/pull.rb +++ b/lib/scm/adapters/git/pull.rb @@ -71,8 +71,8 @@ def clone_or_fetch(source_scm) def convert(source_scm) yield(0,1) if block_given? # Progress bar callback - # Any new work to be done since last time we were here? - commits = source_scm.commits(:since => read_token) + # Any new work to be done since the last time we were here? + commits = source_scm.commits(:after => read_token) if commits and commits.size > 0 # Start by making sure we are in a known good state. Set up our working directory. clean_up_disk diff --git a/lib/scm/adapters/hg/commits.rb b/lib/scm/adapters/hg/commits.rb index 864b61f6..981b2677 100644 --- a/lib/scm/adapters/hg/commits.rb +++ b/lib/scm/adapters/hg/commits.rb @@ -1,24 +1,24 @@ module Scm::Adapters class HgAdapter < AbstractAdapter - # Return the number of commits in the repository following +since+. + # Return the number of commits in the repository following +after+. def commit_count(opts={}) commit_tokens(opts).size end - # Return the list of commit tokens following +since+. + # Return the list of commit tokens following +after+. def commit_tokens(opts={}) - since = opts[:since] || 0 + after = opts[:after] || 0 up_to = opts[:up_to] || 'tip' # We reverse the final result in Ruby, rather than passing the --reverse flag to hg. # That's because the -f (follow) flag doesn't behave the same in both directions. # Basically, we're trying very hard to make this act just like Git. The hg_rev_list_test checks this. - tokens = run("cd '#{self.url}' && hg log -f -r #{up_to || 'tip'}:#{since || 0} --template='{node}\\n'").split("\n").reverse + tokens = run("cd '#{self.url}' && hg log -f -r #{up_to || 'tip'}:#{after || 0} --template='{node}\\n'").split("\n").reverse - # Hg returns everything after *and including* since. + # Hg returns everything after *and including* after. # We want to exclude it. - if tokens.any? && tokens.first == since + if tokens.any? && tokens.first == after tokens[1..-1] else tokens @@ -30,12 +30,12 @@ def commit_tokens(opts={}) # If you need all commits including diffs, you should use the each_commit() iterator, which only holds one commit # in memory at a time. def commits(opts={}) - since = opts[:since] || 0 + after = opts[:after] || 0 - log = run("cd '#{self.url}' && hg log -f -v -r tip:#{since} --style #{Scm::Parsers::HgStyledParser.style_path}") + log = run("cd '#{self.url}' && hg log -f -v -r tip:#{after} --style #{Scm::Parsers::HgStyledParser.style_path}") a = Scm::Parsers::HgStyledParser.parse(log).reverse - if a.any? && a.first.token == since + if a.any? && a.first.token == after a[1..-1] else a @@ -48,37 +48,37 @@ def verbose_commit(token) Scm::Parsers::HgStyledParser.parse(log).first end - # Yields each commit after +since+, including its diffs. + # Yields each commit after +after+, including its diffs. # The log is stored in a temporary file. # This is designed to prevent excessive RAM usage when we encounter a massive repository. # Only a single commit is ever held in memory at once. def each_commit(opts={}) - since = opts[:since] || 0 - open_log_file(since) do |io| + after = opts[:after] || 0 + open_log_file(after) do |io| Scm::Parsers::HgStyledParser.parse(io) do |commit| - yield commit if block_given? && commit.token != since + yield commit if block_given? && commit.token != after end end end # Not used by Ohloh proper, but handy for debugging and testing def log(opts={}) - since = opts[:since] || 0 - run "cd '#{url}' && hg log -f -v -r tip:#{since}" + after = opts[:after] || 0 + run "cd '#{url}' && hg log -f -v -r tip:#{after}" end # Returns a file handle to the log. - # In our standard, the log should include everything AFTER +since+. However, hg doesn't work that way; - # it returns everything after and INCLUDING +since+. Therefore, consumers of this file should check for + # In our standard, the log should include everything AFTER +after+. However, hg doesn't work that way; + # it returns everything after and INCLUDING +after+. Therefore, consumers of this file should check for # and reject the duplicate commit. def open_log_file(opts={}) - since = opts[:since] || 0 + after = opts[:after] || 0 begin - if since == head_token # There are no new commits + if after == head_token # There are no new commits # As a time optimization, just create an empty file rather than fetch a log we know will be empty. File.open(log_filename, 'w') { } else - run "cd '#{url}' && hg log --verbose -r #{since || 0}:tip --style #{Scm::Parsers::HgStyledParser.verbose_style_path} > #{log_filename}" + run "cd '#{url}' && hg log --verbose -r #{after || 0}:tip --style #{Scm::Parsers::HgStyledParser.verbose_style_path} > #{log_filename}" end File.open(log_filename, 'r') { |io| yield io } ensure diff --git a/lib/scm/adapters/svn/commits.rb b/lib/scm/adapters/svn/commits.rb index 897c239c..a3412311 100644 --- a/lib/scm/adapters/svn/commits.rb +++ b/lib/scm/adapters/svn/commits.rb @@ -3,7 +3,7 @@ module Scm::Adapters class SvnAdapter < AbstractAdapter - # In all commit- and log-related methods, 'since' refers to the revision + # In all commit- and log-related methods, 'after' refers to the revision # number of the last known commit, and the methods return the commits # *following* this commit. # @@ -19,22 +19,22 @@ class SvnAdapter < AbstractAdapter # this adapter ever return information regarding commits after this point. attr_accessor :final_token - # Returns the count of commits following revision number 'since'. + # Returns the count of commits following revision number 'after'. def commit_count(opts={}) - since = (opts[:since] || 0).to_i - return 0 if final_token && since >= final_token - run("svn log --trust-server-cert --non-interactive -q -r #{since.to_i + 1}:#{final_token || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{final_token || 'HEAD'}' | grep -E -e '^r[0-9]+ ' | wc -l").strip.to_i + after = (opts[:after] || 0).to_i + return 0 if final_token && after >= final_token + run("svn log --trust-server-cert --non-interactive -q -r #{after.to_i + 1}:#{final_token || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{final_token || 'HEAD'}' | grep -E -e '^r[0-9]+ ' | wc -l").strip.to_i end - # Returns an array of revision numbers for all commits following revision number 'since'. + # Returns an array of revision numbers for all commits following revision number 'after'. def commit_tokens(opts={}) - since = (opts[:since] || 0).to_i - return [] if final_token && since >= final_token - cmd = "svn log --trust-server-cert --non-interactive -q -r #{since + 1}:#{final_token || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{final_token || 'HEAD'}' | grep -E -e '^r[0-9]+ ' | cut -f 1 -d '|' | cut -c 2-" + after = (opts[:after] || 0).to_i + return [] if final_token && after >= final_token + cmd = "svn log --trust-server-cert --non-interactive -q -r #{after + 1}:#{final_token || 'HEAD'} --stop-on-copy '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{final_token || 'HEAD'}' | grep -E -e '^r[0-9]+ ' | cut -f 1 -d '|' | cut -c 2-" run(cmd).split.collect { |r| r.to_i } end - # Returns an array of commits following revision number 'since'. + # Returns an array of commits following revision number 'after'. # These commit objects do not include diffs. def commits(opts={}) list = [] @@ -44,7 +44,7 @@ def commits(opts={}) list.each { |c| c.scm = self } end - # Yields each commit following revision number 'since'. These commit object are populated with diffs. + # Yields each commit following revision number 'after'. These commit object are populated with diffs. # # With Subversion, populating the diffs can be tricky because when an entire directory is affected, # Subversion abbreviates the log by simply listing the directory name, rather than all of the directory @@ -143,18 +143,18 @@ def verbose_commit(rev) #--------------------------------------------------------------------- def log(opts={}) - since = (opts[:since] || 0).to_i - run "svn log --trust-server-cert --non-interactive --xml --stop-on-copy -r #{since.to_i + 1}:#{final_token || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name.to_s))}@#{final_token || 'HEAD'}' #{opt_auth}" + after = (opts[:after] || 0).to_i + run "svn log --trust-server-cert --non-interactive --xml --stop-on-copy -r #{after.to_i + 1}:#{final_token || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name.to_s))}@#{final_token || 'HEAD'}' #{opt_auth}" end def open_log_file(opts={}) - since = (opts[:since] || 0).to_i + after = (opts[:after] || 0).to_i begin - if (final_token && since >= final_token) || since >= head_token + if (final_token && after >= final_token) || after >= head_token # As a time optimization, just create an empty file rather than fetch a log we know will be empty. File.open(log_filename, 'w') { |f| f.puts '' } else - run "svn log --trust-server-cert --non-interactive --xml --stop-on-copy -r #{since + 1}:#{final_token || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}' #{opt_auth} > #{log_filename}" + run "svn log --trust-server-cert --non-interactive --xml --stop-on-copy -r #{after + 1}:#{final_token || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}' #{opt_auth} > #{log_filename}" end File.open(log_filename, 'r') { |io| yield io } ensure diff --git a/lib/scm/adapters/svn_chain/chain.rb b/lib/scm/adapters/svn_chain/chain.rb index b3377d85..af23523b 100644 --- a/lib/scm/adapters/svn_chain/chain.rb +++ b/lib/scm/adapters/svn_chain/chain.rb @@ -9,14 +9,14 @@ def chain # If this adapter's branch was created by copying or renaming another branch, # then return a new adapter that points to that prior branch. # - # Only commits following +since+ are considered, so if the copy or rename - # occured on or before +since+, then no parent will be found or returned. - def parent_svn(since=0) + # Only commits following +after+ are considered, so if the copy or rename + # occured on or before +after+, then no parent will be found or returned. + def parent_svn(after=0) @parent_svn ||={} # Poor man's memoize - @parent_svn[since] ||= begin + @parent_svn[after] ||= begin parent = nil - c = first_commit(since) + c = first_commit(after) if c # === Long explanation of real head-scratching bug fix. === # @@ -66,20 +66,20 @@ def parent_svn(since=0) end end - def first_token(since=0) - c = first_commit(since) + def first_token(after=0) + c = first_commit(after) c && c.token end - def first_commit(since=0) + def first_commit(after=0) @first_commit ||={} # Poor man's memoize - @first_commit[since] ||= Scm::Parsers::SvnXmlParser.parse(next_revision_xml(since)).first + @first_commit[after] ||= Scm::Parsers::SvnXmlParser.parse(next_revision_xml(after)).first end # Returns the first commit with a revision number greater than the provided revision number - def next_revision_xml(since=0) - return "" if since.to_i >= head_token - run "svn log --trust-server-cert --non-interactive --verbose --xml --stop-on-copy -r #{since.to_i+1}:#{final_token || 'HEAD'} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}'" + def next_revision_xml(after=0) + return "" if after.to_i >= head_token + run "svn log --trust-server-cert --non-interactive --verbose --xml --stop-on-copy -r #{after.to_i+1}:#{final_token || 'HEAD'} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}'" end # If the passed diff represents the wholesale movement of the entire diff --git a/lib/scm/adapters/svn_chain/commits.rb b/lib/scm/adapters/svn_chain/commits.rb index c4672c6f..f3ea371c 100644 --- a/lib/scm/adapters/svn_chain/commits.rb +++ b/lib/scm/adapters/svn_chain/commits.rb @@ -1,19 +1,19 @@ module Scm::Adapters class SvnChainAdapter < SvnAdapter - # Returns the count of commits following revision number 'since'. + # Returns the count of commits following revision number 'after'. def commit_count(opts={}) - (parent_svn(opts[:since]) ? parent_svn(opts[:since]).commit_count(opts) : 0) + super(opts) + (parent_svn(opts[:after]) ? parent_svn(opts[:after]).commit_count(opts) : 0) + super(opts) end - # Returns an array of revision numbers for all commits following revision number 'since'. + # Returns an array of revision numbers for all commits following revision number 'after'. def commit_tokens(opts={}) - (parent_svn(opts[:since]) ? parent_svn(opts[:since]).commit_tokens(opts) : []) + super(opts) + (parent_svn(opts[:after]) ? parent_svn(opts[:after]).commit_tokens(opts) : []) + super(opts) end - # Returns an array of commits following revision number 'since'. + # Returns an array of commits following revision number 'after'. def commits(opts={}) - (parent_svn(opts[:since]) ? parent_svn(opts[:since]).commits(opts) : []) + super(opts) + (parent_svn(opts[:after]) ? parent_svn(opts[:after]).commits(opts) : []) + super(opts) end def verbose_commit(rev=0) diff --git a/lib/scm/adapters/svn_chain_adapter.rb b/lib/scm/adapters/svn_chain_adapter.rb index 674e6f0e..4d6cf6c2 100644 --- a/lib/scm/adapters/svn_chain_adapter.rb +++ b/lib/scm/adapters/svn_chain_adapter.rb @@ -7,7 +7,7 @@ module Scm::Adapters # # The problem with this is that directories often get moved about. What is # called "/trunk" today might have been in a branch directory at some point - # in the past. But since we completely ignore other directories, we never see + # in the past. But after we completely ignore other directories, we never see # that old history. # # Suppose for example that from revisions 1 to 100, development occured in diff --git a/test/unit/bzr_commits_test.rb b/test/unit/bzr_commits_test.rb index 8005543f..1c9da7dc 100644 --- a/test/unit/bzr_commits_test.rb +++ b/test/unit/bzr_commits_test.rb @@ -6,9 +6,9 @@ class BzrCommitsTest < Scm::Test def test_commit_count with_bzr_repository('bzr') do |bzr| assert_equal 6, bzr.commit_count - assert_equal 5, bzr.commit_count(:since => revision_ids.first) - assert_equal 1, bzr.commit_count(:since => revision_ids[4]) - assert_equal 0, bzr.commit_count(:since => revision_ids.last) + assert_equal 5, bzr.commit_count(:after => revision_ids.first) + assert_equal 1, bzr.commit_count(:after => revision_ids[4]) + assert_equal 0, bzr.commit_count(:after => revision_ids.last) end end @@ -22,17 +22,17 @@ def test_commit_count_with_branches def test_commit_tokens with_bzr_repository('bzr') do |bzr| assert_equal revision_ids, bzr.commit_tokens - assert_equal revision_ids[1..5], bzr.commit_tokens(:since => revision_ids.first) - assert_equal revision_ids[5..5], bzr.commit_tokens(:since => revision_ids[4]) - assert_equal [], bzr.commit_tokens(:since => revision_ids.last) + assert_equal revision_ids[1..5], bzr.commit_tokens(:after => revision_ids.first) + assert_equal revision_ids[5..5], bzr.commit_tokens(:after => revision_ids[4]) + assert_equal [], bzr.commit_tokens(:after => revision_ids.last) end end def test_commits with_bzr_repository('bzr') do |bzr| assert_equal revision_ids, bzr.commits.collect { |c| c.token } - assert_equal revision_ids[5..5], bzr.commits(:since => revision_ids[4]).collect { |c| c.token } - assert_equal [], bzr.commits(:since => revision_ids.last).collect { |c| c.token } + assert_equal revision_ids[5..5], bzr.commits(:after => revision_ids[4]).collect { |c| c.token } + assert_equal [], bzr.commits(:after => revision_ids.last).collect { |c| c.token } # Check that the diffs are not populated assert_equal [], bzr.commits.first.diffs diff --git a/test/unit/cvs_commits_test.rb b/test/unit/cvs_commits_test.rb index 8497aff1..944b5a80 100644 --- a/test/unit/cvs_commits_test.rb +++ b/test/unit/cvs_commits_test.rb @@ -14,14 +14,14 @@ def test_commits assert_equal ['2006/06/29 18:48:54', '2006/06/29 18:52:23'], - cvs.commits(:since => '2006/06/29 18:45:29').collect { |c| c.token } + cvs.commits(:after => '2006/06/29 18:45:29').collect { |c| c.token } # Make sure we are date format agnostic (2008/01/01 is the same as 2008-01-01) assert_equal ['2006/06/29 18:48:54', '2006/06/29 18:52:23'], - cvs.commits(:since => '2006-06-29 18:45:29').collect { |c| c.token } + cvs.commits(:after => '2006-06-29 18:45:29').collect { |c| c.token } - assert_equal [], cvs.commits(:since => '2006/06/29 18:52:23').collect { |c| c.token } + assert_equal [], cvs.commits(:after => '2006/06/29 18:52:23').collect { |c| c.token } end end diff --git a/test/unit/git_commits_test.rb b/test/unit/git_commits_test.rb index 2a3457e8..54e4c516 100644 --- a/test/unit/git_commits_test.rb +++ b/test/unit/git_commits_test.rb @@ -6,8 +6,8 @@ class GitCommitsTest < Scm::Test def test_commit_count with_git_repository('git') do |git| assert_equal 4, git.commit_count - assert_equal 2, git.commit_count(:since => 'b6e9220c3cabe53a4ed7f32952aeaeb8a822603d') - assert_equal 0, git.commit_count(:since => '1df547800dcd168e589bb9b26b4039bff3a7f7e4') + assert_equal 2, git.commit_count(:after => 'b6e9220c3cabe53a4ed7f32952aeaeb8a822603d') + assert_equal 0, git.commit_count(:after => '1df547800dcd168e589bb9b26b4039bff3a7f7e4') end end @@ -19,9 +19,9 @@ def test_commit_tokens '1df547800dcd168e589bb9b26b4039bff3a7f7e4'], git.commit_tokens assert_equal ['1df547800dcd168e589bb9b26b4039bff3a7f7e4'], - git.commit_tokens(:since => '2e9366dd7a786fdb35f211fff1c8ea05c51968b1') + git.commit_tokens(:after => '2e9366dd7a786fdb35f211fff1c8ea05c51968b1') - assert_equal [], git.commit_tokens(:since => '1df547800dcd168e589bb9b26b4039bff3a7f7e4') + assert_equal [], git.commit_tokens(:after => '1df547800dcd168e589bb9b26b4039bff3a7f7e4') end end @@ -33,9 +33,9 @@ def test_commits '1df547800dcd168e589bb9b26b4039bff3a7f7e4'], git.commits.collect { |c| c.token } assert_equal ['1df547800dcd168e589bb9b26b4039bff3a7f7e4'], - git.commits(:since => '2e9366dd7a786fdb35f211fff1c8ea05c51968b1').collect { |c| c.token } + git.commits(:after => '2e9366dd7a786fdb35f211fff1c8ea05c51968b1').collect { |c| c.token } - assert_equal [], git.commits(:since => '1df547800dcd168e589bb9b26b4039bff3a7f7e4') + assert_equal [], git.commits(:after => '1df547800dcd168e589bb9b26b4039bff3a7f7e4') end end @@ -62,17 +62,17 @@ def test_trunk_only_commit_tokens end end - def test_trunk_only_commit_tokens_using_since + def test_trunk_only_commit_tokens_using_after with_git_repository('git_dupe_delete') do |git| assert_equal ['ad6bb43112706c462e53a9a8a8cd3b05f8e9260f', '41c4b1044ebffc968d363e5f5e883134e624f846'], git.commit_tokens( - :since => 'a0a2b8623941562031a7d7f95d984feb4a2d719c', + :after => 'a0a2b8623941562031a7d7f95d984feb4a2d719c', :trunk_only => true) - # All trunk commit_tokens, with :since == HEAD + # All trunk commit_tokens, with :after == HEAD assert_equal [], git.commit_tokens( - :since => '41c4b1044ebffc968d363e5f5e883134e624f846', + :after => '41c4b1044ebffc968d363e5f5e883134e624f846', :trunk_only => true) end end @@ -88,15 +88,15 @@ def test_trunk_only_commits end end - def test_trunk_only_commits_using_since + def test_trunk_only_commits_using_after with_git_repository('git_dupe_delete') do |git| assert_equal ['ad6bb43112706c462e53a9a8a8cd3b05f8e9260f', '41c4b1044ebffc968d363e5f5e883134e624f846'], - git.commits(:since => 'a0a2b8623941562031a7d7f95d984feb4a2d719c', + git.commits(:after => 'a0a2b8623941562031a7d7f95d984feb4a2d719c', :trunk_only => true).collect { |c| c.token } assert_equal [], git.commit_tokens( - :since => '41c4b1044ebffc968d363e5f5e883134e624f846', + :after => '41c4b1044ebffc968d363e5f5e883134e624f846', :trunk_only => true) end end diff --git a/test/unit/git_rev_list_test.rb b/test/unit/git_rev_list_test.rb index 693b2fbd..184720fd 100644 --- a/test/unit/git_rev_list_test.rb +++ b/test/unit/git_rev_list_test.rb @@ -53,11 +53,11 @@ def test_trunk_only_rev_list protected def rev_list_helper(git, from, to) - to_labels(git.commit_tokens(:since => from_label(from), :up_to => from_label(to))) + to_labels(git.commit_tokens(:after => from_label(from), :up_to => from_label(to))) end def rev_list_trunk(git, from, to) - to_labels(git.commit_tokens(:since => from_label(from), :up_to => from_label(to), + to_labels(git.commit_tokens(:after => from_label(from), :up_to => from_label(to), :trunk_only => true)) end diff --git a/test/unit/hg_commits_test.rb b/test/unit/hg_commits_test.rb index 439882ed..7dd2e0aa 100644 --- a/test/unit/hg_commits_test.rb +++ b/test/unit/hg_commits_test.rb @@ -6,8 +6,8 @@ class HgCommitsTest < Scm::Test def test_commit with_hg_repository('hg') do |hg| assert_equal 4, hg.commit_count - assert_equal 2, hg.commit_count(:since => 'b14fa4692f949940bd1e28da6fb4617de2615484') - assert_equal 0, hg.commit_count(:since => '75532c1e1f1de55c2271f6fd29d98efbe35397c4') + assert_equal 2, hg.commit_count(:after => 'b14fa4692f949940bd1e28da6fb4617de2615484') + assert_equal 0, hg.commit_count(:after => '75532c1e1f1de55c2271f6fd29d98efbe35397c4') assert_equal ['01101d8ef3cea7da9ac6e9a226d645f4418f05c9', 'b14fa4692f949940bd1e28da6fb4617de2615484', @@ -15,9 +15,9 @@ def test_commit '75532c1e1f1de55c2271f6fd29d98efbe35397c4'], hg.commit_tokens assert_equal ['75532c1e1f1de55c2271f6fd29d98efbe35397c4'], - hg.commit_tokens(:since => '468336c6671cbc58237a259d1b7326866afc2817') + hg.commit_tokens(:after => '468336c6671cbc58237a259d1b7326866afc2817') - assert_equal [], hg.commit_tokens(:since => '75532c1e1f1de55c2271f6fd29d98efbe35397c4') + assert_equal [], hg.commit_tokens(:after => '75532c1e1f1de55c2271f6fd29d98efbe35397c4') assert_equal ['01101d8ef3cea7da9ac6e9a226d645f4418f05c9', 'b14fa4692f949940bd1e28da6fb4617de2615484', @@ -25,12 +25,12 @@ def test_commit '75532c1e1f1de55c2271f6fd29d98efbe35397c4'], hg.commits.collect { |c| c.token } assert_equal ['75532c1e1f1de55c2271f6fd29d98efbe35397c4'], - hg.commits(:since => '468336c6671cbc58237a259d1b7326866afc2817').collect { |c| c.token } + hg.commits(:after => '468336c6671cbc58237a259d1b7326866afc2817').collect { |c| c.token } # Check that the diffs are not populated - assert_equal [], hg.commits(:since => '468336c6671cbc58237a259d1b7326866afc2817').first.diffs + assert_equal [], hg.commits(:after => '468336c6671cbc58237a259d1b7326866afc2817').first.diffs - assert_equal [], hg.commits(:since => '75532c1e1f1de55c2271f6fd29d98efbe35397c4') + assert_equal [], hg.commits(:after => '75532c1e1f1de55c2271f6fd29d98efbe35397c4') end end diff --git a/test/unit/hg_rev_list_test.rb b/test/unit/hg_rev_list_test.rb index 389870d3..a0250df1 100644 --- a/test/unit/hg_rev_list_test.rb +++ b/test/unit/hg_rev_list_test.rb @@ -33,7 +33,7 @@ def test_rev_list protected def rev_list_helper(hg, from, to) - to_labels(hg.commit_tokens(:since => from_label(from), :up_to => from_label(to))) + to_labels(hg.commit_tokens(:after => from_label(from), :up_to => from_label(to))) end def commit_labels diff --git a/test/unit/svn_chain_commits_test.rb b/test/unit/svn_chain_commits_test.rb index 897d12e7..5ceaaa6c 100644 --- a/test/unit/svn_chain_commits_test.rb +++ b/test/unit/svn_chain_commits_test.rb @@ -6,46 +6,46 @@ class SvnChainTest < Scm::Test def test_chained_commit_tokens with_svn_chain_repository('svn_with_branching', '/trunk') do |svn| assert_equal [1,2,4,5,8,9], svn.commit_tokens - assert_equal [2,4,5,8,9], svn.commit_tokens(:since => 1) - assert_equal [4,5,8,9], svn.commit_tokens(:since => 2) - assert_equal [4,5,8,9], svn.commit_tokens(:since => 3) - assert_equal [5,8,9], svn.commit_tokens(:since => 4) - assert_equal [8,9], svn.commit_tokens(:since => 5) - assert_equal [8,9], svn.commit_tokens(:since => 6) - assert_equal [8,9], svn.commit_tokens(:since => 7) - assert_equal [9], svn.commit_tokens(:since => 8) - assert_equal [], svn.commit_tokens(:since => 9) - assert_equal [], svn.commit_tokens(:since => 10) + assert_equal [2,4,5,8,9], svn.commit_tokens(:after => 1) + assert_equal [4,5,8,9], svn.commit_tokens(:after => 2) + assert_equal [4,5,8,9], svn.commit_tokens(:after => 3) + assert_equal [5,8,9], svn.commit_tokens(:after => 4) + assert_equal [8,9], svn.commit_tokens(:after => 5) + assert_equal [8,9], svn.commit_tokens(:after => 6) + assert_equal [8,9], svn.commit_tokens(:after => 7) + assert_equal [9], svn.commit_tokens(:after => 8) + assert_equal [], svn.commit_tokens(:after => 9) + assert_equal [], svn.commit_tokens(:after => 10) end end def test_chained_commit_count with_svn_chain_repository('svn_with_branching', '/trunk') do |svn| assert_equal 6, svn.commit_count - assert_equal 5, svn.commit_count(:since => 1) - assert_equal 4, svn.commit_count(:since => 2) - assert_equal 4, svn.commit_count(:since => 3) - assert_equal 3, svn.commit_count(:since => 4) - assert_equal 2, svn.commit_count(:since => 5) - assert_equal 2, svn.commit_count(:since => 6) - assert_equal 2, svn.commit_count(:since => 7) - assert_equal 1, svn.commit_count(:since => 8) - assert_equal 0, svn.commit_count(:since => 9) + assert_equal 5, svn.commit_count(:after => 1) + assert_equal 4, svn.commit_count(:after => 2) + assert_equal 4, svn.commit_count(:after => 3) + assert_equal 3, svn.commit_count(:after => 4) + assert_equal 2, svn.commit_count(:after => 5) + assert_equal 2, svn.commit_count(:after => 6) + assert_equal 2, svn.commit_count(:after => 7) + assert_equal 1, svn.commit_count(:after => 8) + assert_equal 0, svn.commit_count(:after => 9) end end def test_chained_commits with_svn_chain_repository('svn_with_branching', '/trunk') do |svn| assert_equal [1,2,4,5,8,9], svn.commits.collect { |c| c.token } - assert_equal [2,4,5,8,9], svn.commits(:since => 1).collect { |c| c.token } - assert_equal [4,5,8,9], svn.commits(:since => 2).collect { |c| c.token } - assert_equal [4,5,8,9], svn.commits(:since => 3).collect { |c| c.token } - assert_equal [5,8,9], svn.commits(:since => 4).collect { |c| c.token } - assert_equal [8,9], svn.commits(:since => 5).collect { |c| c.token } - assert_equal [8,9], svn.commits(:since => 6).collect { |c| c.token } - assert_equal [8,9], svn.commits(:since => 7).collect { |c| c.token } - assert_equal [9], svn.commits(:since => 8).collect { |c| c.token } - assert_equal [], svn.commits(:since => 9).collect { |c| c.token } + assert_equal [2,4,5,8,9], svn.commits(:after => 1).collect { |c| c.token } + assert_equal [4,5,8,9], svn.commits(:after => 2).collect { |c| c.token } + assert_equal [4,5,8,9], svn.commits(:after => 3).collect { |c| c.token } + assert_equal [5,8,9], svn.commits(:after => 4).collect { |c| c.token } + assert_equal [8,9], svn.commits(:after => 5).collect { |c| c.token } + assert_equal [8,9], svn.commits(:after => 6).collect { |c| c.token } + assert_equal [8,9], svn.commits(:after => 7).collect { |c| c.token } + assert_equal [9], svn.commits(:after => 8).collect { |c| c.token } + assert_equal [], svn.commits(:after => 9).collect { |c| c.token } end end diff --git a/test/unit/svn_commits_test.rb b/test/unit/svn_commits_test.rb index b66d54af..7a16525c 100644 --- a/test/unit/svn_commits_test.rb +++ b/test/unit/svn_commits_test.rb @@ -6,16 +6,16 @@ class SvnCommitsTest < Scm::Test def test_commits with_svn_repository('svn') do |svn| assert_equal 5, svn.commit_count - assert_equal 3, svn.commit_count(:since => 2) - assert_equal 0, svn.commit_count(:since => 1000) + assert_equal 3, svn.commit_count(:after => 2) + assert_equal 0, svn.commit_count(:after => 1000) assert_equal [1,2,3,4,5], svn.commit_tokens - assert_equal [3,4,5], svn.commit_tokens(:since => 2) - assert_equal [], svn.commit_tokens(:since => 1000) + assert_equal [3,4,5], svn.commit_tokens(:after => 2) + assert_equal [], svn.commit_tokens(:after => 1000) assert_equal [1,2,3,4,5], svn.commits.collect { |c| c.token } - assert_equal [3,4,5], svn.commits(:since => 2).collect { |c| c.token } - assert_equal [], svn.commits(:since => 1000) + assert_equal [3,4,5], svn.commits(:after => 2).collect { |c| c.token } + assert_equal [], svn.commits(:after => 1000) assert !FileTest.exist?(svn.log_filename) end end @@ -147,7 +147,7 @@ def test_deep_commits # Also, our commits do not include diffs for the actual directories; # only the files within those directories. # - # Also, since we are only tracking the /trunk and not /branches/b, then + # Also, after we are only tracking the /trunk and not /branches/b, then # there should not be anything referring to activity in /branches/b. assert_equal 3, deep_commits.first.token # Make sure this is the right revision From 053d35d79b4c5b48479eb007a5b24407fccd34e0 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Thu, 13 Jan 2011 12:14:39 -0800 Subject: [PATCH 065/219] OTWO-277 Fix bug revealed by Ohloh integration test Ohloh testing revealed a bug in HgAdapter.each_commit(). I've added a unit test to cover the problem. --- lib/scm/adapters/hg/commits.rb | 2 +- test/unit/hg_commits_test.rb | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/scm/adapters/hg/commits.rb b/lib/scm/adapters/hg/commits.rb index 981b2677..41fce732 100644 --- a/lib/scm/adapters/hg/commits.rb +++ b/lib/scm/adapters/hg/commits.rb @@ -54,7 +54,7 @@ def verbose_commit(token) # Only a single commit is ever held in memory at once. def each_commit(opts={}) after = opts[:after] || 0 - open_log_file(after) do |io| + open_log_file(opts) do |io| Scm::Parsers::HgStyledParser.parse(io) do |commit| yield commit if block_given? && commit.token != after end diff --git a/test/unit/hg_commits_test.rb b/test/unit/hg_commits_test.rb index 7dd2e0aa..a58ddb42 100644 --- a/test/unit/hg_commits_test.rb +++ b/test/unit/hg_commits_test.rb @@ -59,6 +59,17 @@ def test_each_commit '75532c1e1f1de55c2271f6fd29d98efbe35397c4'], commits.collect { |c| c.token } end end + + def test_each_commit_after + commits = [] + with_hg_repository('hg') do |hg| + hg.each_commit(:after => 'b14fa4692f949940bd1e28da6fb4617de2615484') do |c| + commits << c + end + assert_equal ['468336c6671cbc58237a259d1b7326866afc2817', + '75532c1e1f1de55c2271f6fd29d98efbe35397c4'], commits.collect { |c| c.token } + end + end end end From f834f8e86aa32597743d38d8a93ae4b7b96ad150 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 25 Jan 2011 09:42:35 -0800 Subject: [PATCH 066/219] OTWO-278 Updates HgAdapter to support :trunk_only --- lib/scm/adapters/hg/commits.rb | 16 ++++-- test/repositories/hg_dupe_delete.tgz | Bin 0 -> 2399 bytes test/unit/hg_commits_test.rb | 75 ++++++++++++++++++++++++++- 3 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 test/repositories/hg_dupe_delete.tgz diff --git a/lib/scm/adapters/hg/commits.rb b/lib/scm/adapters/hg/commits.rb index 41fce732..77214a65 100644 --- a/lib/scm/adapters/hg/commits.rb +++ b/lib/scm/adapters/hg/commits.rb @@ -14,7 +14,7 @@ def commit_tokens(opts={}) # We reverse the final result in Ruby, rather than passing the --reverse flag to hg. # That's because the -f (follow) flag doesn't behave the same in both directions. # Basically, we're trying very hard to make this act just like Git. The hg_rev_list_test checks this. - tokens = run("cd '#{self.url}' && hg log -f -r #{up_to || 'tip'}:#{after || 0} --template='{node}\\n'").split("\n").reverse + tokens = run("cd '#{self.url}' && hg log -f #{trunk_only(opts)} -r #{up_to || 'tip'}:#{after || 0} --template='{node}\\n'").split("\n").reverse # Hg returns everything after *and including* after. # We want to exclude it. @@ -32,7 +32,7 @@ def commit_tokens(opts={}) def commits(opts={}) after = opts[:after] || 0 - log = run("cd '#{self.url}' && hg log -f -v -r tip:#{after} --style #{Scm::Parsers::HgStyledParser.style_path}") + log = run("cd '#{self.url}' && hg log -f #{trunk_only(opts)} -v -r tip:#{after} --style #{Scm::Parsers::HgStyledParser.style_path}") a = Scm::Parsers::HgStyledParser.parse(log).reverse if a.any? && a.first.token == after @@ -64,7 +64,7 @@ def each_commit(opts={}) # Not used by Ohloh proper, but handy for debugging and testing def log(opts={}) after = opts[:after] || 0 - run "cd '#{url}' && hg log -f -v -r tip:#{after}" + run "cd '#{url}' && hg log -f #{trunk_only(opts)} -v -r tip:#{after}" end # Returns a file handle to the log. @@ -78,7 +78,7 @@ def open_log_file(opts={}) # As a time optimization, just create an empty file rather than fetch a log we know will be empty. File.open(log_filename, 'w') { } else - run "cd '#{url}' && hg log --verbose -r #{after || 0}:tip --style #{Scm::Parsers::HgStyledParser.verbose_style_path} > #{log_filename}" + run "cd '#{url}' && hg log --verbose #{trunk_only(opts)} -r #{after || 0}:tip --style #{Scm::Parsers::HgStyledParser.verbose_style_path} > #{log_filename}" end File.open(log_filename, 'r') { |io| yield io } ensure @@ -90,5 +90,13 @@ def log_filename File.join('/tmp', (self.url).gsub(/\W/,'') + '.log') end + def trunk_only(opts={}) + if opts[:trunk_only] + '--follow-first' + else + '' + end + end + end end diff --git a/test/repositories/hg_dupe_delete.tgz b/test/repositories/hg_dupe_delete.tgz new file mode 100644 index 0000000000000000000000000000000000000000..61b3ddd708fe046727c5f1260627ed0b24f89d02 GIT binary patch literal 2399 zcmV-l383~LiwFR~2R}^!1MQm&RMb`)$45|cQwl6)w{F$-0&PLdLXycO!=eJ}_{O5g zN9&`INis88W|C|!fSvxwaINZpf6#*e9U?FIbR@VR{Sz1_`yaz~sOo=z(5nAwQY3wJ5!{FW zF$6_q|I2R()&KtB?*7jZGMEf9gU+yJF!Ahzw&8Rz?$mWF{?}=>&HazUs1DHp*q0q` zji=oInl|#E>rE$(CLq+EUEe@p$=TjJ2)09;X_qHo$LnrZ#+6KIT75#1ZP;LLFC2E} zd<5Tr&Z?5pDG}?ILF>K_c(>=iQC&i>1nv7FDH{s^c!R!Dd+GcP=~o3qi^kPX*mU6F z8q1)AgX%s;netKsW#-PsF0&Q{F7*5ktH$fRTQV*Z%Aza(!P-Tv0mQRze4cf7Lj zpVI>S9o?4rH^YvlKd!eJ3UANU6(mJr+KPc4`mNqwaJ?X9=C$&Su6bDH{Nf4Gi;jQ3 zD?e*W=FZa_nT_p27XCMz-*ReONdDCs3F4Y6>cvfiR;_u3{BV%I-(TwoIxg09JC>K- z{fiHa%i6LZ9LP^W#|-^MU;cc;TU~!PeH#?HtaP-0{rG^~UH=xwYUSgp2baErH~q_U z_Za^PR7M{AASjz>X<#E+F18z(1OZ?dSWYy>Mh$RYPH`ZI7p!#TI4-JN5;O(!XJ=JB zX;uFcNAo^v!<+tLOnYbjk7COFPm8Jg_XjX+BRST@I7E4nNAW}mhA9ilnHei@mUDDk zy(-WrnO61R?85kEc%Ac|is@AdVtCMBZ$7l6m z+a1PYXReC;eE&xqMq~LKzNy=Ev#zI+3h&&p)?oPVyDgU27tARbRdi@+|3h^_^&h=3 zt5_x-&5~?pZ?sD ztfti`6m>a}3hjl%G<$CDib{xGHqRCwHp~*5_r{GGQYQ&XTQRb{dd^W>TyA7i{uBV zMs^OlojYyPp)x$c9(QBJQPV(vd}(1q^6r`;UGj%dTy<39z_OP)(O zR>o|t+Y>fB-NW=lTSI2R!Eckb++6GH+ec)NnaowU`6}|oeumkZM*waSn+|(_x_!g0s?aL zo16NFgGk6;I9Rji%;w9_tkjV3jT?{!_OkNQMY$D+2Y0=?zvk+qdi$pdxmSmtLIWy#B0)d4D<04RUOMSw z#D8|28@V=clw;Bhb@hQiUwWxnIhSLU=1p>P&IAHAcP2vtLY;V`&(6c}mS>Ag-zlsJ zjS74Iv!*snlpd!NDHCp@VR??FgN+!8;xq~CQAAIoTFg1gr*R5_hC8JNhDcNvlM8w% zLbEC#Qp`4zwZ>Dttrvu#iHKZ*AW(qn^)L)UX^dd@$^7JLriJm}x$_fGvw}P@ivF4Z z5rpUZ4@GtA`0o!|8YEj9jpVLR|G;^JXh>aEv|O)!!`e#a@uoHX8wHZ1EWT;OtNvk6 z{p)ab|JOgzjER)2;-fZ0{srbui4_=!&)V>+f3#8m7)&^y|J0#``uvAq5SVOv zg`bT;%Bmk~*!5F)ex4Ru(7!A6TNsjd#QS6q*qiLBtM(1QMbx%5}K|MkBP#nt%l z7rgD_xlz~uPbMwsUnI>w3j7Ut)xQpFqJP|}e@uP;(?4jzy@qv2jpt7wE$H8ecYa-X zkN=40`k%m5{rigmKub1TE@<>R5P4u1m~4gj!^kbTt}8%tG$4V) z!V4nk101|0Pz*4!RtCg2JayJhKA2*Y$Km80*S-`($AgBl&P>@z4!AB}8t@!2@}fnt z-1+kp#c0Ucs58e^U&&J%Y0QxiV{<-BKm#L5WjRN`W(SZ9zsgy2n{`C7S?-6V42sU8 zaZ2Zu^8vcMzUeL(Q##BsB7hsuAk;@Whw@Xupk50LAAyQymbtqoq*0lft literal 0 HcmV?d00001 diff --git a/test/unit/hg_commits_test.rb b/test/unit/hg_commits_test.rb index a58ddb42..65f87b46 100644 --- a/test/unit/hg_commits_test.rb +++ b/test/unit/hg_commits_test.rb @@ -3,12 +3,16 @@ module Scm::Adapters class HgCommitsTest < Scm::Test - def test_commit + def test_commit_count with_hg_repository('hg') do |hg| assert_equal 4, hg.commit_count assert_equal 2, hg.commit_count(:after => 'b14fa4692f949940bd1e28da6fb4617de2615484') assert_equal 0, hg.commit_count(:after => '75532c1e1f1de55c2271f6fd29d98efbe35397c4') + end + end + def test_commit_tokens + with_hg_repository('hg') do |hg| assert_equal ['01101d8ef3cea7da9ac6e9a226d645f4418f05c9', 'b14fa4692f949940bd1e28da6fb4617de2615484', '468336c6671cbc58237a259d1b7326866afc2817', @@ -18,7 +22,11 @@ def test_commit hg.commit_tokens(:after => '468336c6671cbc58237a259d1b7326866afc2817') assert_equal [], hg.commit_tokens(:after => '75532c1e1f1de55c2271f6fd29d98efbe35397c4') + end + end + def test_commits + with_hg_repository('hg') do |hg| assert_equal ['01101d8ef3cea7da9ac6e9a226d645f4418f05c9', 'b14fa4692f949940bd1e28da6fb4617de2615484', '468336c6671cbc58237a259d1b7326866afc2817', @@ -34,6 +42,71 @@ def test_commit end end + def test_trunk_only_commits + with_hg_repository('hg_dupe_delete') do |hg| + assert_equal ['73e93f57224e3fd828cf014644db8eec5013cd6b', + '732345b1d5f4076498132fd4b965b1fec0108a50', + # '525de321d8085bc1d4a3c7608fda6b4020027985', # On branch + '72fe74d643bdcb30b00da3b58796c50f221017d0'], + hg.commits(:trunk_only => true).collect { |c| c.token } + end + end + + def test_trunk_only_commit_count + with_hg_repository('hg_dupe_delete') do |hg| + assert_equal 4, hg.commit_count(:trunk_only => false) + assert_equal 3, hg.commit_count(:trunk_only => true) + end + end + + def test_trunk_only_commit_tokens + with_hg_repository('hg_dupe_delete') do |hg| + assert_equal ['73e93f57224e3fd828cf014644db8eec5013cd6b', + '732345b1d5f4076498132fd4b965b1fec0108a50', + '525de321d8085bc1d4a3c7608fda6b4020027985', # On branch + '72fe74d643bdcb30b00da3b58796c50f221017d0'], + hg.commit_tokens(:trunk_only => false) + + assert_equal ['73e93f57224e3fd828cf014644db8eec5013cd6b', + '732345b1d5f4076498132fd4b965b1fec0108a50', + # '525de321d8085bc1d4a3c7608fda6b4020027985', # On branch + '72fe74d643bdcb30b00da3b58796c50f221017d0'], + hg.commit_tokens(:trunk_only => true) + end + end + + def test_trunk_only_commit_tokens_using_after + with_hg_repository('hg_dupe_delete') do |hg| + assert_equal ['732345b1d5f4076498132fd4b965b1fec0108a50', + '525de321d8085bc1d4a3c7608fda6b4020027985', # On branch + '72fe74d643bdcb30b00da3b58796c50f221017d0'], + hg.commit_tokens( + :after => '73e93f57224e3fd828cf014644db8eec5013cd6b', + :trunk_only => false) + + assert_equal ['732345b1d5f4076498132fd4b965b1fec0108a50', + # '525de321d8085bc1d4a3c7608fda6b4020027985', # On branch + '72fe74d643bdcb30b00da3b58796c50f221017d0'], + hg.commit_tokens( + :after => '73e93f57224e3fd828cf014644db8eec5013cd6b', + :trunk_only => true) + + assert_equal [], hg.commit_tokens( + :after => '72fe74d643bdcb30b00da3b58796c50f221017d0', + :trunk_only => true) + end + end + + def test_trunk_only_commits + with_hg_repository('hg_dupe_delete') do |hg| + assert_equal ['73e93f57224e3fd828cf014644db8eec5013cd6b', + '732345b1d5f4076498132fd4b965b1fec0108a50', + # '525de321d8085bc1d4a3c7608fda6b4020027985', # On branch + '72fe74d643bdcb30b00da3b58796c50f221017d0'], + hg.commits(:trunk_only => true).collect { |c| c.token } + end + end + def test_each_commit commits = [] with_hg_repository('hg') do |hg| From 81950c144391177acfb97cda0c67335f99565541 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Wed, 26 Jan 2011 20:03:07 -0800 Subject: [PATCH 067/219] OTWO-344 Allows Bzr revision-ids to include ':' character It is possible for a bzr revision-id to include a ':' character. We've been using ':' as a parsing delimiter, so such revision-ids caused problems. Fixed. --- lib/scm/adapters/bzr/commits.rb | 2 +- test/repositories/bzr_colon.tgz | Bin 0 -> 2411 bytes test/unit/bzr_commits_test.rb | 7 +++++++ 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 test/repositories/bzr_colon.tgz diff --git a/lib/scm/adapters/bzr/commits.rb b/lib/scm/adapters/bzr/commits.rb index d3ee64bb..44c59237 100644 --- a/lib/scm/adapters/bzr/commits.rb +++ b/lib/scm/adapters/bzr/commits.rb @@ -9,7 +9,7 @@ def commit_count(opts={}) # Return the list of commit tokens following +after+. def commit_tokens(opts={}) after = opts[:after] - tokens = run("#{rev_list_command(opts)} | grep -E -e '^( *)revision-id: ' | cut -f2 -d':' | cut -c 2-").split("\n") + tokens = run("#{rev_list_command(opts)} | grep -E -e '^( *)revision-id: ' | cut -f2- -d':' | cut -c 2-").split("\n") # Bzr returns everything after *and including* after. # We want to exclude it. diff --git a/test/repositories/bzr_colon.tgz b/test/repositories/bzr_colon.tgz new file mode 100644 index 0000000000000000000000000000000000000000..c49ff509a39ef792994952256c9575a06099a0ba GIT binary patch literal 2411 zcmV-x36%C9iwFSY?LbWc1MQp(P!o3^$AgH~2p;0q*VwrggaI{S|NBb9X=|gPyi(sS z%88rJhOC5Lx>*ps@lkA5dZ1@ft5vDJqqgWcE!_El(NnKhan2WbT1Tr?X-9jlkFnFD zM{92*P}@L^z`9=H{}~_wHu)#}{eSaU`Wr9< z)L#ue^q(60{DkCKg~xCUOc8`v{V_m#=#Ntq<2O)#KZqqk>(kP!eOBO z>puY~82?qFZT*`Js?-?1)_;^Rc<4_O@|1w*MNjj0u;au{Z==2yq{Z9c;{~J&o`dzK5IYbOj5j26BXdP_@m<|9N zt23g6UB}`!6N8aKUzeK0IlpDjR|6A36B#J}-tAdyHUtltnYXY>t z{wD!|^}i~#slQI``XBeyA2(po|7y@w|LZIhkxW*iAGC5uBTaJv0WjisW!m=t|H1l? z!S!DaJoINAER!K*ONt%==s^FU#9{nb1#kK*nF08W|70uw8weQxRiU~6|DqsfaC|y4 zU1ZsoqW}~V+0_3B1UvxHRq^J3IT4hNA+bt~;miL7>Y4vjm;u)Rsu0$6ng-IMH)40n z)^E=JaV;Y85f6H@X+#@|A9E;P~ zv?IVf{DQeqDHKK|Qk{U>k( z)L#wEv!)^~S|d)*CBeQ=x5AtMmFxg@p#MX_^Z(SrLw}LY5?q|S0jyvLs3ZM9f`a<1 zfp`70vz!8LQ(_vlUw=9N!~U--c-LRK4xrEckD@&F$0=Cy}JmG(UU)ytoQQtpk4+Un)spPhEQK7Z@>Gl}P`YwJhdyR-1t%YGq)|1>o9 z!+WQ7#`05%ov8Xydw-XYB3WjzoVj62Qv>L!LjcSE3-zMLi04tvS}91Kgb^J81T1$ zt_y1@Hjl3eDqYfWukmgpt81v*y!V+MX>-0#TBy5x;>B~33t_ytd<+ zcOn*Vy!3a{_S-i~dnfc5v5v=5DlB`pnbJ3}Sv=$BmFE{$KlOCz_3uXoP3&8_=+@g@ zbkCB_MaE%Kel>+>Q;M-Y$My`K8?>o+VCaey=@&CDlw7Mkdiu`dwRhqR^TC)|hfiL0 z#%-?&j~&b$$}VuNOc}EFYsZS5n&LUtj^O9crOfs>1Ju;=9!-=MQ0}*wIQ!80O{+H- zzqQ`}F>9YU&v}^b{c5j%hwTvs5pnAZstV$l#Z@g^7FAX?uvY|ERdzUP-O;$M9CtV> zZsxW)J~c2RHEKibOzjBA{Euk{@fZ1qh8PPy$DU&>4z`xcQi? zrbOrX(m6iiRm+zfQ}6gaKQ=hq42&($ZPcRjGyA(Iv7gePSkQg&zWxhVm*8Y2Hm%c% zK)d6=e2>6k{8t0-`g6REV^}3Jzz*bpB<%mIgKzzPW`G=*`|vS**8f94NH-s6J6mZyL8@3k>x*OT5Y-3A5x@9M1o0q~6fvj5@r z|Ekd8{vY}a|HC5!zfu(NztrjYk5jGuPr?4bDs&+JV?O);SQbj*@dT(y`gd{?M%0o- zQv8{nC>nn{nY5HAQCM;!ZUGfjNs)xc>*v38!)ulKtIP9W$@d$ix!7-5)@gG3{t3ik3Ki10s;m68@dVs)yQ`?2t3;+D~IZNRo^gGkQfPfIf z`ND`^xi`OAxTDdPQgUF#};PR%DqFL38QsX{YIQZLS?re`+yMmuxJn8qtVY^Q;6!5>;`TC!19sl9^KdPW; z{ePj)5;RbAVA1^7^}*HKt$q6q$h;jM8X2&=;l>Yqon?3R$-Q&uy&0QaIpmxraKcA) zY*5ya>z@rBzVwer)~x9}VBqM~@E^Yk3sLNYCm=rY?tkUZ0PjHm7d621e<2VE1OkCT dAP@)y0)apv5C{YUfj~OM{{Z$g`2+xX007$U_geq} literal 0 HcmV?d00001 diff --git a/test/unit/bzr_commits_test.rb b/test/unit/bzr_commits_test.rb index 1c9da7dc..8efec8d1 100644 --- a/test/unit/bzr_commits_test.rb +++ b/test/unit/bzr_commits_test.rb @@ -80,6 +80,13 @@ def test_each_commit_excludes_directories end end + # Verfies OTWO-344 + def test_commit_tokens_with_colon_character + with_bzr_repository('bzr_colon') do |bzr| + assert_equal ['svn-v4:364a429a-ab12-11de-804f-e3d9c25ff3d2::0'], bzr.commit_tokens + end + end + protected def revision_ids From 86d106d4ca8a66f8236ddaa09488d255ab7257a6 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Wed, 26 Jan 2011 20:45:34 -0800 Subject: [PATCH 068/219] OTWO-285 Updates BzrAdapter to support :trunk_only --- lib/scm/adapters/bzr/commits.rb | 5 +- test/unit/bzr_commits_test.rb | 84 ++++++++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 3 deletions(-) diff --git a/lib/scm/adapters/bzr/commits.rb b/lib/scm/adapters/bzr/commits.rb index 44c59237..233f4f7d 100644 --- a/lib/scm/adapters/bzr/commits.rb +++ b/lib/scm/adapters/bzr/commits.rb @@ -8,11 +8,11 @@ def commit_count(opts={}) # Return the list of commit tokens following +after+. def commit_tokens(opts={}) - after = opts[:after] tokens = run("#{rev_list_command(opts)} | grep -E -e '^( *)revision-id: ' | cut -f2- -d':' | cut -c 2-").split("\n") # Bzr returns everything after *and including* after. # We want to exclude it. + after = opts[:after] if tokens.any? && tokens.first == after tokens[1..-1] else @@ -97,7 +97,8 @@ def log_filename def rev_list_command(opts={}) after = opts[:after] - "cd '#{self.url}' && bzr log --long --show-id --forward --include-merges -r #{to_rev_param(after)}.." + trunk_only = opts[:trunk_only] ? '--levels=1' : '--include-merges' + "cd '#{self.url}' && bzr log --long --show-id --forward #{trunk_only} -r #{to_rev_param(after)}.." end end end diff --git a/test/unit/bzr_commits_test.rb b/test/unit/bzr_commits_test.rb index 8efec8d1..9e9d28aa 100644 --- a/test/unit/bzr_commits_test.rb +++ b/test/unit/bzr_commits_test.rb @@ -19,7 +19,14 @@ def test_commit_count_with_branches end end - def test_commit_tokens + def test_commit_count_trunk_only + with_bzr_repository('bzr_with_branch') do |bzr| + # Only 3 commits are on main line + assert_equal 3, bzr.commit_count(:trunk_only => true) + end + end + + def test_commit_tokens_after with_bzr_repository('bzr') do |bzr| assert_equal revision_ids, bzr.commit_tokens assert_equal revision_ids[1..5], bzr.commit_tokens(:after => revision_ids.first) @@ -28,6 +35,55 @@ def test_commit_tokens end end + def test_commit_tokens_trunk_only_false + # There's some funny business with commit ordering here. + # When we request that Bzr iterate commits in the '--forward' direction, + # we actually get the branch commits *after* the merge that brought them in. + # This makes my head hurt, and I'm not yet sure whether this will be a problem + # down the road. For now, just accepts that bzr does this. + with_bzr_repository('bzr_with_branch') do |bzr| + assert_equal [ + 'test@example.com-20090206214301-s93cethy9atcqu9h', + 'test@example.com-20090206214451-lzjngefdyw3vmgms', + 'test@example.com-20090206214515-21lkfj3dbocao5pr', # merge commit + 'test@example.com-20090206214350-rqhdpz92l11eoq2t' # branch commit -- after merge! + ], bzr.commit_tokens(:trunk_only => false) + end + end + + def test_commit_tokens_trunk_only_true + with_bzr_repository('bzr_with_branch') do |bzr| + assert_equal [ + 'test@example.com-20090206214301-s93cethy9atcqu9h', + 'test@example.com-20090206214451-lzjngefdyw3vmgms', + 'test@example.com-20090206214515-21lkfj3dbocao5pr', # merge commit + # 'test@example.com-20090206214350-rqhdpz92l11eoq2t' # branch commit + ], bzr.commit_tokens(:trunk_only => true) + end + end + + def test_commits_trunk_only_false + with_bzr_repository('bzr_with_branch') do |bzr| + assert_equal [ + 'test@example.com-20090206214301-s93cethy9atcqu9h', + 'test@example.com-20090206214451-lzjngefdyw3vmgms', + 'test@example.com-20090206214515-21lkfj3dbocao5pr', # merge commit + 'test@example.com-20090206214350-rqhdpz92l11eoq2t' # branch commit -- after merge! + ], bzr.commits(:trunk_only => false).map { |c| c.token } + end + end + + def test_commits_trunk_only_true + with_bzr_repository('bzr_with_branch') do |bzr| + assert_equal [ + 'test@example.com-20090206214301-s93cethy9atcqu9h', + 'test@example.com-20090206214451-lzjngefdyw3vmgms', + 'test@example.com-20090206214515-21lkfj3dbocao5pr', # merge commit + # 'test@example.com-20090206214350-rqhdpz92l11eoq2t' # branch commit + ], bzr.commits(:trunk_only => true).map { |c| c.token } + end + end + def test_commits with_bzr_repository('bzr') do |bzr| assert_equal revision_ids, bzr.commits.collect { |c| c.token } @@ -63,6 +119,32 @@ def test_each_commit end end + def test_each_commit_trunk_only_false + with_bzr_repository('bzr_with_branch') do |bzr| + commits = [] + bzr.each_commit(:trunk_only => false) { |c| commits << c } + assert_equal [ + 'test@example.com-20090206214301-s93cethy9atcqu9h', + 'test@example.com-20090206214451-lzjngefdyw3vmgms', + 'test@example.com-20090206214515-21lkfj3dbocao5pr', # merge commit + 'test@example.com-20090206214350-rqhdpz92l11eoq2t' # branch commit -- after merge! + ], commits.map { |c| c.token } + end + end + + def test_each_commit_trunk_only_true + with_bzr_repository('bzr_with_branch') do |bzr| + commits = [] + bzr.each_commit(:trunk_only => true) { |c| commits << c } + assert_equal [ + 'test@example.com-20090206214301-s93cethy9atcqu9h', + 'test@example.com-20090206214451-lzjngefdyw3vmgms', + 'test@example.com-20090206214515-21lkfj3dbocao5pr' # merge commit + # 'test@example.com-20090206214350-rqhdpz92l11eoq2t' # branch commit -- after merge! + ], commits.map { |c| c.token } + end + end + # This bzr repository contains the following tree structure # /foo/ # /foo/helloworld.c From 4daf07fefd46fd7822f832e21636fe48ef0ac545 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Fri, 28 Jan 2011 09:52:27 -0800 Subject: [PATCH 069/219] OTWO-351 Escape backtick char in Hg filenames --- lib/scm/adapters/hg/cat_file.rb | 2 +- test/unit/hg_cat_file_test.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/scm/adapters/hg/cat_file.rb b/lib/scm/adapters/hg/cat_file.rb index 09158b47..938392e3 100644 --- a/lib/scm/adapters/hg/cat_file.rb +++ b/lib/scm/adapters/hg/cat_file.rb @@ -20,7 +20,7 @@ def cat(revision, path) # Example: # "Foo Bar & Baz" => "Foo\ Bar\ \&\ Baz" def escape(path) - path.gsub(/[ '"&()<>|#]/) { |c| '\\' + c } + path.gsub(/[ `'"&()<>|#]/) { |c| '\\' + c } end end end diff --git a/test/unit/hg_cat_file_test.rb b/test/unit/hg_cat_file_test.rb index a2df16d6..fb9ed9d9 100644 --- a/test/unit/hg_cat_file_test.rb +++ b/test/unit/hg_cat_file_test.rb @@ -31,7 +31,7 @@ def test_cat_file def test_funny_file_name_chars Scm::ScratchDir.new do |dir| # Make a file with a problematic filename - funny_name = '#|file_name (&\'")#' + funny_name = '#|file_name` (&\'")#' File.open(File.join(dir, funny_name), 'w') { |f| f.write "contents" } # Add it to an hg repository From df5a52c8b481760652f0cabccb6a329e59e01afe Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Fri, 18 Feb 2011 03:53:49 -0800 Subject: [PATCH 070/219] OTWO-443: Fixes GitStyledParser to support empty commits If a commit did not contain any changes at all, then the GitStyledParser would fail to parse the commit. When changes are present, `git whatchanged` inserts an extra newline. When changes are not present, we don't get the changes listed, and we also don't get the extra newline. That newline was required to trigger the parser to advance states. I've added an explicit newline in our log format string to guarantee that we'll always get at least one newline. If we get two, that's OK. At some point we should probably get rid of GitStyledParser completely, and use something more reliable like `git cat-file` or `git fast-export`. --- lib/scm/parsers/git_styled_parser.rb | 2 +- test/repositories/git_with_empty_merge.tgz | Bin 0 -> 9378 bytes test/unit/git_log_parser_test.rb | 11 +++++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 test/repositories/git_with_empty_merge.tgz diff --git a/lib/scm/parsers/git_styled_parser.rb b/lib/scm/parsers/git_styled_parser.rb index a52ac8e5..3966ddd2 100644 --- a/lib/scm/parsers/git_styled_parser.rb +++ b/lib/scm/parsers/git_styled_parser.rb @@ -11,7 +11,7 @@ def self.whatchanged end def self.format - "format:'__BEGIN_COMMIT__%nCommit: %H%nAuthor: %an%nAuthorEmail: %ae%nDate: %aD%n__BEGIN_COMMENT__%n%s%n%b%n__END_COMMENT__'" + "format:'__BEGIN_COMMIT__%nCommit: %H%nAuthor: %an%nAuthorEmail: %ae%nDate: %aD%n__BEGIN_COMMENT__%n%s%n%b%n__END_COMMENT__%n'" end ANONYMOUS = "(no author)" unless defined?(ANONYMOUS) diff --git a/test/repositories/git_with_empty_merge.tgz b/test/repositories/git_with_empty_merge.tgz new file mode 100644 index 0000000000000000000000000000000000000000..4276f993941f2986630cb63ea0b2cde437846f37 GIT binary patch literal 9378 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 Zm5nA~QTxA!Jf0Wo3qKT3I1+fc{|CX-ss;c6 literal 0 HcmV?d00001 diff --git a/test/unit/git_log_parser_test.rb b/test/unit/git_log_parser_test.rb index 0d1eec24..ddfe067b 100644 --- a/test/unit/git_log_parser_test.rb +++ b/test/unit/git_log_parser_test.rb @@ -209,5 +209,16 @@ def test_use_email_when_names_are_missing assert_equal 'mickeyl', commits.first.author_name # Use name when present assert_equal 'mickeyl@openembedded.org', commits.last.author_name # Else use email end + + # Verifies OTWO-443 + def test_empty_merge + with_git_repository('git_with_empty_merge') do |git| + assert_equal 5, git.commit_count + assert_equal 5, git.commits.size + c = git.verbose_commit('ff13970b54e5bc373abf932f0708b89e75c842b4') + assert_equal "Merge branch 'feature'\n", c.message + assert_equal 0, c.diffs.size + end + end end end From d8070b0a56d359eb717fd1f0e189f182523c4b17 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Fri, 18 Feb 2011 04:10:39 -0800 Subject: [PATCH 071/219] RAGE! Do not commit your punk logging code... --- lib/scm/adapters/cvs/misc.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/scm/adapters/cvs/misc.rb b/lib/scm/adapters/cvs/misc.rb index 7068468c..99aa275e 100644 --- a/lib/scm/adapters/cvs/misc.rb +++ b/lib/scm/adapters/cvs/misc.rb @@ -184,7 +184,6 @@ def ensure_host_key if self.protocol == :ext ensure_key_file = File.dirname(__FILE__) + "/../../../../bin/ensure_key" cmd = "#{ensure_key_file} '#{ self.host }'" - File.new("/home/jallen/LOG", "w+").write("RUNNING: '#{cmd}'") stdout, stderr = run_with_err(cmd) end end From fd5a2f96ff0f518111fa31fa7ccf97d7cd5a55a6 Mon Sep 17 00:00:00 2001 From: Robert Schultz Date: Mon, 14 Mar 2011 12:38:21 -0400 Subject: [PATCH 072/219] Removed a catch for an exception that shouldn't be caught and eaten. Fail fast. --- lib/scm/adapters/svn/misc.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/scm/adapters/svn/misc.rb b/lib/scm/adapters/svn/misc.rb index 4303ceea..6f54bca5 100644 --- a/lib/scm/adapters/svn/misc.rb +++ b/lib/scm/adapters/svn/misc.rb @@ -66,11 +66,7 @@ def info(path=nil, revision=final_token || 'HEAD') else url end - @info[[path, revision]] ||= begin - run "svn info --trust-server-cert --non-interactive -r #{revision} #{opt_auth} '#{SvnAdapter.uri_encode(uri)}@#{revision}'" - rescue - raise unless $!.message =~ /Not a valid URL/m - end + @info[[path, revision]] ||= run "svn info --trust-server-cert --non-interactive -r #{revision} #{opt_auth} '#{SvnAdapter.uri_encode(uri)}@#{revision}'" end def root From 3131c05e47aeafe1b17aa974347a32fa5697cda5 Mon Sep 17 00:00:00 2001 From: Robert Schultz Date: Fri, 25 Mar 2011 09:52:08 -0400 Subject: [PATCH 073/219] Fixed an SVN bug introduced in the last commit by exposing an exception that was caught and eaten before Basically in a previous changed I removed an exception catch for 'Not a valid URL'. Turns out that the misc.rb is_directory() method relied on the exception being eaten. This commit adds proper exception catching for this now exposed error message and handles it correctly. --- lib/scm/adapters/svn/misc.rb | 2 +- test/unit/svn_misc_test.rb | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/scm/adapters/svn/misc.rb b/lib/scm/adapters/svn/misc.rb index 6f54bca5..13a2282c 100644 --- a/lib/scm/adapters/svn/misc.rb +++ b/lib/scm/adapters/svn/misc.rb @@ -105,7 +105,7 @@ def is_directory?(path=nil, revision=final_token || 'HEAD') begin return node_kind(path, revision) == 'directory' rescue - if $!.message =~ /svn: .* is not a directory in filesystem/ + if $!.message =~ /svn: .* is not a directory in filesystem/ || $!.message =~ /.*Not a valid URL.*/ return false else raise diff --git a/test/unit/svn_misc_test.rb b/test/unit/svn_misc_test.rb index 0736891d..e5404d10 100644 --- a/test/unit/svn_misc_test.rb +++ b/test/unit/svn_misc_test.rb @@ -58,6 +58,7 @@ def test_is_directory with_svn_repository('svn') do |svn| assert svn.is_directory?('trunk') assert !svn.is_directory?('trunk/helloworld.c') + assert !svn.is_directory?('invalid/path') end end From 117b36cbb11519c3255ac4e7cd0384505e06862b Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 12 Apr 2011 12:53:31 -0700 Subject: [PATCH 074/219] OTWO-579 Use read-only URLs when possible If the user supplies a read-write Github URL, transparently substitute a read-only URL. This avoids an unwanted (and unhandled) password prompt. --- lib/scm/adapters/git/validation.rb | 14 ++++++++++++++ test/unit/git_validation_test.rb | 28 ++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/lib/scm/adapters/git/validation.rb b/lib/scm/adapters/git/validation.rb index b3607b69..3f985bf9 100644 --- a/lib/scm/adapters/git/validation.rb +++ b/lib/scm/adapters/git/validation.rb @@ -10,10 +10,24 @@ def self.public_url_regex def normalize super + @url = read_only_url @branch_name = 'master' if @branch_name.to_s == '' self end + # Given a Github read-write URL, return a read-only URL. + # Otherwise, return the original URL. + def read_only_url + case @url + when /^https:\/\/\w+@github.com\/(.+)\.git$/ + "git://github.com/#{$1}.git" + when /^git@github.com:(.+)\.git$/ + "git://github.com/#{$1}.git" + else + @url + end + end + def validate_server_connection return unless valid? @errors << [:failed, "The server did not respond to the 'git-ls-remote' command. Is the URL correct?"] unless self.exists? diff --git a/test/unit/git_validation_test.rb b/test/unit/git_validation_test.rb index f30f0202..a80b2e68 100644 --- a/test/unit/git_validation_test.rb +++ b/test/unit/git_validation_test.rb @@ -40,5 +40,33 @@ def test_guess_forge git = GitAdapter.new( :url => 'http://kernel.org/pub/scm/linux/kernel/git/stable/linux-2.6.17.y.git') assert_equal 'kernel.org', git.guess_forge end + + def test_read_only_url + assert_equal nil, GitAdapter.new(:url => nil).read_only_url + assert_equal '', GitAdapter.new(:url => '').read_only_url + assert_equal 'foo', GitAdapter.new(:url => 'foo').read_only_url + + # A non-Github URL: no change + assert_equal 'git://kernel.org/pub/scm/git/git.git', + GitAdapter.new(:url => 'git://kernel.org/pub/scm/git/git.git').read_only_url + + # A Github read-write URL: converted to read-only + assert_equal 'git://github.com/robinluckey/ohcount.git', + GitAdapter.new(:url => 'https://robinluckey@github.com/robinluckey/ohcount.git').read_only_url + + # A Github read-write URL: converted to read-only + assert_equal 'git://github.com/robinluckey/ohcount.git', + GitAdapter.new(:url => 'git@github.com:robinluckey/ohcount.git').read_only_url + + # A Github read-only URL: no change + assert_equal 'git://github.com/robinluckey/ohcount.git', + GitAdapter.new(:url => 'git@github.com:robinluckey/ohcount.git').read_only_url + end + + def test_normalize_converts_to_read_only + git = GitAdapter.new(:url => 'https://robinluckey@github.com/robinluckey/ohcount.git') + git.normalize + assert_equal 'git://github.com/robinluckey/ohcount.git', git.url + end end end From ffef61d1e512e03463fd9f46da1e376ee853e86d Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Mon, 25 Apr 2011 01:03:27 -0700 Subject: [PATCH 075/219] OTWO-623 Fixes incorrect list of diffs for null git merges Whenever a git merge commit has a resulting tree identical to its first parent's tree, the list of diffs should be empty. However, a bug in our commit parser caused us to return the set of diffs relative to the second parent, instead of the correct empty list. I could not invent a method to force `git whatchanged` to do what we want, so I surrendered, and instead I manually patch the result after the fact. --- lib/scm/adapters/git/commits.rb | 24 ++++++++++++++++++-- lib/scm/adapters/git/misc.rb | 5 +++++ test/repositories/git_with_null_merge.tgz | Bin 0 -> 9233 bytes test/unit/git_commits_test.rb | 26 ++++++++++++++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 test/repositories/git_with_null_merge.tgz diff --git a/lib/scm/adapters/git/commits.rb b/lib/scm/adapters/git/commits.rb index 9a13394a..0acb4d64 100644 --- a/lib/scm/adapters/git/commits.rb +++ b/lib/scm/adapters/git/commits.rb @@ -41,16 +41,36 @@ def each_commit(opts={}) previous = nil Scm::Parsers::GitStyledParser.parse(log(opts)) do |e| - yield e unless previous && previous.token == e.token + yield fixup_null_merge(e) unless previous && previous.token == e.token previous = e end end # Returns a single commit, including its diffs def verbose_commit(token) - Scm::Parsers::GitStyledParser.parse(run("cd '#{url}' && #{Scm::Parsers::GitStyledParser.whatchanged} #{token}")).first + c = Scm::Parsers::GitStyledParser.parse(run("cd '#{url}' && #{Scm::Parsers::GitStyledParser.whatchanged} #{token}")).first + fixup_null_merge(c) end + # For a merge commit, we ask `git whatchanged` to output the changes relative to each parent. + # It is possible, through developer hackery, to create a merge commit which does not change the tree. + # When this happens, `git whatchanged` will suppress its output relative to the first parent, + # and jump immediately to the second (branch) parent. Our code mistakenly interprets this output + # as the missing changes relative to the first parent. + # + # To avoid this calamity, we must compare the tree hash of this commit with its first parent's. + # If they are the same, then the diff should be empty, regardless of what `git whatchanged` says. + # + # Yes, this is a convoluted, time-wasting hack to address a very rare circumstance. Ultimatley + # we should stop parsing `git whatchanged` to extract commit data. + def fixup_null_merge(c) + first_parent_token = parent_tokens(c).first + if first_parent_token && get_commit_tree(first_parent_token) == get_commit_tree(c.token) + c.diffs = [] + end + c + end + # Retrieves the git log in the format expected by GitStyledParser. # We get the log forward chronological order (oldest first) def log(opts={}) diff --git a/lib/scm/adapters/git/misc.rb b/lib/scm/adapters/git/misc.rb index a6b30617..61c9e16e 100644 --- a/lib/scm/adapters/git/misc.rb +++ b/lib/scm/adapters/git/misc.rb @@ -21,6 +21,11 @@ def ls_tree(token='HEAD') run("cd #{url} && git ls-tree -r #{token} | cut -f 2 -d '\t'").split("\n") end + # For a given commit ID, returns the SHA1 hash of its tree + def get_commit_tree(token='HEAD') + run("cd #{url} && git cat-file commit #{token} | grep '^tree' | cut -d ' ' -f 2").strip + end + # Moves us the correct branch and checks out the most recent files. # # Anything not tracked by Git is deleted. diff --git a/test/repositories/git_with_null_merge.tgz b/test/repositories/git_with_null_merge.tgz new file mode 100644 index 0000000000000000000000000000000000000000..283db5ced9c22a2eb5daead42bb121565a0a3705 GIT binary patch literal 9233 zcmV+sB<|ZEiwFRPCbdlf1MEEscoap}A%K!z4`dY-S+|%3a*&yH&za!}awtTu5Wx#W z=$Wp`G@0ohyL(7Nh$nckDu?IpBJQuEfS{twA)@Q=qRSZ&Q3UzD!CzScSx{H~WnWeI z90?(lm^l36ypLvjx~uBFdRM*os;5&SYUNd;<}a7Rfk1f>D;2mPt(}1da5)_0lXE%P z_|FKWah${9umU)(X)I^wI9nQWv^OD5L0Hvz1)(%W_J~q5?GoMpg+fIW^7rFFK(=_> z4F?gh({4Yh{5j6vNd69+!aDT2BDB5N}4anG?J)DKB|(HfYAGT$&@>Qsbfy{TvE__Xv+RAaIrlX zfmZo{my7s+7r23x|4#y(RQ@9`8#26|a3u2otko5jKWk&D|97z||DOy{u&+OY|5RA@ zc|k1*@~VcFlq>(Wz)9_&>O}kCXodgh99C-oF4mRu|H**n<*)G-?Vtp$m%r0#cckQ> z3}{~d`kK&I9IcQ4Tr8WCe^Q_&^7ph6N5c5e!NuY~YX2?{Lc&!1mjrNeZU=U|d7oFn z&O%(sx@=ZAcKO^khs$fVW7ff9ug`%~5#i|xEwO(+C-~_&T4Vpz|AQCcQudz|5NsZS z^#SvYwtz8#Y}vO!VJa{q}*Ix7@|DMhF{rlkY zM|X6ef8}oH;t5;MNXvTnoEJ|u%_(RoT$3^@E=d#&T@qbdFW%3X4 z-b(c+<49Qlb2=N!-^$ut)|CHG29zKoTeG#$E?BY0#@Yq1&1n;CJjc6Wjd%D8dCu*_ zf?zGQS*;!mY0adHfu{{5w0|P-Q{extspmhE0xgq&>wQE#js)>PXLmG`zt!nEuJ*_(>=)d+lNPf-_zQC z_8V&~?mv9`qW{3Hy&wE|z*9#aFWcX_Uj6*p(DcKo;9c`4u5<8~fjd_oQg{pJt7!pknO&RBD7=JbxcCXD{(P^X*osuz6!`nP`= zzxs(B$Hf0;w{FPK-MI7B?K#|5*8Td9EjzQ^X1Cd#`{w%X@4mKU??7(%-t_}F1|B=u zy;vPJs&iRKwPQz%osC<<-vkoJGhWA&@@h9Xt~-`v943~f-CE{jH=HaQ#|pxTubrBExR^9_sPdQc9n)EjI7_bb*%_UO;geGnU8wB+q{c1y4|+x zh5o&kjvoKf^DjK|!u6d#*>$Sz^yh+~!~csybpsp;{J+)ius8Pq4x1z8|C0g7wQ=N! zUg>QZqC*Rh^k$BZ|BsGNZ9F>v0**7-HyIg zxnl06SDP-mX^~u5Qu8*xCD*%B*;Kwi^X=kUx74^U*mER!&XJt%Yeud*@6$uoi=TR9 z`Qe*i4iA6kT2r5rSwsByd<1hl3*66oa5FvO7zyVO!nIZKc^-VPhvP3zt@j-_A3Lx9 z=(^``*|eZ;=Bz-`Lm9&!O*;)C;rcJwPQmlvPM4KS<^RcmmdL+lPY9kIN22{dTm0|8 z>GPj*;jv)HY+`g(u?kv_UEFZ4-Petx%2hwp83;|%m;SQE!^D;nj#|6? z@3$@LYg$maWc)qXPF;NAiWOO}bx$v;pLuv!#WG>#re#}|73sZ(ITluCy)*Z$E~6`~ z*}HDoyY~3IPrmiV2hU7j_0mlTA1beY#PZl@tN!(kbIyCOd|JGE-|OC)8#c_He^aM3 zLbYrEcJbHcb81)rDBk$R^IyFA`zLSvzJp`gtuPmo3#mo&*yV<9$O*jb~{+72i&!*(A~_BgcA9Gj&nA8{=?=-)qj%%)g4A{ z+BmM1wRuWfRyR9owXVzg7u<8IXOn`~!b$DlFUytf^aJqL?Ee|R|7BgN=l_!e3FIFR z3A~0aDjy65nt8&zc}O6C7bE};r-P zPbBwbWYU$?WTD-L$&yd3fD^FbhR|3MZf{9 zVHi6BCA1wd_he+WiHM*qh`yS{MDPSV3i34sH|-<>a^44WM_vW0~uS5}<*9#w>{P>Pib5 z91QZ3fC8d~8N)^fnX)(&12&@IX>e{eF<>V8xy=;mcqQ+{8c^rQ-bzOFp-IR*9htI5 z6i+B0UR-KIWdjIB5|e?welVNilpji1(rGblofkAaXPBjY#hjIvlX5T;dx2I}*H6MZs8xsjIDpgJ7m6PdVa7@RO6 zv#ejxd&j=(gPbtUi7H=#`!|F2M5GZpP*2j>aSY1J0nY|ACU>DBQI(VUm|W%rZBNuY zzHKhkSV5cV-MDE3++e&dLkta#j#1B$sAIHYE@2#1KID@XB*~!bx>A92U_y#a5=wFj zMpVIW%@}2KH)O{&v>>j%DVOo`Du$bJ9Zg_VjA^1o^gxKSEK?quflScF5P4o+9xBnh z#nYg#7=B*W{Q#!s-B9`&0|qcy<-JiIpwrQ6LRf_>pp1r=5z8g9i^XCgANkl*>11@J|!un`#ut35^)h{brdBkC5)f#7+ znXxhIpqVkX#54Az_>m_9 z7qW?tlQj;!4G-F6R#90t)nmHsM!X%7EGT4%uOMM@Y%D{2GJvZYM28yiO&5>OH$yFS zj>WSgYJUkCF+8#&>WgwKX51{5)Pf0#jpZ6oWz^UkP>K5XCD9(>oCcAe0_=?F6e>bs z)zb<{c7d!#eF^p^L<`f%j&#X}sem67Y9JI9RZX=tA+a%(j8^a(oVwYqZi`E=r>6huD=iU{jCy|2iN+{RebA zn#BL)Do}#@563zh)&H!Vi%r%4lL9TO|Ijc9!Y@<2I+zfih9ym}x=c9nuF;pcNJugD zQbB`q5Cr0g_j+-Ngc>~k9TG#L51~=sOdHa0U3Yf^B+|un;1I8pL?T*J(w(v*hbu@b zPhMy)MbdDXLXf28CuDy#DuVLN&2h12IQwA(o! z?{K>9PC@VrPTtBQXQ9uT;O_BpH`FKf49uVCXmF1N3cvp4aoUBW&U zlYCp!6wzZC9_2ZYbd$?RGO0*KUdc}8BjIX|rsjlUFhaC2hGTWH2J*0gqqm@fu&RKt zc?A~;vbTU{2QqwVh&;Zd83%bWkXjB-Q%L0h6%2~tfjqGddjQS*fAIXV{ojcHx7kwu zKPk}A{|}QxHHui_*HDf(7g<@>nNR*NL|23*QAWeiNIu9*a-7SL>W4{RF${M<71#RS?Y`$1m|NDNO#fMgZCCU{}BKkb#pK`cz$ghQ$Zd754d zRk0$HA}_2%Fr!MWlSJysS=LAgBTMjLGOj*b0p*bOBpA|aNDW!iFVj*!nO#^>$V`oL zU4(2>iPcwN)h}0(eUB===wR?g4vF4a-C6VVkdlxTLeH6D2x`Lu>61+siR=hvl#3Nu z)8Yus2YS7HST&02&c_f@os>L|MBdK{P>3?DM0ydUY!{>6i{tOc7_$|9Z(}43pC*j^bPxFvy39 z)n;TAOwO6an%%tFSJp2V6_EBBIj~?2DneW?`BsP2P(ajj3a*z5@(uF1GJ1<76NE+_ zz(JG~9kS7wIhMTKEPddNN&3iHRyw~X$F`Q`=IY~sD&+LmtF zwuD!a?-}$@N}($!48N?jlyXrgAR{aZq^1?UP{*9m+JqtqxH5x6=PF}G)mC&_f8 zn~C4~GxUeaY$GsC{7SCp(!38>gn30!n_R^GJa{aUdKIH(qW?++sYfVKOG3A3dYCM4TK0Zp6@0`g{X0gRkHr z0La0jz8fz>TBw2V1%(o&$TtXHPKGz?ti8YklB+{J7mp!I45L3V0PXdHEzR=vZDtAU zHscA4;0t04rM}Sy`75D<^vAps5Q(b>P2?-F3SlL5t~!Aty;@HnQXzbyfejsiE~z3N zoYp%G;w;8f0Y(WJB14ffL4p)nRe7a``XyrqL4ui_U|0o!7$C6{;}DsN5{Z_ODiX!e z*>*KJOS;0u&y~7XV6veMdT+0vmnw+D$oiBB#)uZ>>ue=-2MyNh`mQ%H6h|-0-_T93dbGTe&`A>Vt^W(Txo^D0ygaZ;M z5K{G&88$Q9II-i{nanb)&d#pNh?#D+yH#23uR69fYi%aZ+R1hXmI4>9fKX4BdZ8x- zQUSq*OaFm#1rBgP0`-E#0S+7xeBbxpvmGascz$KJi$67;#OwF_ec$_jze)v7v8kPg z^p>WPR7EkR~vf?UbN@>xQiIO42$6- z_VE>oC`e)=sRHbZoKT=BfWgG16qag}W|by1&2mM!K^5Ob@rE2hU=YGA12r?YjZ*}h z9oP|Qx3gbPF-%l?3}S;+l^i3v9?4TwjDW8Op@f|D!0m9urJvxAEmRctX^M%M0b(IG zQSq1-0xRbw$W40?Q1b%i%3@{(gDDzE;*n@*30Q>(RxgYt%@B2Rh&;=%b|6kYh}>)V zKIEh(p31_Oi+%(hJTENaBNXW);b4O@zM?2oKVs8UiK<`^<=>I-_!d5}pd@};Y<=uY z)zq^w?Z;1LLtpP}us5DsT6wmDf zmmXLlMOnZ+!3Vt~N6 zkeWOiUa~W_(as3LyTZ>_(Fi~GNr@wgz`>;OthITEhYb2(3!VCif*w%^Jk9^#9MS*Q zYI**T*+5qRZ(yvvHmWf#LIJDg5BdVxxsc0Us)3`9w+lb)kjYfgh6ETBqAzAjK`VFx zlDz2POzCrl>Cgj7hx4pxB_q|Czu^p8uoaUjn5B zV#kg;NqpoK0E%X(0S8b3vL~M?2O!Sq3dNyFS%G^vD~gyBG%B)7DKBSk01@hjHL^Q$ zd&C0U?0S7vm+`t+nd7zFkzxYLCE1Jnf$K6JgCEyZZ>`h}$2RLVyJfnqrlp#yYt&oq z6~}DWR#w^|GuE4GUD~hOLw@UAmczNVLfi9bq&V&n!yx$JA6qb|Ej|J0C0pUKAW(*i z42OawVnE~z6auml_+iL;9jlK{S4_ljz>>IKBDmIL-*d+G3%}#}`DrZP|UUd*d--WG|p01*9kv{s;WuS=h5cLbo4S0Tjb9H^0D7W{eb-tgUGA^_4njgEV=^o4ci|z_hq((@grCX zjvvPNXy64XXrtkVbZ0HEbKKC|>5}G*x>hO73$r1uH|(EE{5K3P zLF4Z_+5#8lR(^synXQfc>swoE8#rpkVWrzldFSpOwX{5B-7Q`X0zX(~>p(?zIlY1P zM&ZVNg+TIqNk*lk#e+TE-^h zBO!5ICTZsa{z9&;;&mN&4_BC4idH&WN=5k;YBqAn0$KdOkIMi~lmBY<5&q9G^84Rr z0@?UK!SxA8I?j$+=sbk>&-S2$fuEe!gSU1q=g@*vVxJ+mwTg!+nsjoybIOnf|Bssl zWGenQj8Xj0{eNcyS>-?A%zNZ#N^u%P(bvSJ61$5YBn!+L?6xp^t{WoH6ds8bL@7NY zPDMOYLN|bB6ug!wCl1Gl>G~gBb|qFl9f1r?!T*}B>M8u!RW-l=Zzgb9{2#9Yo~-$y zcqJK^8U-kE|Cmt7>BGv`vhdO8^$8I*O5-4^;YG;foeF_C9QuR6b`#pA5<0^KKvGED z9@X~7rMbSBe9rn(HPyDfPAI*%Q%b2aS5hSS9;*f9j%RW?q@F2-Vic>zJQ@ziVqSm>?-p4O?RAj zrA=0burG4@;FclB4Cw4zAUhX>OvJY7S(&vnpIh)!r<{muEIipR;|b`Uc{|Yeu8=ubajI2 z7t+=D&{uhZyGw9)+2WmUkyY4R2P$)-<$SBKFwZ*z9XfxWEz<6K`DM1Y#?(X~7`w2{ z52BCG6< zR_&E=L_2^JOnDTd-#JuW zKMObs`|sq_AHCtE;io*77od|g<_1!{z^JWgjHQU^^O{dbY?K8NDe_32gNHcG zrtqtkOv71He90Zjy=n{hUT4sQvlAD3bhgk#lN&X7{L>P(Sh|<$kT~Pec!42QFpfdj zd&Cr5jtCCd>b=`+{_X`0|6g@V%OjC>S0?u(4zN3G?4LmY6Abrp+aMpmiTS@%`Cqk0 zEtmgh1Eb0GE=n3FNmVJa6-pHUD2-hSJM2@im2)@(9EkrXaPPZ>Y5HGv9% zX9APgAH(90-^Nt>Z)&OaH;qQ_|1}d>v1$$5FjUiNSX#?isnzQ3W?k0|({8DHy-_o4 zw`I2L$vlItg6h^C%d#5vM%{LerfyozT2s?CsHARaP7M>dn}(*&kET01>jCF51e5XK z-6M72G257i|GJsJ{{gmLF8|L27D!(2gp?pSWQxL5n!p#a_6j=Tt&MC65W%)kn&FZ= zdDU@=ytGgv$0n(eu86d1mUILJfilG4X%Iv=%Bg%jJopTAyK~(tIwtyU@(ra{F_068 zNH=6lL+Q|V)9zlVM8@aKn8xiw<+g9##V_yV<&iTL7 zhXdEY3%kKe|W^Ium@J$?VHZshm>%mmboz_JPo>^e>q z+Zxyp-F^1ephI6?X>~07p#$GTzukWu7=#KO-i)S9WS zOI`}g>E34U#HsFr6+=JyecRBQhTCjfZQF6p6?a7ibjDoCP2FhNwYsYsstar39<9fw znc4-nFoBG<&mOoSHk8>W{XlV{weJ=(_vLgq#mY)%WXs$UN6&T<_fdM>Q0w*7HYQ#G zw(&Ok3yE|R-4?$~V{hW|HJ4f#LQ$o2m-feh=<)wjoJp$Us?`bei|7+-t`2KHx|Es3v^50D0DUtsoaY`h_<(Fj16sQzG|EXk0&w6>M zLT3Eu-0G3qn1cUW%`}JgKQ#@`fgJy50Z$43pMw4;*G-(fZXy>!pEWp;{_~^~C(_0= z{!i2EY5Sk1=l1`Zz-_$#>n`51DP1`+2a45y>;@sm+O6^16guv%@3`;_6N(h(TWH~5 z!yGc0(+F4vtJA@puoR*j%Gb_%Y&lGa1Mz?3+V=M5&HGocY~I|y@#?YKn1=uL5&K_5 z&Fz1)fsvyXV>>qcl!82D9q*w_el?hWJx=w;FUZ}#di~X_6`p6TpST`DT*y#ny^f1P zk>WOQ^1Vl8YiO136zqzK+*3=)p+T31fbv*^KiApY|-56Ve+08hjJnx?1qf9MjB zqwr#V=h8H>#6v^gah&a+V#y>@6W{lM^z0iKK~7} z|J1ZR|IbVyE57E~`E0@j|9{8bJDE17;lHjW@ZY5PA9$GK|199j=JgHua}GYwZU1`l zm&V>tzm9+PfBdC9H}~RmbLU=vac=H=AI!}?{|W!hZGG{zPfGSzzVZI&|Ni63`yc(_ zGk^Wh&o0k>mh2xD8(z46^$o1^mVBb|em&fAy~~{PVXDfAPat-YmZK zopBZa{%>#IdZDoS{Ga~&?=P=>>D?DTT-CQkV6hR&_o*0Pp|+rmtRd literal 0 HcmV?d00001 diff --git a/test/unit/git_commits_test.rb b/test/unit/git_commits_test.rb index 54e4c516..1a39a872 100644 --- a/test/unit/git_commits_test.rb +++ b/test/unit/git_commits_test.rb @@ -101,5 +101,31 @@ def test_trunk_only_commits_using_after end end + # In rare cases, a merge commit's resulting tree is identical to its first parent's tree. + # I believe this is a result of developer trickery, and not a common situation. + # + # When this happens, `git whatchanged` will omit the changes relative to the first parent, + # and instead output only the changes relative to the second parent. + # + # Our commit parser became confused by this, assuming that these changes relative to the + # second parent were in fact the missing changes relative to the first. + # + # This is bug OTWO-623. This test confirms the fix. + def test_verbose_commit_with_null_merge + with_git_repository('git_with_null_merge') do |git| + c = git.verbose_commit('d3bd0bedbf4b197b2c4eb827e1ec4c35b834482f') + # This commit's tree is identical to its parent's. Thus it should contain no diffs. + assert_equal [], c.diffs + end + end + + def test_each_commit_with_null_merge + with_git_repository('git_with_null_merge') do |git| + git.each_commit do |c| + assert_equal [], c.diffs if c.token == 'd3bd0bedbf4b197b2c4eb827e1ec4c35b834482f' + end + end + end + end end From 6a010e3fefc65bcfef269839c99c47cf6841370d Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Fri, 17 Jun 2011 13:09:03 -0400 Subject: [PATCH 076/219] OTWO-208 Ignore 'fatal signal 11' from all CVS servers We have always ignored 'fatal signal 11' when it is returned from eclipse.org in response to a `cvs ls` command. We do this because eclipse.org *always* returns this error, even when everything is OK. As it turns out, more CVS servers than just eclipse.org do this. There is probably a particular version or configuration of CVS that causes this. The result is that many CVS repositories cannot be processed by Ohloh because we treat these errors as fatal. Let's simply accept 'fatal signal 11' as standard operating procedure, and always ignore it when it is returned by `cvs ls`. --- lib/scm/adapters/cvs/misc.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/scm/adapters/cvs/misc.rb b/lib/scm/adapters/cvs/misc.rb index 99aa275e..8c967bdf 100644 --- a/lib/scm/adapters/cvs/misc.rb +++ b/lib/scm/adapters/cvs/misc.rb @@ -38,14 +38,14 @@ def ls(path=nil) /-m wrapper option is not supported remotely; ignored/, /cannot open directory .* No such file or directory/, /ignoring module/, - /skipping directory/, - /existing repository .* does not match/, - /nothing known about/ - ] + /skipping directory/, + /existing repository .* does not match/, + /nothing known about/, - # The signal 11 error should not really be ignored, but dev.eclipse.org - # returns it at the end of every ls. Yes, this sucks. - ignored_error_messages << /Terminated with fatal signal 11/ if guess_forge == 'eclipse.org' + # The signal 11 error should not really be ignored, but many CVS servers + # including dev.eclipse.org return it at the end of every ls. + /Terminated with fatal signal 11/ + ] if s.length == 0 error_handled = true From ccbcc2da53d151ea2aeb189e4100baa1ca7588fb Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Mon, 20 Jun 2011 12:56:40 -0400 Subject: [PATCH 077/219] OTWO-627 Escape '$' characters in hg filenames --- lib/scm/adapters/hg/cat_file.rb | 2 +- test/unit/hg_cat_file_test.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/scm/adapters/hg/cat_file.rb b/lib/scm/adapters/hg/cat_file.rb index 938392e3..74e6038f 100644 --- a/lib/scm/adapters/hg/cat_file.rb +++ b/lib/scm/adapters/hg/cat_file.rb @@ -20,7 +20,7 @@ def cat(revision, path) # Example: # "Foo Bar & Baz" => "Foo\ Bar\ \&\ Baz" def escape(path) - path.gsub(/[ `'"&()<>|#]/) { |c| '\\' + c } + path.gsub(/[ `'"&()<>|#\$]/) { |c| '\\' + c } end end end diff --git a/test/unit/hg_cat_file_test.rb b/test/unit/hg_cat_file_test.rb index fb9ed9d9..7c60210d 100644 --- a/test/unit/hg_cat_file_test.rb +++ b/test/unit/hg_cat_file_test.rb @@ -31,7 +31,7 @@ def test_cat_file def test_funny_file_name_chars Scm::ScratchDir.new do |dir| # Make a file with a problematic filename - funny_name = '#|file_name` (&\'")#' + funny_name = '#|file_name` $(&\'")#' File.open(File.join(dir, funny_name), 'w') { |f| f.write "contents" } # Add it to an hg repository From 455a302b7e93620ff9734f091a5ccbeb5ff75e0d Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Wed, 29 Jun 2011 09:36:33 -0700 Subject: [PATCH 078/219] OTWO-840 Removes redundant log query from BzrAdapter.cat_file_parent This patch allows BzrAdapter to process repositories that include ghost commits, and should also improve line count performance considerably. BzrAdapter's cat_file_parent() was needlessly complicated. To determine the revision ID of a parent commit, we would request the log for that commit -- using the revision ID! -- and then parse the revision ID from the resulting log fragment. This work was completely pointless. Worse, in the case of a ghost commit, the parent commit is not actually present in the repository. This would cause the log request to fail, and thus cat_file_parent() would fail. Ohloh doesn't actually care what the ghost commit contains; we were trying to read it simply to find its ID (which we already know, and worse, won't use). By removing the redundant ID lookup, Ohloh can successfully process repositories that contain ghost commits. I spent some time trying to create a test repostiory that includes a ghost commit, but this is rather involved. You can't do it using the bzr CLI alone. The most common source of ghost commits seems to be some complex interaction with bzr svn-import. I manually verified that this fix works with repository `lp:bzr` itself, which has a ghost commit as a parent of revo 897. --- lib/scm/adapters/bzr/cat_file.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/scm/adapters/bzr/cat_file.rb b/lib/scm/adapters/bzr/cat_file.rb index c3ca2ed8..bc0cc529 100644 --- a/lib/scm/adapters/bzr/cat_file.rb +++ b/lib/scm/adapters/bzr/cat_file.rb @@ -4,10 +4,10 @@ def cat_file(commit, diff) cat(commit.token, diff.path) end - def cat_file_parent(commit, diff) - p = parents(commit) - cat(p.first.token, diff.path) if p.first - end + def cat_file_parent(commit, diff) + first_parent_token = parent_tokens(commit).first + cat(first_parent_token, diff.path) if first_parent_token + end def cat(revision, path) out, err, status = run_with_err("cd '#{url}' && bzr cat --name-from-revision -r #{to_rev_param(revision)} '#{escape(path)}'") From 2aad0156da9ae5774f84110bba7d62f7dfadbd5c Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Mon, 1 Aug 2011 16:18:19 -0400 Subject: [PATCH 079/219] Initial Bazaar XML log parser and basic tests. --- lib/scm.rb | 1 + lib/scm/parsers/bzr_xml_parser.rb | 121 ++++++++++++++++++++++++++++++ test/unit/bzr_xml_parser_test.rb | 65 ++++++++++++++++ 3 files changed, 187 insertions(+) create mode 100644 lib/scm/parsers/bzr_xml_parser.rb create mode 100644 test/unit/bzr_xml_parser_test.rb diff --git a/lib/scm.rb b/lib/scm.rb index c89c6487..fb8e25a0 100644 --- a/lib/scm.rb +++ b/lib/scm.rb @@ -28,6 +28,7 @@ module Scm require 'lib/scm/parsers/git_styled_parser' require 'lib/scm/parsers/hg_parser' require 'lib/scm/parsers/hg_styled_parser' +require 'lib/scm/parsers/bzr_xml_parser' require 'lib/scm/parsers/bzr_parser' require 'lib/scm/parsers/array_writer' diff --git a/lib/scm/parsers/bzr_xml_parser.rb b/lib/scm/parsers/bzr_xml_parser.rb new file mode 100644 index 00000000..827ea425 --- /dev/null +++ b/lib/scm/parsers/bzr_xml_parser.rb @@ -0,0 +1,121 @@ +require 'parsedate' +require 'rexml/document' +require 'rexml/streamlistener' + +module Scm::Parsers + class BazaarListener + include REXML::StreamListener + attr_accessor :callback + + def initialize(callback) + @callback = callback + end + + attr_accessor :text, :commit, :diff + + def tag_start(name, attrs) + case name + when 'log' + @commit = Scm::Commit.new + @commit.diffs = [] + when 'affected-files' + @diffs = [] + when 'file' + @before_path = attrs['oldpath'] + when 'merge' + # This is a merge commit, save it and pop it after all branch commits + @merge_commit = @commit + end + end + + def tag_end(name) + case name + when 'log' + @callback.call(@commit) + when 'revisionid' + @token = @text + when 'message' + @message = @text + when 'committer' + @commit.committer_name = @text[/(.+?)(\s+<(.+)>)/, 1] + @commit.committer_email = @text[/(.+?)(\s+<(.+)>)/, 3] + when 'timestamp' + @commit.committer_date = Time.parse(@text) + when 'file' + @path = @text + when 'added', 'modified', 'removed', 'renamed' + @diffs.concat(parse_diff(name, @path, @before_path)) + @before_path = nil + @path = nil + when 'affected-files' + @commit.diffs = remove_dupes(@diffs) + when 'merge' + @callback.call(@merge_commit) + @merge_commit = nil + end + end + + def text(text) + @text = text + end + + private + # Parse one single diff + def parse_diff(action, path, before_path) + diffs = [] + case action + # A rename action requires two diffs: one to remove the old filename, + # another to add the new filename. + # + # Note that is possible to be renamed to the empty string! + # This happens when a subdirectory is moved to become the root. + when 'renamed' + diffs = [ Scm::Diff.new(:action => 'D', :path => before_path), + Scm::Diff.new(:action => 'A', :path => path || '')] + when 'added' + diffs = [Scm::Diff.new(:action => 'A', :path => path)] + when 'modified' + diffs = [Scm::Diff.new(:action => 'M', :path => path)] + when 'removed' + diffs = [Scm::Diff.new(:action => 'D', :path => path)] + end + diffs.each do |d| + d.path = strip_trailing_asterisk(d.path) + end + diffs + end + + def strip_trailing_asterisk(path) + path[-1..-1] == '*' ? path[0..-2] : path + end + + def remove_dupes(diffs) + # Bazaar may report that a file was added and modified in a single commit. + # Reduce these cases to a single 'A' action. + diffs.delete_if do |d| + d.action == 'M' && diffs.select { |x| x.path == d.path && x.action == 'A' }.any? + end + + # Bazaar may report that a file was both deleted and added in a single commit. + # Reduce these cases to a single 'M' action. + diffs.each do |d| + d.action = 'M' if diffs.select { |x| x.path == d.path }.size > 1 + end.uniq + end + + end + + class BzrXmlParser < Parser + def self.internal_parse(buffer, opts) + buffer = '' if buffer.is_a?(StringIO) and buffer.length < 2 + begin + REXML::Document.parse_stream(buffer, BazaarListener.new(Proc.new { |c| yield c if block_given? })) + rescue EOFError + end + end + + def self.scm + 'bzr' + end + end +end diff --git a/test/unit/bzr_xml_parser_test.rb b/test/unit/bzr_xml_parser_test.rb new file mode 100644 index 00000000..05bce341 --- /dev/null +++ b/test/unit/bzr_xml_parser_test.rb @@ -0,0 +1,65 @@ +require File.dirname(__FILE__) + '/../test_helper' + +module Scm::Parsers + class BzrXmlParserTest < Scm::Test + + #def test_basic + # assert_convert(BzrXmlParser, DATA_DIR + '/simple.svn_xml_log', DATA_DIR + '/simple.ohlog') + #end + + def test_empty_array + assert_equal([], BzrXmlParser.parse('')) + end + + def test_empty_xml + assert_equal("\n\n\n", BzrXmlParser.parse('', :writer => XmlWriter.new)) + end + + def test_basic_xml + xml = <<-XML + + + + 10 + test@example.com-20110725174345-brbpkwumeh07aoh8 + + amujumdar@blackducksoftware.com-20110722185038-e0i4d1mdxwpipxc4 + + test <test@example.com> + myproject + Mon 2011-07-25 13:43:45 -0400 + + + + test2.txt + + + test_a.txt + + + subdir/test_b.txt + + + + + XML + commits = BzrXmlParser.parse(xml) + assert_equal 1, commits.size + c = commits.first + assert_equal 4, c.diffs.size # Rename is a D followed by A + + assert_equal "test2.txt", c.diffs[0].path + assert_equal "D", c.diffs[0].action + + assert_equal "test_a.txt", c.diffs[1].path + assert_equal "A", c.diffs[1].action + + assert_equal "test1.txt", c.diffs[2].path + assert_equal "D", c.diffs[2].action + + assert_equal "subdir/test_b.txt", c.diffs[3].path + assert_equal "A", c.diffs[3].action + end + + end +end From d8b62623cbfcdae3e7837db4a33f2d877a291e68 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Mon, 1 Aug 2011 16:56:39 -0400 Subject: [PATCH 080/219] Fixed message and token parsing, added basic test. --- lib/scm/parsers/bzr_xml_parser.rb | 8 ++++++-- test/unit/bzr_xml_parser_test.rb | 29 +++++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/lib/scm/parsers/bzr_xml_parser.rb b/lib/scm/parsers/bzr_xml_parser.rb index 827ea425..31909ad5 100644 --- a/lib/scm/parsers/bzr_xml_parser.rb +++ b/lib/scm/parsers/bzr_xml_parser.rb @@ -33,9 +33,9 @@ def tag_end(name) when 'log' @callback.call(@commit) when 'revisionid' - @token = @text + @commit.token = @text when 'message' - @message = @text + @commit.message = @cdata when 'committer' @commit.committer_name = @text[/(.+?)(\s+<(.+)>)/, 1] @commit.committer_email = @text[/(.+?)(\s+<(.+)>)/, 3] @@ -55,6 +55,10 @@ def tag_end(name) end end + def cdata(data) + @cdata = data + end + def text(text) @text = text end diff --git a/test/unit/bzr_xml_parser_test.rb b/test/unit/bzr_xml_parser_test.rb index 05bce341..713df529 100644 --- a/test/unit/bzr_xml_parser_test.rb +++ b/test/unit/bzr_xml_parser_test.rb @@ -14,8 +14,33 @@ def test_empty_array def test_empty_xml assert_equal("\n\n\n", BzrXmlParser.parse('', :writer => XmlWriter.new)) end - - def test_basic_xml + + def test_basic_xml + xml = <<-XML + + + + 10 + test@example.com-20110725174345-brbpkwumeh07aoh8 + + amujumdar@blackducksoftware.com-20110722185038-e0i4d1mdxwpipxc4 + + test <test@example.com> + myproject + Mon 2011-07-25 13:43:45 -0400 + + + + XML + commits = BzrXmlParser.parse(xml) + assert_equal 1, commits.size + c = commits.first + assert_equal 0, c.diffs.size + assert_equal "Renamed test1.txt to subdir/test_b.txt, removed test2.txt and added test_a.txt.", c.message + assert_equal "test@example.com-20110725174345-brbpkwumeh07aoh8", c.token + end + + def test_verbose_xml xml = <<-XML From be60224706ddc074cfa4eaa8b7395754c1f90342 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Wed, 3 Aug 2011 06:14:18 -0400 Subject: [PATCH 081/219] Fixed processing multiple file elements under one Op element. Eg should create two diff records. --- lib/scm/parsers/bzr_xml_parser.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/scm/parsers/bzr_xml_parser.rb b/lib/scm/parsers/bzr_xml_parser.rb index 31909ad5..ad666d1a 100644 --- a/lib/scm/parsers/bzr_xml_parser.rb +++ b/lib/scm/parsers/bzr_xml_parser.rb @@ -20,6 +20,8 @@ def tag_start(name, attrs) @commit.diffs = [] when 'affected-files' @diffs = [] + when 'added', 'modified', 'removed', 'renamed' + @action = name when 'file' @before_path = attrs['oldpath'] when 'merge' @@ -42,11 +44,8 @@ def tag_end(name) when 'timestamp' @commit.committer_date = Time.parse(@text) when 'file' - @path = @text - when 'added', 'modified', 'removed', 'renamed' - @diffs.concat(parse_diff(name, @path, @before_path)) + @diffs.concat(parse_diff(@action, @text, @before_path)) @before_path = nil - @path = nil when 'affected-files' @commit.diffs = remove_dupes(@diffs) when 'merge' From c892897a7d3685cb9bd0d533f3722bc62eabfa13 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Wed, 3 Aug 2011 06:15:58 -0400 Subject: [PATCH 082/219] Updated to include BzrXmlParser. --- bin/ohlog | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/bin/ohlog b/bin/ohlog index 311530b9..172926de 100755 --- a/bin/ohlog +++ b/bin/ohlog @@ -31,6 +31,7 @@ Ohloh source control log parser --svn-xml Parse a Subversion XML log --hg Parse a Mercurial log --bzr Parse a Bazaar log + --bzr-xml Parse a Bazaar XML log -h, --human Output result as a human-readable log (default) -x, --xml Output result as an XML log @@ -50,6 +51,8 @@ Examples: bzr log -v | ohlog --bzr + bzr xmllog -v | ohlog --bzr + HELP end @@ -77,6 +80,10 @@ HELP parse BzrParser end + def bzr_xml + parse BzrXmlParser + end + def parse(parser) self.writer ||= HumanWriter.new(STDOUT) @@ -116,6 +123,8 @@ HELP self.subcommand = :hg when '--bzr' self.subcommand = :bzr + when '--bzr-xml' + self.subcommand = :bzr_xml when '-h', '--human' self.writer = HumanWriter.new(STDOUT) when '-x', '--xml' From 940da312f41249bb1168ca42f23dad324fd0e852 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Wed, 3 Aug 2011 06:16:54 -0400 Subject: [PATCH 083/219] Adds sample bzr logs for testing. --- test/data/branch_merge.bzr_xml_log | 87 ++++++++++++++++++++++++++++++ test/data/simple.bzr_xml_log | 41 ++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 test/data/branch_merge.bzr_xml_log create mode 100644 test/data/simple.bzr_xml_log diff --git a/test/data/branch_merge.bzr_xml_log b/test/data/branch_merge.bzr_xml_log new file mode 100644 index 00000000..c42c223d --- /dev/null +++ b/test/data/branch_merge.bzr_xml_log @@ -0,0 +1,87 @@ + + + + 7 + amujumdar@blackducksoftware.com-20110722184732-seu94oakpvy66nuu + + amujumdar@blackducksoftware.com-20110722184717-u0ykbdm4pquaj0ai + + Abhay <amujumdar@blackducksoftware.com> + myproject + Fri 2011-07-22 14:47:32 -0400 + + + + subdir/test4.txt + + + + + 8 + amujumdar@blackducksoftware.com-20110722184839-og2qcc9g9re09iuu + + amujumdar@blackducksoftware.com-20110722184732-seu94oakpvy66nuu + amujumdar@blackducksoftware.com-20110722184630-kn5n3oo0c9hns3i8 + + Abhay <amujumdar@blackducksoftware.com> + myproject + Fri 2011-07-22 14:48:39 -0400 + + + + test1.txt + test2.txt + + + + + 5.1.1 + amujumdar@blackducksoftware.com-20110722184557-splhn3urfvq9mqfl + + amujumdar@blackducksoftware.com-20110722180659-be4tmnzss40h05o6 + + Abhay <amujumdar@blackducksoftware.com> + feature_a + Fri 2011-07-22 14:45:57 -0400 + + + + test1.txt + + + + + 5.1.2 + amujumdar@blackducksoftware.com-20110722184630-kn5n3oo0c9hns3i8 + + amujumdar@blackducksoftware.com-20110722184557-splhn3urfvq9mqfl + + Abhay <amujumdar@blackducksoftware.com> + feature_a + Fri 2011-07-22 14:46:30 -0400 + + + + test2.txt + + + + + + + 9 + amujumdar@blackducksoftware.com-20110722185038-e0i4d1mdxwpipxc4 + + amujumdar@blackducksoftware.com-20110722184839-og2qcc9g9re09iuu + + Abhay <amujumdar@blackducksoftware.com> + myproject + Fri 2011-07-22 14:50:38 -0400 + + + + test1.txt + + + + diff --git a/test/data/simple.bzr_xml_log b/test/data/simple.bzr_xml_log new file mode 100644 index 00000000..6e8dd78b --- /dev/null +++ b/test/data/simple.bzr_xml_log @@ -0,0 +1,41 @@ + + + + 9 + amujumdar@blackducksoftware.com-20110722185038-e0i4d1mdxwpipxc4 + + amujumdar@blackducksoftware.com-20110722184839-og2qcc9g9re09iuu + + Abhay <amujumdar@blackducksoftware.com> + myproject + Fri 2011-07-22 14:50:38 -0400 + + + + test1.txt + + + + + 10 + test@example.com-20110725174345-brbpkwumeh07aoh8 + + amujumdar@blackducksoftware.com-20110722185038-e0i4d1mdxwpipxc4 + + test <test@example.com> + myproject + Mon 2011-07-25 13:43:45 -0400 + + + + test2.txt + + + test_a.txt + + + subdir/test_b.txt + + + + From 486a700baba7a6c5f1e7226f214113a3a662e516 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Wed, 3 Aug 2011 12:10:18 -0400 Subject: [PATCH 084/219] Fixes duplicate merge commits. Yields merge commit on tag and not tag. --- lib/scm/parsers/bzr_xml_parser.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scm/parsers/bzr_xml_parser.rb b/lib/scm/parsers/bzr_xml_parser.rb index ad666d1a..2958618d 100644 --- a/lib/scm/parsers/bzr_xml_parser.rb +++ b/lib/scm/parsers/bzr_xml_parser.rb @@ -49,7 +49,7 @@ def tag_end(name) when 'affected-files' @commit.diffs = remove_dupes(@diffs) when 'merge' - @callback.call(@merge_commit) + @commit = @merge_commit @merge_commit = nil end end From 85ddb3b3e6a27c5d8b50a60b871b00320970edd8 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Wed, 3 Aug 2011 12:15:19 -0400 Subject: [PATCH 085/219] Fixes commits and commit_tokens method to use xmllog. --- lib/scm/adapters/bzr/commits.rb | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/scm/adapters/bzr/commits.rb b/lib/scm/adapters/bzr/commits.rb index 233f4f7d..174f2b6c 100644 --- a/lib/scm/adapters/bzr/commits.rb +++ b/lib/scm/adapters/bzr/commits.rb @@ -8,7 +8,7 @@ def commit_count(opts={}) # Return the list of commit tokens following +after+. def commit_tokens(opts={}) - tokens = run("#{rev_list_command(opts)} | grep -E -e '^( *)revision-id: ' | cut -f2- -d':' | cut -c 2-").split("\n") + tokens = commits(opts).map { |c| c.token } # Bzr returns everything after *and including* after. # We want to exclude it. @@ -28,7 +28,7 @@ def commit_tokens(opts={}) def commits(opts={}) after = opts[:after] log = run("#{rev_list_command(opts)} | cat") - a = Scm::Parsers::BzrParser.parse(log) + a = Scm::Parsers::BzrXmlParser.parse(log) if a.any? && a.first.token == after a[1..-1] @@ -39,8 +39,8 @@ def commits(opts={}) # Returns a single commit, including its diffs def verbose_commit(token) - log = run("cd '#{self.url}' && bzr log --long --show-id -v --limit 1 -c #{to_rev_param(token)}") - Scm::Parsers::BzrParser.parse(log).first + log = run("cd '#{self.url}' && bzr xmllog --show-id -v --limit 1 -c #{to_rev_param(token)}") + Scm::Parsers::BzrXmlParser.parse(log).first end # Yields each commit after +after+, including its diffs. @@ -51,7 +51,7 @@ def verbose_commit(token) def each_commit(opts={}) after = opts[:after] open_log_file(opts) do |io| - Scm::Parsers::BzrParser.parse(io) do |commit| + Scm::Parsers::BzrXmlParser.parse(io) do |commit| yield remove_directories(commit) if block_given? && commit.token != after end end @@ -95,10 +95,12 @@ def log_filename File.join('/tmp', (self.url).gsub(/\W/,'') + '.log') end + # Uses xmllog command for output to be used by BzrXmlParser. def rev_list_command(opts={}) after = opts[:after] trunk_only = opts[:trunk_only] ? '--levels=1' : '--include-merges' - "cd '#{self.url}' && bzr log --long --show-id --forward #{trunk_only} -r #{to_rev_param(after)}.." + "cd '#{self.url}' && bzr xmllog --show-id --forward #{trunk_only} -r #{to_rev_param(after)}.." end - end + + end end From bbe92a1761a2a731d1154d466f91a95ea9ee4dd4 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Wed, 3 Aug 2011 12:17:47 -0400 Subject: [PATCH 086/219] Fixes tests, to accomodate correct branch/merge commit ordering. Funny business with commit ordering has been fixed by BzrXmlParser. Now, when we request that Bzr iterate commits in the '--forward' direction, we correctly get the branch commits *before* the merge that brought them in. --- test/unit/bzr_commits_test.rb | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/test/unit/bzr_commits_test.rb b/test/unit/bzr_commits_test.rb index 9e9d28aa..4068cd33 100644 --- a/test/unit/bzr_commits_test.rb +++ b/test/unit/bzr_commits_test.rb @@ -1,4 +1,6 @@ require File.dirname(__FILE__) + '/../test_helper' +require 'rubygems' +require 'ruby-debug' module Scm::Adapters class BzrCommitsTest < Scm::Test @@ -36,17 +38,14 @@ def test_commit_tokens_after end def test_commit_tokens_trunk_only_false - # There's some funny business with commit ordering here. - # When we request that Bzr iterate commits in the '--forward' direction, - # we actually get the branch commits *after* the merge that brought them in. - # This makes my head hurt, and I'm not yet sure whether this will be a problem - # down the road. For now, just accepts that bzr does this. + # Funny business with commit ordering has been fixed by BzrXmlParser. + # Now we always see branch commits before merge commit. with_bzr_repository('bzr_with_branch') do |bzr| assert_equal [ 'test@example.com-20090206214301-s93cethy9atcqu9h', 'test@example.com-20090206214451-lzjngefdyw3vmgms', - 'test@example.com-20090206214515-21lkfj3dbocao5pr', # merge commit - 'test@example.com-20090206214350-rqhdpz92l11eoq2t' # branch commit -- after merge! + 'test@example.com-20090206214350-rqhdpz92l11eoq2t', # branch commit + 'test@example.com-20090206214515-21lkfj3dbocao5pr' # merge commit ], bzr.commit_tokens(:trunk_only => false) end end @@ -56,8 +55,7 @@ def test_commit_tokens_trunk_only_true assert_equal [ 'test@example.com-20090206214301-s93cethy9atcqu9h', 'test@example.com-20090206214451-lzjngefdyw3vmgms', - 'test@example.com-20090206214515-21lkfj3dbocao5pr', # merge commit - # 'test@example.com-20090206214350-rqhdpz92l11eoq2t' # branch commit + 'test@example.com-20090206214515-21lkfj3dbocao5pr' # merge commit ], bzr.commit_tokens(:trunk_only => true) end end @@ -67,8 +65,8 @@ def test_commits_trunk_only_false assert_equal [ 'test@example.com-20090206214301-s93cethy9atcqu9h', 'test@example.com-20090206214451-lzjngefdyw3vmgms', - 'test@example.com-20090206214515-21lkfj3dbocao5pr', # merge commit - 'test@example.com-20090206214350-rqhdpz92l11eoq2t' # branch commit -- after merge! + 'test@example.com-20090206214350-rqhdpz92l11eoq2t', # branch commit + 'test@example.com-20090206214515-21lkfj3dbocao5pr' # merge commit ], bzr.commits(:trunk_only => false).map { |c| c.token } end end @@ -78,8 +76,7 @@ def test_commits_trunk_only_true assert_equal [ 'test@example.com-20090206214301-s93cethy9atcqu9h', 'test@example.com-20090206214451-lzjngefdyw3vmgms', - 'test@example.com-20090206214515-21lkfj3dbocao5pr', # merge commit - # 'test@example.com-20090206214350-rqhdpz92l11eoq2t' # branch commit + 'test@example.com-20090206214515-21lkfj3dbocao5pr' # merge commit ], bzr.commits(:trunk_only => true).map { |c| c.token } end end @@ -126,8 +123,8 @@ def test_each_commit_trunk_only_false assert_equal [ 'test@example.com-20090206214301-s93cethy9atcqu9h', 'test@example.com-20090206214451-lzjngefdyw3vmgms', - 'test@example.com-20090206214515-21lkfj3dbocao5pr', # merge commit - 'test@example.com-20090206214350-rqhdpz92l11eoq2t' # branch commit -- after merge! + 'test@example.com-20090206214350-rqhdpz92l11eoq2t', # branch commit + 'test@example.com-20090206214515-21lkfj3dbocao5pr' # merge commit ], commits.map { |c| c.token } end end From f367d38e2246a04a0f70d50222e824a30370e784 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Wed, 3 Aug 2011 12:24:48 -0400 Subject: [PATCH 087/219] Fixes tests to match xmllog output. After log parsing, commit messages don't have trailing newline anymore. --- test/unit/bzr_pull_test.rb | 2 +- test/unit/bzr_push_test.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/bzr_pull_test.rb b/test/unit/bzr_pull_test.rb index 9c8a29e3..77db85bc 100644 --- a/test/unit/bzr_pull_test.rb +++ b/test/unit/bzr_pull_test.rb @@ -17,7 +17,7 @@ def test_pull # Commit some new code on the original and pull again src.run "cd '#{src.url}' && touch foo && bzr add foo && bzr whoami 'test ' && bzr commit -m test" - assert_equal "test\n", src.commits.last.message + assert_equal "test", src.commits.last.message assert_equal "test", src.commits.last.committer_name assert_equal "test@example.com", src.commits.last.committer_email diff --git a/test/unit/bzr_push_test.rb b/test/unit/bzr_push_test.rb index a64d0375..05a35983 100644 --- a/test/unit/bzr_push_test.rb +++ b/test/unit/bzr_push_test.rb @@ -47,7 +47,7 @@ def test_push # Commit some new code on the original and pull again src.run "cd '#{src.url}' && touch foo && bzr add foo && bzr whoami 'test ' && bzr commit -m test" - assert_equal "test\n", src.commits.last.message + assert_equal "test", src.commits.last.message assert_equal "test", src.commits.last.committer_name assert_equal "test@example.com", src.commits.last.committer_email From dbb5c09265d5b6e589abe6a82cf155ed86b1d25f Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Wed, 3 Aug 2011 13:40:31 -0400 Subject: [PATCH 088/219] Fixes parsing of multi-level nested branch/merge. Adds bzr_with_nested_branches repository for tests that has two level nested branching and merging. --- lib/scm/parsers/bzr_xml_parser.rb | 6 +- .../bzr_with_nested_branches/.bzr/README | 3 + .../.bzr/branch-format | 1 + .../.bzr/branch/branch.conf | 1 + .../.bzr/branch/format | 1 + .../.bzr/branch/last-revision | 1 + .../bzr_with_nested_branches/.bzr/branch/tags | 0 .../.bzr/checkout/conflicts | 1 + .../.bzr/checkout/dirstate | Bin 0 -> 1557 bytes .../.bzr/checkout/format | 1 + .../.bzr/checkout/merge-hashes | 6 + .../.bzr/repository/format | 1 + .../0428489d1a03d05c496c2c429fe96e90.iix | Bin 0 -> 175 bytes .../0428489d1a03d05c496c2c429fe96e90.rix | Bin 0 -> 174 bytes .../0428489d1a03d05c496c2c429fe96e90.six | 5 + .../0428489d1a03d05c496c2c429fe96e90.tix | Bin 0 -> 267 bytes .../30fcaac048e328a7727156986055f6e8.iix | Bin 0 -> 450 bytes .../30fcaac048e328a7727156986055f6e8.rix | Bin 0 -> 432 bytes .../30fcaac048e328a7727156986055f6e8.six | 5 + .../30fcaac048e328a7727156986055f6e8.tix | Bin 0 -> 496 bytes .../673cc297ed321f667e1d8d4fff600829.iix | Bin 0 -> 777 bytes .../673cc297ed321f667e1d8d4fff600829.rix | Bin 0 -> 745 bytes .../673cc297ed321f667e1d8d4fff600829.six | 5 + .../673cc297ed321f667e1d8d4fff600829.tix | Bin 0 -> 922 bytes .../71af8bae249bcb824a4ff17c62029142.iix | Bin 0 -> 178 bytes .../71af8bae249bcb824a4ff17c62029142.rix | Bin 0 -> 174 bytes .../71af8bae249bcb824a4ff17c62029142.six | 5 + .../71af8bae249bcb824a4ff17c62029142.tix | Bin 0 -> 265 bytes .../7202eb77b81a80eca5296f317ed42149.iix | Bin 0 -> 177 bytes .../7202eb77b81a80eca5296f317ed42149.rix | Bin 0 -> 174 bytes .../7202eb77b81a80eca5296f317ed42149.six | 5 + .../7202eb77b81a80eca5296f317ed42149.tix | 5 + .../8a571ba35ee54cd133b71e967442fe17.iix | Bin 0 -> 178 bytes .../8a571ba35ee54cd133b71e967442fe17.rix | Bin 0 -> 174 bytes .../8a571ba35ee54cd133b71e967442fe17.six | 5 + .../8a571ba35ee54cd133b71e967442fe17.tix | Bin 0 -> 163 bytes .../a06b9c10004fc3e05affee8cf0a9febd.iix | Bin 0 -> 120 bytes .../a06b9c10004fc3e05affee8cf0a9febd.rix | Bin 0 -> 119 bytes .../a06b9c10004fc3e05affee8cf0a9febd.six | 5 + .../a06b9c10004fc3e05affee8cf0a9febd.tix | Bin 0 -> 163 bytes .../da6c79a024c70fd6831e323430a96cc8.iix | Bin 0 -> 235 bytes .../da6c79a024c70fd6831e323430a96cc8.rix | Bin 0 -> 232 bytes .../da6c79a024c70fd6831e323430a96cc8.six | 5 + .../da6c79a024c70fd6831e323430a96cc8.tix | 5 + .../f35e1020b6a55c81b6d2fe4c7bcd4645.iix | Bin 0 -> 175 bytes .../f35e1020b6a55c81b6d2fe4c7bcd4645.rix | Bin 0 -> 174 bytes .../f35e1020b6a55c81b6d2fe4c7bcd4645.six | 5 + .../f35e1020b6a55c81b6d2fe4c7bcd4645.tix | Bin 0 -> 163 bytes .../.bzr/repository/pack-names | Bin 0 -> 209 bytes .../0428489d1a03d05c496c2c429fe96e90.pack | Bin 0 -> 1115 bytes .../30fcaac048e328a7727156986055f6e8.pack | Bin 0 -> 4367 bytes .../673cc297ed321f667e1d8d4fff600829.pack | Bin 0 -> 7946 bytes .../71af8bae249bcb824a4ff17c62029142.pack | Bin 0 -> 785 bytes .../7202eb77b81a80eca5296f317ed42149.pack | Bin 0 -> 556 bytes .../8a571ba35ee54cd133b71e967442fe17.pack | Bin 0 -> 781 bytes .../a06b9c10004fc3e05affee8cf0a9febd.pack | Bin 0 -> 752 bytes .../da6c79a024c70fd6831e323430a96cc8.pack | Bin 0 -> 790 bytes .../f35e1020b6a55c81b6d2fe4c7bcd4645.pack | Bin 0 -> 920 bytes .../.bzr/repository/upload/.gitignore | 1 + .../bzr_with_nested_branches/file1.txt | 2 + .../bzr_with_nested_branches/file3.txt | 1 + .../bzr_with_nested_branches/file4.txt | 1 + .../bzr_with_nested_branches/file5.txt | 4 + .../bzr_with_nested_branches/file6.txt | 2 + .../bzr_with_nested_branches/file7.txt | 2 + test/unit/bzr_commits_test.rb | 103 ++++++++++++++++++ 66 files changed, 190 insertions(+), 3 deletions(-) create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/README create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/branch-format create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/branch/branch.conf create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/branch/format create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/branch/last-revision create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/branch/tags create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/checkout/conflicts create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/checkout/dirstate create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/checkout/format create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/checkout/merge-hashes create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/format create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/0428489d1a03d05c496c2c429fe96e90.iix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/0428489d1a03d05c496c2c429fe96e90.rix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/0428489d1a03d05c496c2c429fe96e90.six create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/0428489d1a03d05c496c2c429fe96e90.tix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/30fcaac048e328a7727156986055f6e8.iix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/30fcaac048e328a7727156986055f6e8.rix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/30fcaac048e328a7727156986055f6e8.six create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/30fcaac048e328a7727156986055f6e8.tix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/673cc297ed321f667e1d8d4fff600829.iix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/673cc297ed321f667e1d8d4fff600829.rix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/673cc297ed321f667e1d8d4fff600829.six create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/673cc297ed321f667e1d8d4fff600829.tix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/71af8bae249bcb824a4ff17c62029142.iix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/71af8bae249bcb824a4ff17c62029142.rix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/71af8bae249bcb824a4ff17c62029142.six create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/71af8bae249bcb824a4ff17c62029142.tix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/7202eb77b81a80eca5296f317ed42149.iix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/7202eb77b81a80eca5296f317ed42149.rix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/7202eb77b81a80eca5296f317ed42149.six create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/7202eb77b81a80eca5296f317ed42149.tix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/8a571ba35ee54cd133b71e967442fe17.iix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/8a571ba35ee54cd133b71e967442fe17.rix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/8a571ba35ee54cd133b71e967442fe17.six create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/8a571ba35ee54cd133b71e967442fe17.tix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/a06b9c10004fc3e05affee8cf0a9febd.iix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/a06b9c10004fc3e05affee8cf0a9febd.rix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/a06b9c10004fc3e05affee8cf0a9febd.six create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/a06b9c10004fc3e05affee8cf0a9febd.tix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/da6c79a024c70fd6831e323430a96cc8.iix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/da6c79a024c70fd6831e323430a96cc8.rix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/da6c79a024c70fd6831e323430a96cc8.six create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/da6c79a024c70fd6831e323430a96cc8.tix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/f35e1020b6a55c81b6d2fe4c7bcd4645.iix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/f35e1020b6a55c81b6d2fe4c7bcd4645.rix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/f35e1020b6a55c81b6d2fe4c7bcd4645.six create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/indices/f35e1020b6a55c81b6d2fe4c7bcd4645.tix create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/pack-names create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/packs/0428489d1a03d05c496c2c429fe96e90.pack create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/packs/30fcaac048e328a7727156986055f6e8.pack create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/packs/673cc297ed321f667e1d8d4fff600829.pack create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/packs/71af8bae249bcb824a4ff17c62029142.pack create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/packs/7202eb77b81a80eca5296f317ed42149.pack create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/packs/8a571ba35ee54cd133b71e967442fe17.pack create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/packs/a06b9c10004fc3e05affee8cf0a9febd.pack create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/packs/da6c79a024c70fd6831e323430a96cc8.pack create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/packs/f35e1020b6a55c81b6d2fe4c7bcd4645.pack create mode 100644 test/repositories/bzr_with_nested_branches/.bzr/repository/upload/.gitignore create mode 100644 test/repositories/bzr_with_nested_branches/file1.txt create mode 100644 test/repositories/bzr_with_nested_branches/file3.txt create mode 100644 test/repositories/bzr_with_nested_branches/file4.txt create mode 100644 test/repositories/bzr_with_nested_branches/file5.txt create mode 100644 test/repositories/bzr_with_nested_branches/file6.txt create mode 100644 test/repositories/bzr_with_nested_branches/file7.txt diff --git a/lib/scm/parsers/bzr_xml_parser.rb b/lib/scm/parsers/bzr_xml_parser.rb index 2958618d..ed970b8d 100644 --- a/lib/scm/parsers/bzr_xml_parser.rb +++ b/lib/scm/parsers/bzr_xml_parser.rb @@ -9,6 +9,7 @@ class BazaarListener def initialize(callback) @callback = callback + @merge_commit = [] end attr_accessor :text, :commit, :diff @@ -26,7 +27,7 @@ def tag_start(name, attrs) @before_path = attrs['oldpath'] when 'merge' # This is a merge commit, save it and pop it after all branch commits - @merge_commit = @commit + @merge_commit.push(@commit) end end @@ -49,8 +50,7 @@ def tag_end(name) when 'affected-files' @commit.diffs = remove_dupes(@diffs) when 'merge' - @commit = @merge_commit - @merge_commit = nil + @commit = @merge_commit.pop end end diff --git a/test/repositories/bzr_with_nested_branches/.bzr/README b/test/repositories/bzr_with_nested_branches/.bzr/README new file mode 100644 index 00000000..4f8e767e --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/.bzr/README @@ -0,0 +1,3 @@ +This is a Bazaar control directory. +Do not change any files in this directory. +See http://bazaar-vcs.org/ for more information about Bazaar. diff --git a/test/repositories/bzr_with_nested_branches/.bzr/branch-format b/test/repositories/bzr_with_nested_branches/.bzr/branch-format new file mode 100644 index 00000000..9eb09b73 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/.bzr/branch-format @@ -0,0 +1 @@ +Bazaar-NG meta directory, format 1 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/branch/branch.conf b/test/repositories/bzr_with_nested_branches/.bzr/branch/branch.conf new file mode 100644 index 00000000..7d11ab06 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/.bzr/branch/branch.conf @@ -0,0 +1 @@ +submit_branch = file:///home/amujumdar/app/ohloh_scm/test/repositories/bzr_branch_a/ diff --git a/test/repositories/bzr_with_nested_branches/.bzr/branch/format b/test/repositories/bzr_with_nested_branches/.bzr/branch/format new file mode 100644 index 00000000..1fc6b88e --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/.bzr/branch/format @@ -0,0 +1 @@ +Bazaar Branch Format 6 (bzr 0.15) diff --git a/test/repositories/bzr_with_nested_branches/.bzr/branch/last-revision b/test/repositories/bzr_with_nested_branches/.bzr/branch/last-revision new file mode 100644 index 00000000..3e4bc166 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/.bzr/branch/last-revision @@ -0,0 +1 @@ +7 test@example.com-20110803170818-v44umypquqg8migo diff --git a/test/repositories/bzr_with_nested_branches/.bzr/branch/tags b/test/repositories/bzr_with_nested_branches/.bzr/branch/tags new file mode 100644 index 00000000..e69de29b diff --git a/test/repositories/bzr_with_nested_branches/.bzr/checkout/conflicts b/test/repositories/bzr_with_nested_branches/.bzr/checkout/conflicts new file mode 100644 index 00000000..0dc2d3a0 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/.bzr/checkout/conflicts @@ -0,0 +1 @@ +BZR conflict list format 1 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/checkout/dirstate b/test/repositories/bzr_with_nested_branches/.bzr/checkout/dirstate new file mode 100644 index 0000000000000000000000000000000000000000..6afcd64b99ad7fc4287abce2ca9ec8b5bdbbbc9e GIT binary patch literal 1557 zcmbW%%Wm676b4|f{S*SarZH#EnOjz25!LOcLW2}&y9ws1i$zkVD2dY3cf^E>3%Cv( z0t9~y$iw;O_LH+0Yr9!kcl+M`T6w8Q(ot)0DZyXEsPi#)bx#|9ACT3N5!HXN?wdX?f$ zI;Q8J5$STjuMa0HtZ&otk)OAtlwvSZ>i|wmFOmgsI0fmfh*mn4BnniXSOJst!=Eom z>(eBCTftYPB(OXvW-+c3+Grl_873*+q+@y}C4;g|5xn1kIqgET;qGyiYGIR*(fN>P z5F%;_IT@dWV&E+&?GS+%puW!O{6%RyN#9oR|D|MzmkPV)#MYPC5Kkazl8T#jO#hYY za&?hr8|&SH5If{*l;#!dqV!BSZ(IaTIuO(5YL|(7!IBh`8C&p4`tZ`~t@o4kZ3TZ& zDsR#;W$Eoe$y>HG=YD{CNW%)7l|1i8X@OV4@SQ8~zbqz?q(ZRTD<@e}hM_^{Si-_kru;a9?SV|_<3 zWC98R;S}23UFm{DXGA2M=ahT`B`IcPRJy=x!Pf|a^V05*a&0cM=6vJz<&p{i0yv_% A#Q*>R literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/checkout/format b/test/repositories/bzr_with_nested_branches/.bzr/checkout/format new file mode 100644 index 00000000..9ffb5e44 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/.bzr/checkout/format @@ -0,0 +1 @@ +Bazaar Working Tree Format 4 (bzr 0.15) diff --git a/test/repositories/bzr_with_nested_branches/.bzr/checkout/merge-hashes b/test/repositories/bzr_with_nested_branches/.bzr/checkout/merge-hashes new file mode 100644 index 00000000..16bc5227 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/.bzr/checkout/merge-hashes @@ -0,0 +1,6 @@ +BZR merge-modified list format 1 +file_id: file7.txt-20110803170452-nymk4xd500w4qn43-1 +hash: 35115b73ad026bdb3b95e4abc64cf1764ef65e78 + +file_id: file6.txt-20110803170200-9ytx1mxfxh3nh6yp-1 +hash: f654c347dda8c7b60f790393bb0f3d02241c4197 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/format b/test/repositories/bzr_with_nested_branches/.bzr/repository/format new file mode 100644 index 00000000..520349da --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/.bzr/repository/format @@ -0,0 +1 @@ +Bazaar pack repository format 1 (needs bzr 0.92) diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/0428489d1a03d05c496c2c429fe96e90.iix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/0428489d1a03d05c496c2c429fe96e90.iix new file mode 100644 index 0000000000000000000000000000000000000000..94a5cc60d270995998391e8fc580b1588752fb70 GIT binary patch literal 175 zcmaLOK@Ng25J1sx?J0Tz%(P4cU6>d*##4|X3`n3;EhHkRmlL@8$y@vz?L^t!GrgYX zAsuhVYDpb8nfqoQmvy-~J@L2UnIp?Vt7n#@sg<-{7m6*NQyvNj5WoQfIFC>ak%a1X n@_iWE^bU%Y`tx8wS5#$|4~#nty54$J3Vb*zQ`*WP)>{7nj}SA* literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/0428489d1a03d05c496c2c429fe96e90.rix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/0428489d1a03d05c496c2c429fe96e90.rix new file mode 100644 index 0000000000000000000000000000000000000000..dc5836edeef26059e0a4589d28d7f6e9afb41091 GIT binary patch literal 174 zcmaLOK@Ng25J1tcdx~BFGnA>=1&MKEJOvrTv=U&dg+%1^8V}&|zvN$NC(7oU>2WtV z>3K7ymeg~bIkeNTtV>hsk>4#(JhS|AV)6L l;A5AbUXfCN9`tC7y2|o`VP`=bN{32;^UBmmXDakse*j!3GsFM@ literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/0428489d1a03d05c496c2c429fe96e90.six b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/0428489d1a03d05c496c2c429fe96e90.six new file mode 100644 index 00000000..1206f930 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/0428489d1a03d05c496c2c429fe96e90.six @@ -0,0 +1,5 @@ +Bazaar Graph Index 1 +node_ref_lists=0 +key_elements=1 +len=0 + diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/0428489d1a03d05c496c2c429fe96e90.tix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/0428489d1a03d05c496c2c429fe96e90.tix new file mode 100644 index 0000000000000000000000000000000000000000..bca0f049eaea52961f88888cf0fca278c0bb750d GIT binary patch literal 267 zcmbWxO%8%E6a?UI?J0VJlD_r*gBQbGg^5)DY8y3cBA7we+!wLf1< z1+=S5m_SP?NSpVD!uo+j_jrMBm4vOaBV&kIl`uhIY%$bZLxZZbNm>7-D^So$=B60N zRRxfeL<9OgKvetn(F`s(6VbJ^IWtDeR3*i5(){~Kqij7x>e@J%@p*T~=j-2y4~bNU LNOVdxs5t)xNho{| literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/30fcaac048e328a7727156986055f6e8.rix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/30fcaac048e328a7727156986055f6e8.rix new file mode 100644 index 0000000000000000000000000000000000000000..f5335640dbd131fa7586e14424fb73b9c2021002 GIT binary patch literal 432 zcmaLTO>V+46a-+eBlQlxfYE#Q^WOpqbyM{e$O#S&O&pY@V0`*o93abCd>YMsh7!WU zzm{JGsh;)mv~-ce;$W*TaVcM#@9KHaf<03$C!?~ncFny(;B8W9OmUJB!CAA z1VEmouxd$97)need(^}NW6c)V?G$sE?qfW3^HdQcI8bOoffRkAsa>2;uGiuEQweC# zI7zOI-PeTTfkXFrfo@5`X57daB32EaEAqQs1BqgD(SP{{GU}{~soW~Yt#*~WeJ-U4 z>%$Dbm`Tc8=SpErD#Li)XSmY1>kT+N|? literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/30fcaac048e328a7727156986055f6e8.six b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/30fcaac048e328a7727156986055f6e8.six new file mode 100644 index 00000000..1206f930 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/30fcaac048e328a7727156986055f6e8.six @@ -0,0 +1,5 @@ +Bazaar Graph Index 1 +node_ref_lists=0 +key_elements=1 +len=0 + diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/30fcaac048e328a7727156986055f6e8.tix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/30fcaac048e328a7727156986055f6e8.tix new file mode 100644 index 0000000000000000000000000000000000000000..db2744b376a5eb1aebc766578b2077356e496865 GIT binary patch literal 496 zcmb`Dv2Md46h&F%uiyuW9*+lxAyU<)>Q_W0!L<`ZQk$ljudkJ<>e3~{9qw>-bndIK z-cS5(^0%J9r&B0gHtBi_`zdt$ahUVG!{!o}eHcRw=~2g!cGPsk7|b@8ED)pw3rer=eTcG$^S5Qbnfc zqoHcYkb+x#)A+WY9-c92WI-VdV}J`hT7>qrMXToY4PA~&%SIT@0%PSGm-QoVVZ0CV z?L3XNdLh7p5*8H5s>yn+XXle^OlYrEQ4R|VsiQzrx5o@Es+Z`_uN_RS6|Cq6#$ed%Mr{mfWARkUfB7Jqm;L^%b5UH7ZhSx jC4U_RwW}uB&UNbS@O}3-7T{d_UTxFAv-r9NUw7Iq)w!;WMGhDW;tW1xX?L&#Abnn_{( zG~h8@TlB#Veiw`hS!i^!(BjCggst}mHlZ+iJzZ0}JPU1Qi4N{9mxnk(-Az7vyAG;# zU6US;F-gQYz1>I2$(7Cw&hZEO93sh9C}N(mY7NW!6*fQJ$MA7ZQz=>quz%$KqK^3uJ_dXn;XwmCDVsN|Ox%U>yb9o?_V)(N(A6MHlM+@10H R_Ur$nMHvl+)ujWfs{bm4%;5k4 literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/673cc297ed321f667e1d8d4fff600829.six b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/673cc297ed321f667e1d8d4fff600829.six new file mode 100644 index 00000000..1206f930 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/673cc297ed321f667e1d8d4fff600829.six @@ -0,0 +1,5 @@ +Bazaar Graph Index 1 +node_ref_lists=0 +key_elements=1 +len=0 + diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/673cc297ed321f667e1d8d4fff600829.tix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/673cc297ed321f667e1d8d4fff600829.tix new file mode 100644 index 0000000000000000000000000000000000000000..80600395c86679627e3836b5cf98fcafec9ceaaf GIT binary patch literal 922 zcmb`FJ&xNj5JuVBr_cpx49Ouy77HxW1UZF4Nt9$uqHO({(&@vMg9O_Svw@(2YaiNAHHxQVMpH=?mW2i++N0MeB;N)t!LM|&iQ?9oqyBE^3pnXn!-dm zfB_B&z=hD%K1w?dRc-vdz2uO2?LlUK>inw&g@y}k!3>|^XYi=5lMO8QI3oqo+ zYi<2qx0o{F?&S)*moi2~5Z^)K9}sFfj@|sQ(&l}+G<o>QY!|8oRRR z1C{;*Qolfqfd;|Sm={p9PJwly47KpJT5l0Fxp8`T!FIRSo$|hmQT;v`UDzdGR*)GAn3Qe_K`jq)Vl}w>$ja=z^s^aCPW{?77zzpS zz`IBBg_#7TTN*YwhbwR=gV@y54B?}M&$hpW6l-C}MP1CMI?k`T-Znx~5QjL?Ok&Io H;duNBSDgUS literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/71af8bae249bcb824a4ff17c62029142.iix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/71af8bae249bcb824a4ff17c62029142.iix new file mode 100644 index 0000000000000000000000000000000000000000..273571ca23a584fcbdb8418361a2965dbce990f8 GIT binary patch literal 178 zcmaKjK@P$o5CFN#EBHXo0>#R~#CS2jf^5^RH3imCn-pJfU*KUTnZw-hi&)gX;CoV! zJkX}J%sfyiG=}(EKFh_(nQEX&iSnLWM#{Un&%9k1Og$dCJR1Yx!9WXOT4$TJ1GF@a m7Rk?8wLl^MJx-sS+QX)uWjv*cd02%2=MOtV>CP+Ttdu_wD>Q%r literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/71af8bae249bcb824a4ff17c62029142.rix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/71af8bae249bcb824a4ff17c62029142.rix new file mode 100644 index 0000000000000000000000000000000000000000..b0c9c3b094547f6c0c7f8b2fb252250660d26c40 GIT binary patch literal 174 zcmaLOK@P$o5I|AZoPrC~3{X@SCdQ5N6l6%JVoDhUHfcS*#sj$gFZmaIBUW{-_)O|n z23nPtg$D|i#*iQF)lOPYv<1pEQ~714@meOdE j{DhkpD8#?V>0`G=Shcf^`#CWWixA+vP`x$EIwR!=JhC&; literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/71af8bae249bcb824a4ff17c62029142.six b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/71af8bae249bcb824a4ff17c62029142.six new file mode 100644 index 00000000..1206f930 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/71af8bae249bcb824a4ff17c62029142.six @@ -0,0 +1,5 @@ +Bazaar Graph Index 1 +node_ref_lists=0 +key_elements=1 +len=0 + diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/71af8bae249bcb824a4ff17c62029142.tix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/71af8bae249bcb824a4ff17c62029142.tix new file mode 100644 index 0000000000000000000000000000000000000000..12a7b8fef40994f8327c9f60de3a823104607fd1 GIT binary patch literal 265 zcmb`9I}(C06adqjQ{)0+UJ`;*Fyq)bo`QME<0Fu000mC3V`p!%#TL6K+z^8}2fR1p z;!0YC;?9?p2deVE9j7tVyrVUzo(6JX?a5_|S8Y!!nwCjwfD|;u0NR*?#8-u5sGHQy z+tr#-fsqgOPZ4Wr13coIZe5awE}5SU8T;4Ys)Jk$Sd=v$lcDjxoEZa~ N?mjRPYoW}Z^EXRWPGbN7 literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/7202eb77b81a80eca5296f317ed42149.iix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/7202eb77b81a80eca5296f317ed42149.iix new file mode 100644 index 0000000000000000000000000000000000000000..cf7f8ffc5137c250a6ee538789cd204251076596 GIT binary patch literal 177 zcmaKjK@Ng25CD6%ujmJAwuKUUFfm??uOQp7fPr?kU;@70zQDswGKab07cr}Q#@D1C zsi$2TnYgDe)6gx?bz3i1&UAFNP^47S$c0idhs67J#Tf9+dDIrbgM}KvI@9VSz;0Z{ m*u;ss{|FS~?^A;wBPMLO*$sXS{PseC^QVGPwN<96r2GN?o;1h+ literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/7202eb77b81a80eca5296f317ed42149.rix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/7202eb77b81a80eca5296f317ed42149.rix new file mode 100644 index 0000000000000000000000000000000000000000..92431c058a297ae3fee645f035577fa6077eabc7 GIT binary patch literal 174 zcmaLOK?=e!5J1tabBbIbGD#b07J|4DPZ1_`+De;@rWI08uXq5L|G~fD8?mTs!N;U- zxu>d(%-mBbG=$~8ZtKa&nf5>nCCa~CD1VV-=6YT+MLcjBwFU5Cp#`wcbb60ajcXW> jX=3hQ0)_bdw4ld?8M|$EgC8S5y%6BMP!^nO97y>AU!*io literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/7202eb77b81a80eca5296f317ed42149.six b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/7202eb77b81a80eca5296f317ed42149.six new file mode 100644 index 00000000..1206f930 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/7202eb77b81a80eca5296f317ed42149.six @@ -0,0 +1,5 @@ +Bazaar Graph Index 1 +node_ref_lists=0 +key_elements=1 +len=0 + diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/7202eb77b81a80eca5296f317ed42149.tix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/7202eb77b81a80eca5296f317ed42149.tix new file mode 100644 index 00000000..78227aa0 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/7202eb77b81a80eca5296f317ed42149.tix @@ -0,0 +1,5 @@ +Bazaar Graph Index 1 +node_ref_lists=2 +key_elements=2 +len=0 + diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/8a571ba35ee54cd133b71e967442fe17.iix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/8a571ba35ee54cd133b71e967442fe17.iix new file mode 100644 index 0000000000000000000000000000000000000000..7a0c57bffcb11f913261ca66fef55237a6ad8b24 GIT binary patch literal 178 zcmaKjK@Ng25CD6%ujmIb+ogaUOpF)fE65TSR7xwY8tUuq3p~subC@%IiGsQWdfwF4 z4ZJBWogcUhJa+aTU-5`?=G3v}gzF_YsM=jdDBT!^RW0QY7<)8V literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/8a571ba35ee54cd133b71e967442fe17.rix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/8a571ba35ee54cd133b71e967442fe17.rix new file mode 100644 index 0000000000000000000000000000000000000000..1b5b38eba690177bf7ba5e2532d98620bfb2c542 GIT binary patch literal 174 zcmaLOK@Ng25J1sc_Y}PVW@roA1&MKEJOvrTfZEd9q6R#@!~?keKY1tm5M_DJ^tj4P z=y{Q)2(jlj^U(U+{G6LoI9^-!JaPD?=djJ#g}5ANnmXFWJQfPkqC$hHv{6NsF`1F? kuD03LuQw3DKV#HpRv*&An|-M{4J!g*WkDK^QdcO%7e=Hrr2qf` literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/8a571ba35ee54cd133b71e967442fe17.six b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/8a571ba35ee54cd133b71e967442fe17.six new file mode 100644 index 00000000..1206f930 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/8a571ba35ee54cd133b71e967442fe17.six @@ -0,0 +1,5 @@ +Bazaar Graph Index 1 +node_ref_lists=0 +key_elements=1 +len=0 + diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/8a571ba35ee54cd133b71e967442fe17.tix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/8a571ba35ee54cd133b71e967442fe17.tix new file mode 100644 index 0000000000000000000000000000000000000000..beccd5bf19941d772dfb7021f0b3894d0a75894a GIT binary patch literal 163 zcmY+*Jr2Sk6aZjWIRzJ>dAw4Up^0%Zo}!`h`b)t=ht|`ZxH*2qcefvFlXxWi9>g;^ z+J)jFI%*PijUV%tYveN>4S8B9{OBpvig%+YEVg}<2w(s~1E5w$X25ECnHehA5A)ec m#bO)ce#>@gZ4p!dHxOlY_^@8RzNnJc?f}M4OlTCUM9#mvg)ij* literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/a06b9c10004fc3e05affee8cf0a9febd.iix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/a06b9c10004fc3e05affee8cf0a9febd.iix new file mode 100644 index 0000000000000000000000000000000000000000..d6e2fe198c790b557cb0a05c68e499fa5262533d GIT binary patch literal 120 zcmWN^K@Ng25CFhl?JN2L%yual4km^R@fFPyR@9bOw`$PW%Vm=3=|?1H5PDqAIZeD8 zt5crX3txP^l~*~U4*c~TdEvCx>d0v`k14OGLd!_|EOUhb9UwRWtQ}U3z|+lq4{ax* QeSehNDPs?4u&K5F1AxyYWdHyG literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/a06b9c10004fc3e05affee8cf0a9febd.rix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/a06b9c10004fc3e05affee8cf0a9febd.rix new file mode 100644 index 0000000000000000000000000000000000000000..1bd5029fbf53cc2b6df915304d7bb91973c0017d GIT binary patch literal 119 zcmW;AK?=e!5CFiO^NRgIWxGuSJqY4Od_~yOwQABtH!9WFD;{U|{9#r&DBsR-%#*Cp z+FT|HDyNVx^-;I2jq(nXWRd)5lKjgu=CbZ8FC%Y?&J7_BNazr$bJX;TcQ?y5`az?A NzKk*8sE3ZcwO?IEBwYXi literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/a06b9c10004fc3e05affee8cf0a9febd.six b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/a06b9c10004fc3e05affee8cf0a9febd.six new file mode 100644 index 00000000..1206f930 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/a06b9c10004fc3e05affee8cf0a9febd.six @@ -0,0 +1,5 @@ +Bazaar Graph Index 1 +node_ref_lists=0 +key_elements=1 +len=0 + diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/a06b9c10004fc3e05affee8cf0a9febd.tix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/a06b9c10004fc3e05affee8cf0a9febd.tix new file mode 100644 index 0000000000000000000000000000000000000000..3833ed28ca1395140ae9766ca31a3c45ab708299 GIT binary patch literal 163 zcmY+*OAdlC5CG6_?J0VJlIaH`3lihTcnUJe@R8DL3yPfH#GT8xcxT)ZqqszT4C3lr z+Jxdhv{XmxYB#1ORhm!qsmaky{zpf?QoI`-schL6sR2sRU;(r-M~UwaQ|yP*ulp@G otyC;DK5VCibAwrk{ok-!<`JH@r~6ctaVpjqV+SUz7RmtUUkK_k8~^|S literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/da6c79a024c70fd6831e323430a96cc8.iix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/da6c79a024c70fd6831e323430a96cc8.iix new file mode 100644 index 0000000000000000000000000000000000000000..4b1f2c2bb2d4159965713a3591b3fde7669ec448 GIT binary patch literal 235 zcmairOOAp-5I}o7op^`70H&%bhh|}7+)U;aq|lN<`-2UR$m!(*PY%WP1`be1N|rSbhZjeDza@@m9OkhmslFL7mRW10^mhnBY~cZCJ0!2$tLO}41Y z9G}oH63Je0M~aowlZ?|rW)6dw?J0$ILIejTR`5-(NHCw;*jN5J)D|^JbVRg2SWuDEYrKHV_mXeNGjlTg#Qnt_ z!bv8BI>eLINzS$FhH==SzR9~5CtkuYorLdY8ixgha z%@Qa-UxWx23M^qwHj6MFo6wc+)mJ6Y*T2Z3&7MRL|L*UP Wdux5yMx|g?Ef7(e!mbTLq4fuk+eI<} literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/da6c79a024c70fd6831e323430a96cc8.six b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/da6c79a024c70fd6831e323430a96cc8.six new file mode 100644 index 00000000..1206f930 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/da6c79a024c70fd6831e323430a96cc8.six @@ -0,0 +1,5 @@ +Bazaar Graph Index 1 +node_ref_lists=0 +key_elements=1 +len=0 + diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/da6c79a024c70fd6831e323430a96cc8.tix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/da6c79a024c70fd6831e323430a96cc8.tix new file mode 100644 index 00000000..78227aa0 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/da6c79a024c70fd6831e323430a96cc8.tix @@ -0,0 +1,5 @@ +Bazaar Graph Index 1 +node_ref_lists=2 +key_elements=2 +len=0 + diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/f35e1020b6a55c81b6d2fe4c7bcd4645.iix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/f35e1020b6a55c81b6d2fe4c7bcd4645.iix new file mode 100644 index 0000000000000000000000000000000000000000..393d9e145b496b0c75768b7ebeaa6889d03c1a00 GIT binary patch literal 175 zcmaLOO$x#=5J2H<%_(w$%H*fiECg{Qo+3=?)JoHdO%xhWZ%^Rn!MAu<{32#`%lMkq zod?>KmYfC(nZ^*G$IhHtRPT`zfWtMPX}me8ZDBav1%cp^#`GJ=altM${%T-Gk^d9 literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/f35e1020b6a55c81b6d2fe4c7bcd4645.rix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/f35e1020b6a55c81b6d2fe4c7bcd4645.rix new file mode 100644 index 0000000000000000000000000000000000000000..a47772736249cf948a494bd796110ed37aec1ec6 GIT binary patch literal 174 zcmaLOK@Ng25J1tcdx~BFGi|BR1&MKEJOvrTR19S*MHA}jH6Fm_f5|`N8!@X(#>b?t zJkqYT$H>~HsCXM literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/f35e1020b6a55c81b6d2fe4c7bcd4645.six b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/f35e1020b6a55c81b6d2fe4c7bcd4645.six new file mode 100644 index 00000000..1206f930 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/f35e1020b6a55c81b6d2fe4c7bcd4645.six @@ -0,0 +1,5 @@ +Bazaar Graph Index 1 +node_ref_lists=0 +key_elements=1 +len=0 + diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/f35e1020b6a55c81b6d2fe4c7bcd4645.tix b/test/repositories/bzr_with_nested_branches/.bzr/repository/indices/f35e1020b6a55c81b6d2fe4c7bcd4645.tix new file mode 100644 index 0000000000000000000000000000000000000000..c4f928f41914407f67c580166e0f41299e93c9f5 GIT binary patch literal 163 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 literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/packs/673cc297ed321f667e1d8d4fff600829.pack b/test/repositories/bzr_with_nested_branches/.bzr/repository/packs/673cc297ed321f667e1d8d4fff600829.pack new file mode 100644 index 0000000000000000000000000000000000000000..143f207de7d1583882e93454affd3dc78161fbdf GIT binary patch literal 7946 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%0AqMUI+bQZ0dgDl4ZKYO6l%B)HS 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 PrT7A`@dQ literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/packs/7202eb77b81a80eca5296f317ed42149.pack b/test/repositories/bzr_with_nested_branches/.bzr/repository/packs/7202eb77b81a80eca5296f317ed42149.pack new file mode 100644 index 0000000000000000000000000000000000000000..bbf60ffe402d98d432d3cf5aa1a54dd9d8bc41c1 GIT binary patch literal 556 zcmV+{0@M9MVR~UK4eE-^SM3PLe8 zHwp?LiwFP!00002|CP>53d0}}0MNaskgQFaO#DP>N^ereItD3GYC>plUwVX`;Jt&} zmTQqUl=``EvwUpO|dY z4ij6XDFqz`s6h?ln#;juuk9;SZ7c0_XFA#V$bbKlK2mk;800092l~T=a!Y~ZJ_bH+rxB*F;Hm#u5_5gbZJ^@GA0VimV*NiRoWM(9(4Gu z3FoBOsz#pY6%(Bjs_Z28iYqReE(BAosIjbSVX|$+lf9{Q!8w}}#)f{_ZUj7#_Z}Qs z9Ma~GgT;_Gl$a15q=puhSbsvFLcHvz5qLwDR9%6yhODG0HS}PFstrPEq!I>80hQ6R zr{p2OvwcHf3`$9|4yOd}*ibI=T(O^ot4guo(KUE%XkIc#+iW{SCm67e=)wsJ5MvLR zW%sbzcKrZk+ats|&(uE8vx{i{ZVrVR~UK4eE-^SM3PLe5 zHVO(KiwFP!00002|CPsu;SZI{_x&E}pt(p_<0hMY+DDQ|C!o4h;a`Pu+u zmI0HDfdpvOKBh-IO2Y*{;?9U9&M4EO5bhSom)qHd_tPTS3vKY#w&@(O-2&LY=X_xZA@sZj^#`#mM3 zAe3-ID5rEUZlk^CBhOL>*X~A8fkae*>}bbCOGU1UWGN9jfQ&KcDHk9*A=9Mvu$sq^ z)=iTM0epquOgktT(W_Py+Ku7#3t-oW6Gol$lL{3U7#X{Q4bI=r%b?N~x;qOM zW|9zGCuNi_s)t%>jg)m^0MwZglJdA!l5$o)F0$0myPQ3Af2L$SQhIXbJ-lCJ;V<%I z#poFAj!);=yBT~iu+&?8Lsm@@weiZf!`_4h} LrNE|J0ssI-U?^fV literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/packs/a06b9c10004fc3e05affee8cf0a9febd.pack b/test/repositories/bzr_with_nested_branches/.bzr/repository/packs/a06b9c10004fc3e05affee8cf0a9febd.pack new file mode 100644 index 0000000000000000000000000000000000000000..ab504c81bf17a0e562d2cd4de5d3c952e41103e3 GIT binary patch literal 752 zcmVK4eE-^SM3PLe5 zGztnIiwFP!00002|CPZJa&BnlFu0000&GBh^|3LlFI0000000RG&k;`s_Fc3xee1+vb ziQmRji25hd7~6y<*s5_T&DR$y^|fR(n$4MeW@h$z8d5~b#0BaYU1PBN$zTjQH0U| zL4IBKi=g6{a+$6`TkN$B!qP@a;(%*Gt#qUjS~(`$N>NVLNhWj3JM>K2mk;800092m60(|!!Qtq_xuXWL$|ihC3X@u ziC};YRtAKsOMFR98@o8BqW$$m&`5}_+nw&cyZ7l%xRLEK)&KnrrjYO*uBPqEe>JxFTkP?8_qiC2MiULoEdu}8=OCH#~sEM&k9vY0EwtD zj)f+YP1dwipiCz@=uYLC?2tH{&u@*c_>G*L1vAhXa5z>xh9t>ECID6d>UVT;mMWeo zA$T2?lXS$M>euIompArk{1~p#QFJAa%Jr;@%AK4eE-^SM3PLk8 zI0_0MiwFP!00002|CN%&pDeVssQQc58k zAuV({M`#F#W9qxQgkyOPqshB%Sh_y91Q0<1MF|R3J1}<2({6v-zp0$w`kL2FQyl?F zjFxjBEpSjl867kl3eF49QCK1?Sl|My=hO|MEB#@rV}Hn|yfnP24`E0bfOYaO&7%;_ zs^Sa2Ak}kB+fZN1HRsZZWf{wD00C(AR7T8W95=Mvh-ueiQ+FnZo0T7=|9L3GcEIF@ z3Akkxics5TKI2%{$Bn@`QE=uclinNUq!kdQ2CAvG5UB@37&?YpelMl-j6vt|Y4w+n z{O!XyX}c+Zu+ejXPqyzEz4wui_;5m6a~wp{XORhccj|n;^PwD(TS?8#F08lIY95%e zPB0fy3KnMLAl1DOz50aCKm1|U7cuHbgPQ^X075f4Hwp?LiwFP!00002|CN$WZsZ^k zh4(%MVv(J@`EwhTwv`La87wemH%S{DO#hyKn0Q*PnMI`RKvng=_eyn!xVYd^f+fAd zRZsH~Hhq{%Mkpnca9R^dWqB6jG~MRU)8{BBHwL5-w^ePp=&c+iNCgx`Zw5{+?<*xF z(cE$&cC6S(IJ+-O7M@&65F7jlh+dBA^?&lqm|ig&LY#DJaD|ccXYeV+TeloEZLm;W z4TP{^FjZv-Ln@N_T7jaPliu!ZMR$hP7(KY1vn%i?2{B4;$}@SO!IV?R6=h0pD$3T< zJ$PtvNrfN;x5Yj;FM5Rb7sL@PGEw{f(CO?y1(f2+e{A;KM^mw%b zV0^f~EqXF~6XKXH6Ga%wK%oRHYaacDxI1{k23iS>w%^Kqw}PFJWgyqycvl}Uv#Ry| zebw7Ooz5}L5R-$YeY|hT>nZPHjaz!xf8f^KV|Q`s(D_UR+pR@dvew_JFWskF{ym(w U1$g`8dn|qfJI*tU$pQcXMYtGivj6}9 literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/packs/f35e1020b6a55c81b6d2fe4c7bcd4645.pack b/test/repositories/bzr_with_nested_branches/.bzr/repository/packs/f35e1020b6a55c81b6d2fe4c7bcd4645.pack new file mode 100644 index 0000000000000000000000000000000000000000..fd1bb7af38a9b1e828a4b7223cdd098e4cd2f0da GIT binary patch literal 920 zcmV;J184j~VR~UK4eE-^SM3PLe5 zHVO(KiwFP!00002|CP$Vxhga!%Gkh9w>AY0j+Wl4AbYS2JZlf+ncj=s3Yx+Fu@XLiCqhvu!b zp%5yDbMLD{>km;f>c5xz0jT?hDWm`Z075f3I0_0MiwFP!00002|CQ6-PUA2T1>pNW zMU?x1$N!cn;!V)lo@qncL`~Ar@bsieyR^_wG!z{7YNFGrQ~6}~eL{bn25 z<3}tSx9m5frE8fvw~yvv5p-kwdT{lF{*+qyEKFzc|`g!>~WTqruei)W~^v z%~AJoZq?+Hv-C8O_ZgzM$uL3+QfC{{5Za}!RvG1z7B@MMe=GdFqBh_ATUMVk_HOTH z0{{R*Gc+{{3LlFI0000000RG&QcG@wFc95y3d@V^Nc;f|N5HPENL@9%8O@vb8O;sDWW6K4b^hmLg0Y3I52sWxRx!ac#zdCO^jk5I*c%C0onhvL zbApx9Eib_^5SW)H>kx~q)Sxm6QdC+LB?Db1hk!TxQ0e?Q+88m^^viZV;6Oe#jAS#! z{T~OLQ`}Qxd>A3tG^fP68@lMje4KjVHEna$veX%BV-~T38wFX{GT_4Ss#S*Tu25Y? z$tr)ex~6Xir6k%BrwHSvrd&v=m|~UOmhw5edxtfZ1!J^H4hwXG6E>hV0TO!~G%-7j95TfvUd_xX*)4Rt7xN|f3x;TMYSwxt u4#vfF8^Cpa>TGwWO?wZ^+7s}gcr7m7>ZwW4>36>+`32mfOj>3F002duoTyL$ literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_nested_branches/.bzr/repository/upload/.gitignore b/test/repositories/bzr_with_nested_branches/.bzr/repository/upload/.gitignore new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/.bzr/repository/upload/.gitignore @@ -0,0 +1 @@ + diff --git a/test/repositories/bzr_with_nested_branches/file1.txt b/test/repositories/bzr_with_nested_branches/file1.txt new file mode 100644 index 00000000..9d6265cc --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/file1.txt @@ -0,0 +1,2 @@ +first file +second line diff --git a/test/repositories/bzr_with_nested_branches/file3.txt b/test/repositories/bzr_with_nested_branches/file3.txt new file mode 100644 index 00000000..dc4b480e --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/file3.txt @@ -0,0 +1 @@ +a third file diff --git a/test/repositories/bzr_with_nested_branches/file4.txt b/test/repositories/bzr_with_nested_branches/file4.txt new file mode 100644 index 00000000..7c3f1a85 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/file4.txt @@ -0,0 +1 @@ +yet another file diff --git a/test/repositories/bzr_with_nested_branches/file5.txt b/test/repositories/bzr_with_nested_branches/file5.txt new file mode 100644 index 00000000..f71a6e04 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/file5.txt @@ -0,0 +1,4 @@ +and yet another file + + +... diff --git a/test/repositories/bzr_with_nested_branches/file6.txt b/test/repositories/bzr_with_nested_branches/file6.txt new file mode 100644 index 00000000..33a752d5 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/file6.txt @@ -0,0 +1,2 @@ +File added on branch a +and modified. diff --git a/test/repositories/bzr_with_nested_branches/file7.txt b/test/repositories/bzr_with_nested_branches/file7.txt new file mode 100644 index 00000000..40db9f70 --- /dev/null +++ b/test/repositories/bzr_with_nested_branches/file7.txt @@ -0,0 +1,2 @@ +Added on branch b. +and modified. diff --git a/test/unit/bzr_commits_test.rb b/test/unit/bzr_commits_test.rb index 4068cd33..9626a999 100644 --- a/test/unit/bzr_commits_test.rb +++ b/test/unit/bzr_commits_test.rb @@ -60,6 +60,39 @@ def test_commit_tokens_trunk_only_true end end + def test_nested_branches_commit_tokens_trunk_only_false + with_bzr_repository('bzr_with_nested_branches') do |bzr| + assert_equal [ + 'obnox@samba.org-20090204002342-5r0q4gejk69rk6uv', + 'obnox@samba.org-20090204002422-5ylnq8l4713eqfy0', + 'obnox@samba.org-20090204002453-u70a3ehf3ae9kay1', + 'obnox@samba.org-20090204002518-yb0x153oa6mhoodu', + 'obnox@samba.org-20090204002540-gmana8tk5f9gboq9', + 'obnox@samba.org-20090204004942-73rnw0izen42f154', + 'test@example.com-20110803170302-fz4mbr89n8f5agha', + 'test@example.com-20110803170341-v1icvy05b430t68l', + 'test@example.com-20110803170504-z7xz5uxj02e5x3z6', + 'test@example.com-20110803170522-asv6i9z6m22jc8zz', + 'test@example.com-20110803170648-o0xcbni7lwp97azj', + 'test@example.com-20110803170818-v44umypquqg8migo' + ], bzr.commit_tokens(:trunk_only => false) + end + end + + def test_nested_branches_commit_tokens_trunk_only_true + with_bzr_repository('bzr_with_nested_branches') do |bzr| + assert_equal [ + 'obnox@samba.org-20090204002342-5r0q4gejk69rk6uv', + 'obnox@samba.org-20090204002422-5ylnq8l4713eqfy0', + 'obnox@samba.org-20090204002453-u70a3ehf3ae9kay1', + 'obnox@samba.org-20090204002518-yb0x153oa6mhoodu', + 'obnox@samba.org-20090204002540-gmana8tk5f9gboq9', + 'obnox@samba.org-20090204004942-73rnw0izen42f154', + 'test@example.com-20110803170818-v44umypquqg8migo' + ], bzr.commit_tokens(:trunk_only => true) + end + end + def test_commits_trunk_only_false with_bzr_repository('bzr_with_branch') do |bzr| assert_equal [ @@ -81,6 +114,39 @@ def test_commits_trunk_only_true end end + def test_nested_branches_commits_trunk_only_false + with_bzr_repository('bzr_with_nested_branches') do |bzr| + assert_equal [ + 'obnox@samba.org-20090204002342-5r0q4gejk69rk6uv', + 'obnox@samba.org-20090204002422-5ylnq8l4713eqfy0', + 'obnox@samba.org-20090204002453-u70a3ehf3ae9kay1', + 'obnox@samba.org-20090204002518-yb0x153oa6mhoodu', + 'obnox@samba.org-20090204002540-gmana8tk5f9gboq9', + 'obnox@samba.org-20090204004942-73rnw0izen42f154', + 'test@example.com-20110803170302-fz4mbr89n8f5agha', + 'test@example.com-20110803170341-v1icvy05b430t68l', + 'test@example.com-20110803170504-z7xz5uxj02e5x3z6', + 'test@example.com-20110803170522-asv6i9z6m22jc8zz', + 'test@example.com-20110803170648-o0xcbni7lwp97azj', + 'test@example.com-20110803170818-v44umypquqg8migo' + ], bzr.commits(:trunk_only => false).map { |c| c.token } + end + end + + def test_nested_branches_commits_trunk_only_true + with_bzr_repository('bzr_with_nested_branches') do |bzr| + assert_equal [ + 'obnox@samba.org-20090204002342-5r0q4gejk69rk6uv', + 'obnox@samba.org-20090204002422-5ylnq8l4713eqfy0', + 'obnox@samba.org-20090204002453-u70a3ehf3ae9kay1', + 'obnox@samba.org-20090204002518-yb0x153oa6mhoodu', + 'obnox@samba.org-20090204002540-gmana8tk5f9gboq9', + 'obnox@samba.org-20090204004942-73rnw0izen42f154', + 'test@example.com-20110803170818-v44umypquqg8migo' + ], bzr.commits(:trunk_only => true).map { |c| c.token } + end + end + def test_commits with_bzr_repository('bzr') do |bzr| assert_equal revision_ids, bzr.commits.collect { |c| c.token } @@ -142,6 +208,43 @@ def test_each_commit_trunk_only_true end end + def test_nested_branches_each_commit_trunk_only_false + with_bzr_repository('bzr_with_nested_branches') do |bzr| + commits = [] + bzr.each_commit(:trunk_only => false) { |c| commits << c} + assert_equal [ + 'obnox@samba.org-20090204002342-5r0q4gejk69rk6uv', + 'obnox@samba.org-20090204002422-5ylnq8l4713eqfy0', + 'obnox@samba.org-20090204002453-u70a3ehf3ae9kay1', + 'obnox@samba.org-20090204002518-yb0x153oa6mhoodu', + 'obnox@samba.org-20090204002540-gmana8tk5f9gboq9', + 'obnox@samba.org-20090204004942-73rnw0izen42f154', + 'test@example.com-20110803170302-fz4mbr89n8f5agha', + 'test@example.com-20110803170341-v1icvy05b430t68l', + 'test@example.com-20110803170504-z7xz5uxj02e5x3z6', + 'test@example.com-20110803170522-asv6i9z6m22jc8zz', + 'test@example.com-20110803170648-o0xcbni7lwp97azj', + 'test@example.com-20110803170818-v44umypquqg8migo' + ], commits.map { |c| c.token } + end + end + + def test_nested_branches_each_commit_trunk_only_true + with_bzr_repository('bzr_with_nested_branches') do |bzr| + commits = [] + bzr.each_commit(:trunk_only => true) { |c| commits << c } + assert_equal [ + 'obnox@samba.org-20090204002342-5r0q4gejk69rk6uv', + 'obnox@samba.org-20090204002422-5ylnq8l4713eqfy0', + 'obnox@samba.org-20090204002453-u70a3ehf3ae9kay1', + 'obnox@samba.org-20090204002518-yb0x153oa6mhoodu', + 'obnox@samba.org-20090204002540-gmana8tk5f9gboq9', + 'obnox@samba.org-20090204004942-73rnw0izen42f154', + 'test@example.com-20110803170818-v44umypquqg8migo' + ], commits.map { |c| c.token } + end + end + # This bzr repository contains the following tree structure # /foo/ # /foo/helloworld.c From 0efa4865b0bfce49e2c2a59c16bc4a69f3e29844 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Wed, 3 Aug 2011 14:17:15 -0400 Subject: [PATCH 089/219] Removes debugging code. --- test/unit/bzr_commits_test.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/unit/bzr_commits_test.rb b/test/unit/bzr_commits_test.rb index 9626a999..e34fd125 100644 --- a/test/unit/bzr_commits_test.rb +++ b/test/unit/bzr_commits_test.rb @@ -1,6 +1,4 @@ require File.dirname(__FILE__) + '/../test_helper' -require 'rubygems' -require 'ruby-debug' module Scm::Adapters class BzrCommitsTest < Scm::Test From 79dc9036e0fb97c13c6e2ef05d16e3621c8ce82b Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Wed, 3 Aug 2011 17:56:36 -0400 Subject: [PATCH 090/219] Fixes empty log file to be empty xml file. --- lib/scm/adapters/bzr/commits.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scm/adapters/bzr/commits.rb b/lib/scm/adapters/bzr/commits.rb index 174f2b6c..72cffc0e 100644 --- a/lib/scm/adapters/bzr/commits.rb +++ b/lib/scm/adapters/bzr/commits.rb @@ -81,7 +81,7 @@ def open_log_file(opts={}) if after == head_token # There are no new commits # As a time optimization, just create an empty # file rather than fetch a log we know will be empty. - File.open(log_filename, 'w') { } + File.open(log_filename, 'w') { |f| f.puts '' } else run "#{rev_list_command(opts)} -v > #{log_filename}" end From d92cf65f9390f4195b86dd3aef00702bd361912f Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Thu, 1 Sep 2011 11:56:35 -0400 Subject: [PATCH 091/219] Replaces systemu with a newer version of open4; uses threads to start reading stdout/err immediately. --- lib/scm.rb | 2 +- lib/scm/adapters/abstract/system.rb | 6 ++--- lib/scm/shellout.rb | 42 +++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 lib/scm/shellout.rb diff --git a/lib/scm.rb b/lib/scm.rb index fb8e25a0..ab046b1e 100644 --- a/lib/scm.rb +++ b/lib/scm.rb @@ -5,7 +5,7 @@ module Scm $: << File.join(File.dirname(__FILE__),"..") -require 'lib/scm/systemu' +require 'lib/scm/shellout' require 'lib/scm/scratch_dir' require 'lib/scm/commit' require 'lib/scm/diff' diff --git a/lib/scm/adapters/abstract/system.rb b/lib/scm/adapters/abstract/system.rb index 6dd6bcaa..4ade1b52 100644 --- a/lib/scm/adapters/abstract/system.rb +++ b/lib/scm/adapters/abstract/system.rb @@ -17,8 +17,8 @@ def logger # Raises an exception if the shell returns non-zero exit code. def self.run(cmd) logger.debug { cmd } - status, out, err = systemu(cmd) - raise RuntimeError.new("#{cmd} failed: #{out}\n#{err}") if status.exitstatus != 0 + exitstatus, out, err = Shellout.run(cmd) + raise RuntimeError.new("#{cmd} failed: #{out}\n#{err}") if exitstatus != 0 out end @@ -30,7 +30,7 @@ def run(cmd) # Returns three values: stdout, stderr, and process exit code def self.run_with_err(cmd) logger.debug { cmd } - status, out, err = systemu(cmd) + status, out, err = Shellout.run(cmd) [out, err, status] end diff --git a/lib/scm/shellout.rb b/lib/scm/shellout.rb new file mode 100644 index 00000000..52376ad8 --- /dev/null +++ b/lib/scm/shellout.rb @@ -0,0 +1,42 @@ +require 'rubygems' +require 'stringio' +require 'open4' + +class Shellout + + def self.relay src, dst + while((buf = src.read(8192))); dst << buf; end + end + + def self.run(cmd) + outbuf = StringIO.new + errbuf = StringIO.new + status = Open4::popen4("sh") do | pid, stdin, stdout, stderr | + stdin.puts cmd + stdin.close + to = Thread.new { relay stdout, outbuf } + te = Thread.new { relay stderr, errbuf } + to.join + te.join + end + return status.exitstatus, outbuf.string, errbuf.string + end + +end + +if $0 == __FILE__ + date = %q( ruby -e" t = Time.now; STDOUT.puts t; STDERR.puts t " ) + status, stdout, stderr = Shellout.run(date) + p [status, stdout, stderr] + + sleep = %q( ruby -e" p(sleep(1)) " ) + status, stdout, stderr = Shellout.run(sleep) + p [status, stdout, stderr] + + cat = 'ruby -e" puts Array.new(65536){ 42 } "' + status, stdout, stderr = Shellout.run(cat) + p [status, stdout, stderr] + +end + + From afe9140788633c85466cee10fab32058f0ab900f Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Thu, 1 Sep 2011 18:35:06 -0400 Subject: [PATCH 092/219] Changes Shellout.run to return status object. --- lib/scm/shellout.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/scm/shellout.rb b/lib/scm/shellout.rb index 52376ad8..09392b0e 100644 --- a/lib/scm/shellout.rb +++ b/lib/scm/shellout.rb @@ -19,7 +19,7 @@ def self.run(cmd) to.join te.join end - return status.exitstatus, outbuf.string, errbuf.string + return status, outbuf.string, errbuf.string end end @@ -27,15 +27,15 @@ def self.run(cmd) if $0 == __FILE__ date = %q( ruby -e" t = Time.now; STDOUT.puts t; STDERR.puts t " ) status, stdout, stderr = Shellout.run(date) - p [status, stdout, stderr] + p [status.exitstatus, stdout, stderr] sleep = %q( ruby -e" p(sleep(1)) " ) status, stdout, stderr = Shellout.run(sleep) - p [status, stdout, stderr] + p [status.exitstatus, stdout, stderr] cat = 'ruby -e" puts Array.new(65536){ 42 } "' status, stdout, stderr = Shellout.run(cat) - p [status, stdout, stderr] + p [status.exitstatus, stdout, stderr] end From a082363531d597d638fe7de4c61353234958f38a Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Thu, 1 Sep 2011 19:19:21 -0400 Subject: [PATCH 093/219] Fixes return code from child process, adds tests. --- lib/scm/adapters/abstract/system.rb | 4 ++-- lib/scm/shellout.rb | 3 +++ test/unit/abstract_adapter_test.rb | 29 +++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/lib/scm/adapters/abstract/system.rb b/lib/scm/adapters/abstract/system.rb index 4ade1b52..09e15d76 100644 --- a/lib/scm/adapters/abstract/system.rb +++ b/lib/scm/adapters/abstract/system.rb @@ -17,8 +17,8 @@ def logger # Raises an exception if the shell returns non-zero exit code. def self.run(cmd) logger.debug { cmd } - exitstatus, out, err = Shellout.run(cmd) - raise RuntimeError.new("#{cmd} failed: #{out}\n#{err}") if exitstatus != 0 + status, out, err = Shellout.run(cmd) + raise RuntimeError.new("#{cmd} failed: #{out}\n#{err}") if status.exitstatus != 0 out end diff --git a/lib/scm/shellout.rb b/lib/scm/shellout.rb index 09392b0e..c0585728 100644 --- a/lib/scm/shellout.rb +++ b/lib/scm/shellout.rb @@ -37,6 +37,9 @@ def self.run(cmd) status, stdout, stderr = Shellout.run(cat) p [status.exitstatus, stdout, stderr] + status, stdout, stderr = Shellout.run('osiudfoisynajtet32') + p [status.exitstatus, stdout, stderr] + end diff --git a/test/unit/abstract_adapter_test.rb b/test/unit/abstract_adapter_test.rb index a8440fa4..154cf71e 100644 --- a/test/unit/abstract_adapter_test.rb +++ b/test/unit/abstract_adapter_test.rb @@ -68,5 +68,34 @@ def test_normalize assert_equal "joe", scm.username assert_equal "abc", scm.password end + + def test_shellout + cmd = %q( ruby -e" t = 'Hello World'; STDOUT.puts t; STDERR.puts t " ) + stdout = AbstractAdapter.run(cmd) + assert_equal "Hello World\n", stdout + end + + def test_shellout_with_stderr + cmd = %q( ruby -e" t = 'Hello World'; STDOUT.puts t; STDERR.puts t " ) + stdout, stderr, status = AbstractAdapter.run_with_err(cmd) + assert_equal 0, status.exitstatus + assert_equal "Hello World\n", stdout + assert_equal "Hello World\n", stderr + end + + def test_shellout_large_output + cat = 'ruby -e" puts Array.new(65536){ 42 } "' + stdout = AbstractAdapter.run(cat) + assert_equal Array.new(65536){ 42 }.join("\n").concat("\n"), stdout + end + + def test_shellout_error + cmd = "xxxxiiddosufso" + assert_raise RuntimeError do + #RuntimeError.new("#{cmd} failed` + stdout = AbstractAdapter.run(cmd) + end + end + end end From 51693800485037c481730d793fd9609b32632a6d Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Mon, 5 Sep 2011 13:01:44 -0400 Subject: [PATCH 094/219] Makes Shellout.run an instance method. --- lib/scm/adapters/abstract/system.rb | 4 ++-- lib/scm/shellout.rb | 15 ++++++++++----- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/scm/adapters/abstract/system.rb b/lib/scm/adapters/abstract/system.rb index 09e15d76..766e993a 100644 --- a/lib/scm/adapters/abstract/system.rb +++ b/lib/scm/adapters/abstract/system.rb @@ -17,7 +17,7 @@ def logger # Raises an exception if the shell returns non-zero exit code. def self.run(cmd) logger.debug { cmd } - status, out, err = Shellout.run(cmd) + status, out, err = Shellout.new.run(cmd) raise RuntimeError.new("#{cmd} failed: #{out}\n#{err}") if status.exitstatus != 0 out end @@ -30,7 +30,7 @@ def run(cmd) # Returns three values: stdout, stderr, and process exit code def self.run_with_err(cmd) logger.debug { cmd } - status, out, err = Shellout.run(cmd) + status, out, err = Shellout.new.run(cmd) [out, err, status] end diff --git a/lib/scm/shellout.rb b/lib/scm/shellout.rb index c0585728..a7177413 100644 --- a/lib/scm/shellout.rb +++ b/lib/scm/shellout.rb @@ -8,7 +8,7 @@ def self.relay src, dst while((buf = src.read(8192))); dst << buf; end end - def self.run(cmd) + def self.execute(cmd) outbuf = StringIO.new errbuf = StringIO.new status = Open4::popen4("sh") do | pid, stdin, stdout, stderr | @@ -22,22 +22,27 @@ def self.run(cmd) return status, outbuf.string, errbuf.string end + def run(cmd) + Shellout::execute(cmd) + end + end if $0 == __FILE__ + shell = Shellout.new date = %q( ruby -e" t = Time.now; STDOUT.puts t; STDERR.puts t " ) - status, stdout, stderr = Shellout.run(date) + status, stdout, stderr = shell.run(date) p [status.exitstatus, stdout, stderr] sleep = %q( ruby -e" p(sleep(1)) " ) - status, stdout, stderr = Shellout.run(sleep) + status, stdout, stderr = shell.run(sleep) p [status.exitstatus, stdout, stderr] cat = 'ruby -e" puts Array.new(65536){ 42 } "' - status, stdout, stderr = Shellout.run(cat) + status, stdout, stderr = shell.run(cat) p [status.exitstatus, stdout, stderr] - status, stdout, stderr = Shellout.run('osiudfoisynajtet32') + status, stdout, stderr = shell.run('osiudfoisynajtet32') p [status.exitstatus, stdout, stderr] end From b56f213c12448d65976c963035656c2f362b50c6 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Mon, 5 Sep 2011 13:02:26 -0400 Subject: [PATCH 095/219] Removes systemu library. --- lib/scm/systemu.rb | 299 --------------------------------------------- 1 file changed, 299 deletions(-) delete mode 100644 lib/scm/systemu.rb diff --git a/lib/scm/systemu.rb b/lib/scm/systemu.rb deleted file mode 100644 index 27c0323f..00000000 --- a/lib/scm/systemu.rb +++ /dev/null @@ -1,299 +0,0 @@ -# vim: ts=2:sw=2:sts=2:et:fdm=marker -require 'tmpdir' -require 'socket' -require 'fileutils' -require 'rbconfig' -require 'thread' -require 'yaml' - -class Object - def systemu(*a, &b) SystemUniversal.new(*a, &b).systemu end -end - -class SystemUniversal -# -# constants -# - SystemUniversal::VERSION = '1.2.0' unless defined? SystemUniversal::VERSION - def version() SystemUniversal::VERSION end -# -# class methods -# - - @host = Socket.gethostname - @ppid = Process.ppid - @pid = Process.pid - @turd = ENV['SYSTEMU_TURD'] - - c = ::Config::CONFIG - ruby = File.join(c['bindir'], c['ruby_install_name']) << c['EXEEXT'] - @ruby = if system('%s -e 42' % ruby) - ruby - else - system('%s -e 42' % 'ruby') ? 'ruby' : warn('no ruby in PATH/CONFIG') - end - - class << self - %w( host ppid pid ruby turd ).each{|a| attr_accessor a} - end - -# -# instance methods -# - - def initialize argv, opts = {}, &block - getopt = getopts opts - - @argv = argv - @block = block - - @stdin = getopt[ ['stdin', 'in', '0', 0] ] - @stdout = getopt[ ['stdout', 'out', '1', 1] ] - @stderr = getopt[ ['stderr', 'err', '2', 2] ] - @env = getopt[ 'env' ] - @cwd = getopt[ 'cwd' ] - - @host = getopt[ 'host', self.class.host ] - @ppid = getopt[ 'ppid', self.class.ppid ] - @pid = getopt[ 'pid', self.class.pid ] - @ruby = getopt[ 'ruby', self.class.ruby ] - end - - def systemu - tmpdir do |tmp| - c = child_setup tmp - status = nil - - begin - thread = nil - - quietly{ - IO.popen "#{ @ruby } #{ c['program'] }", 'r+' do |pipe| - line = pipe.gets - case line - when %r/^pid: \d+$/ - cid = Integer line[%r/\d+/] - else - begin - buf = pipe.read - buf = "#{ line }#{ buf }" - e = Marshal.load buf - raise unless Exception === e - raise e - rescue - raise "wtf?\n#{ buf }\n" - end - end - thread = new_thread cid, @block if @block - pipe.read rescue nil - end - } - status = $? - ensure - if thread - begin - class << status - attr 'thread' - end - status.instance_eval{ @thread = thread } - rescue - 42 - end - end - end - - if @stdout or @stderr - open(c['stdout']){|f| relay f => @stdout} if @stdout - open(c['stderr']){|f| relay f => @stderr} if @stderr - status - else - [status, IO.read(c['stdout']), IO.read(c['stderr'])] - end - end - end - - def new_thread cid, block - q = Queue.new - Thread.new(cid) do |cid| - current = Thread.current - current.abort_on_exception = true - q.push current - block.call cid - end - q.pop - end - - def child_setup tmp - stdin = File.expand_path(File.join(tmp, 'stdin')) - stdout = File.expand_path(File.join(tmp, 'stdout')) - stderr = File.expand_path(File.join(tmp, 'stderr')) - program = File.expand_path(File.join(tmp, 'program')) - config = File.expand_path(File.join(tmp, 'config')) - - if @stdin - open(stdin, 'w'){|f| relay @stdin => f} - else - FileUtils.touch stdin - end - FileUtils.touch stdout - FileUtils.touch stderr - - c = {} - c['argv'] = @argv - c['env'] = @env - c['cwd'] = @cwd - c['stdin'] = stdin - c['stdout'] = stdout - c['stderr'] = stderr - c['program'] = program - open(config, 'w'){|f| YAML.dump c, f} - - open(program, 'w'){|f| f.write child_program(config)} - - c - end - - def quietly - v = $VERBOSE - $VERBOSE = nil - yield - ensure - $VERBOSE = v - end - - def child_program config - <<-program - PIPE = STDOUT.dup - begin - require 'yaml' - - config = YAML.load(IO.read('#{ config }')) - - argv = config['argv'] - env = config['env'] - cwd = config['cwd'] - stdin = config['stdin'] - stdout = config['stdout'] - stderr = config['stderr'] - - Dir.chdir cwd if cwd - env.each{|k,v| ENV[k.to_s] = v.to_s} if env - - STDIN.reopen stdin - STDOUT.reopen stdout - STDERR.reopen stderr - - PIPE.puts "pid: \#{ Process.pid }" - PIPE.flush ### the process is ready yo! - PIPE.close - - exec *argv - rescue Exception => e - PIPE.write Marshal.dump(e) rescue nil - exit 42 - end - program - end - - def relay srcdst - src, dst, ignored = srcdst.to_a.first - if src.respond_to? 'read' - while((buf = src.read(8192))); dst << buf; end - else - src.each{|buf| dst << buf} - end - end - - def tmpdir d = Dir.tmpdir, max = 42, &b - i = -1 and loop{ - i += 1 - - tmp = File.join d, "systemu_#{ @host }_#{ @ppid }_#{ @pid }_#{ rand }_#{ i += 1 }" - - begin - Dir.mkdir tmp - rescue Errno::EEXIST - raise if i >= max - next - end - - break( - if b - begin - b.call tmp - ensure - FileUtils.rm_rf tmp unless SystemU.turd - end - else - tmp - end - ) - } - end - - def getopts opts = {} - lambda do |*args| - keys, default, ignored = args - catch('opt') do - [keys].flatten.each do |key| - [key, key.to_s, key.to_s.intern].each do |key| - throw 'opt', opts[key] if opts.has_key?(key) - end - end - default - end - end - end -end - -SystemU = SystemUniversal unless defined? SystemU - - - - - - - - - - - - - -if $0 == __FILE__ -# -# date -# - date = %q( ruby -e" t = Time.now; STDOUT.puts t; STDERR.puts t " ) - - status, stdout, stderr = systemu date - p [status, stdout, stderr] - - status = systemu date, 1=>(stdout = '') - p [status, stdout] - - status = systemu date, 2=>(stderr = '') - p [status, stderr] -# -# sleep -# - sleep = %q( ruby -e" p(sleep(1)) " ) - status, stdout, stderr = systemu sleep - p [status, stdout, stderr] - - sleep = %q( ruby -e" p(sleep(42)) " ) - status, stdout, stderr = systemu(sleep){|cid| Process.kill 9, cid} - p [status, stdout, stderr] -# -# env -# - env = %q( ruby -e" p ENV['A'] " ) - status, stdout, stderr = systemu env, :env => {'A' => 42} - p [status, stdout, stderr] -# -# cwd -# - env = %q( ruby -e" p Dir.pwd " ) - status, stdout, stderr = systemu env, :cwd => Dir.tmpdir - p [status, stdout, stderr] -end From f525ea50b6f78244914cc5b7af9825573d8962f5 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Wed, 7 Sep 2011 04:31:26 -0400 Subject: [PATCH 096/219] Addresses code review comments. --- test/unit/abstract_adapter_test.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/unit/abstract_adapter_test.rb b/test/unit/abstract_adapter_test.rb index 154cf71e..57023f54 100644 --- a/test/unit/abstract_adapter_test.rb +++ b/test/unit/abstract_adapter_test.rb @@ -90,9 +90,8 @@ def test_shellout_large_output end def test_shellout_error - cmd = "xxxxiiddosufso" + cmd = "false" assert_raise RuntimeError do - #RuntimeError.new("#{cmd} failed` stdout = AbstractAdapter.run(cmd) end end From 378e4adb272afca72229bd721ad87d487e63d273 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Wed, 7 Sep 2011 23:50:41 -0400 Subject: [PATCH 097/219] OTWO-969 - Implements bzrlib based bzr adapter. This adapter uses bzrlib via rubypython gem. Shelling out bzr commands has a lot of overhead including Python interpreter startup for each command. Getting data via bzrlib APIs is much faster. --- .gitignore | 1 + lib/scm.rb | 1 + lib/scm/adapters/bzr/misc.rb | 9 ++++- lib/scm/adapters/bzrlib/bzrlib_commands.py | 36 ++++++++++++++++++ lib/scm/adapters/bzrlib/cat_file.rb | 35 ++++++++++++++++++ lib/scm/adapters/bzrlib/head.rb | 34 +++++++++++++++++ lib/scm/adapters/bzrlib_adapter.rb | 23 ++++++++++++ test/test_helper.rb | 4 ++ test/unit/bzrlib_cat_file_test.rb | 43 ++++++++++++++++++++++ test/unit/bzrlib_head_test.rb | 18 +++++++++ 10 files changed, 202 insertions(+), 2 deletions(-) create mode 100644 lib/scm/adapters/bzrlib/bzrlib_commands.py create mode 100644 lib/scm/adapters/bzrlib/cat_file.rb create mode 100644 lib/scm/adapters/bzrlib/head.rb create mode 100644 lib/scm/adapters/bzrlib_adapter.rb create mode 100644 test/unit/bzrlib_cat_file_test.rb create mode 100644 test/unit/bzrlib_head_test.rb diff --git a/.gitignore b/.gitignore index 444fe1a3..3bc5d675 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.swp +*.pyc pkg/ diff --git a/lib/scm.rb b/lib/scm.rb index ab046b1e..a0f5f1b3 100644 --- a/lib/scm.rb +++ b/lib/scm.rb @@ -17,6 +17,7 @@ module Scm require 'lib/scm/adapters/git_adapter' require 'lib/scm/adapters/hg_adapter' require 'lib/scm/adapters/bzr_adapter' +require 'lib/scm/adapters/bzrlib_adapter' require 'lib/scm/adapters/factory' require 'lib/scm/parsers/parser' diff --git a/lib/scm/adapters/bzr/misc.rb b/lib/scm/adapters/bzr/misc.rb index 38312098..dc996016 100644 --- a/lib/scm/adapters/bzr/misc.rb +++ b/lib/scm/adapters/bzr/misc.rb @@ -15,7 +15,8 @@ def ls_tree(token) # If you want to pass a revision-id as a bzr parameter, you # must prefix it with "revid:". This takes care of that. - def to_rev_param(r=nil) + # When passed to bzrlib calls, we don't need to enquote it. + def to_rev_param(r=nil, enquote=true) case r when nil 1 @@ -24,7 +25,11 @@ def to_rev_param(r=nil) when /^\d+$/ r else - "'revid:#{r.to_s}'" + if enquote + "'revid:#{r.to_s}'" + else + "revid:#{r.to_s}" + end end end diff --git a/lib/scm/adapters/bzrlib/bzrlib_commands.py b/lib/scm/adapters/bzrlib/bzrlib_commands.py new file mode 100644 index 00000000..3ccf0f82 --- /dev/null +++ b/lib/scm/adapters/bzrlib/bzrlib_commands.py @@ -0,0 +1,36 @@ +from bzrlib.builtins import cmd_cat +from bzrlib.builtins import cmd_log +from bzrlib.revisionspec import RevisionSpec +import StringIO +import os + +# Get contents of a file for specific revision. +def bzr_cat(repository_url, filename, revision): + os.chdir(repository_url) + spec = RevisionSpec.from_string(revision) + output = StringIO.StringIO() + cmd = cmd_cat() + cmd.outf = output + cmd.run_direct(filename=filename, revision=[spec], name_from_revision=True) + return output.getvalue() + +# Get log for a specific revision. +def bzr_log(repository_url, change): + os.chdir(repository_url) + change_rev = RevisionSpec.from_string(change) + output = StringIO.StringIO() + cmd = cmd_log() + cmd.outf = output + cmd.run_direct(file_list=None, show_ids=True, change=[change_rev], limit=1) + val = output.getvalue() + if isinstance(val, unicode): + return val.encode('utf-8') + else: + return val + +if __name__ == "__main__": + #print bzr_cat('/home/amujumdar/bzrlib_examples/bzr.2.1', 'bzrlib/transport/local.py', 'revid:pqm@pqm.ubuntu.com-20090624225712-x20543g8bpv6e9ny') + #print bzr_log('/home/amujumdar/bzrlib_examples/bzr.2.1', 'bzrlib/transport/local.py', show_ids=True, change='revid:pqm@pqm.ubuntu.com-20090624225712-x20543g8bpv6e9ny', limit=1) + #print bzr_log('/home/amujumdar/app/ohloh_scm/test/repositories/bzr', change='revid:obnox@samba.org-20090204004942-73rnw0izen42f154') + print bzr_log('/home/amujumdar/app/ohloh_scm/test/repositories/bzr', change='1') + diff --git a/lib/scm/adapters/bzrlib/cat_file.rb b/lib/scm/adapters/bzrlib/cat_file.rb new file mode 100644 index 00000000..740e0a3b --- /dev/null +++ b/lib/scm/adapters/bzrlib/cat_file.rb @@ -0,0 +1,35 @@ +module Scm::Adapters + class BzrlibAdapter < BzrAdapter + def cat_file(commit, diff) + cat(commit.token, diff.path) + end + + def cat_file_parent(commit, diff) + first_parent_token = parent_tokens(commit).first + cat(first_parent_token, diff.path) if first_parent_token + end + + def cat(revision, path) + pwd = Dir.pwd + begin + out = bzrlib_commands.bzr_cat(self.url, path, to_rev_param(revision, false)).to_s + rescue => expt + # return nil if err =~ / is not present in revision / + if expt.message =~ / is not present in revision / + out = nil + else + raise RuntimeError.new(expt.message) + end + ensure + Dir.chdir(pwd) + end + out + end + + # Bzr doesn't like it when the filename includes a colon + # Also, fix the case where the filename includes a single quote + def escape(path) + path.gsub(/[:]/) { |c| '\\' + c }.gsub("'", "''") + end + end +end diff --git a/lib/scm/adapters/bzrlib/head.rb b/lib/scm/adapters/bzrlib/head.rb new file mode 100644 index 00000000..7b7e36ee --- /dev/null +++ b/lib/scm/adapters/bzrlib/head.rb @@ -0,0 +1,34 @@ +module Scm::Adapters + class BzrlibAdapter < BzrAdapter + def head_token + run("bzr log --limit 1 --show-id #{url} 2> /dev/null | grep ^revision-id | cut -f2 -d' '").strip + #bzr_log(nil).scan(/^revision-id:\s(.*)$/)[0][0].strip + end + + def head + verbose_commit(head_token) + end + + def parent_tokens(commit) + #run("cd '#{url}' && bzr log --long --show-id --limit 1 -c #{to_rev_param(commit.token)} | grep ^parent | cut -f2 -d' '").split("\n") + s = bzr_log(to_rev_param(commit.token, false)) + bzr_log(to_rev_param(commit.token, false)).scan(/^parent:\s(.*)$/)[0] + end + + def parents(commit) + parent_tokens(commit).collect { |token| verbose_commit(token) } + end + + def bzr_log(revision) + pwd = Dir.pwd + begin + out = bzrlib_commands.bzr_log(self.url, revision) + rescue => expt + raise RuntimeError.new(expt.message) + ensure + Dir.chdir(pwd) + end + out.to_s + end + end +end diff --git a/lib/scm/adapters/bzrlib_adapter.rb b/lib/scm/adapters/bzrlib_adapter.rb new file mode 100644 index 00000000..7e06501d --- /dev/null +++ b/lib/scm/adapters/bzrlib_adapter.rb @@ -0,0 +1,23 @@ +require 'rubygems' +require 'rubypython' + +module Scm::Adapters + class BzrlibAdapter < BzrAdapter + def english_name + "Bazaar" + end + def bzrlib_commands + @bzrlib_commands ||= begin + ENV['PYTHONPATH'] = File.dirname(__FILE__) + '/bzrlib' + RubyPython.start + RubyPython.import('bzrlib_commands') + end + end + def cleaup + RubyPython.stop + end + end +end + +require 'lib/scm/adapters/bzrlib/head' +require 'lib/scm/adapters/bzrlib/cat_file' diff --git a/test/test_helper.rb b/test/test_helper.rb index 01a05ecc..484de92b 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -96,4 +96,8 @@ def with_hg_repository(name) def with_bzr_repository(name) with_repository(Scm::Adapters::BzrAdapter, name) { |bzr| yield bzr } end + + def with_bzrlib_repository(name) + with_repository(Scm::Adapters::BzrlibAdapter, name) { |bzr| yield bzr } + end end diff --git a/test/unit/bzrlib_cat_file_test.rb b/test/unit/bzrlib_cat_file_test.rb new file mode 100644 index 00000000..518087e8 --- /dev/null +++ b/test/unit/bzrlib_cat_file_test.rb @@ -0,0 +1,43 @@ +require File.dirname(__FILE__) + '/../test_helper' + +module Scm::Adapters + class BzrCatFileTest < Scm::Test + + def test_cat_file + with_bzrlib_repository('bzr') do |bzr| + expected = <<-EXPECTED +first file +second line +EXPECTED + assert_equal expected, + bzr.cat_file(Scm::Commit::new(:token => 6), + Scm::Diff.new(:path => "file1.txt")) + + # file2.txt has been removed in commit #5 + assert_equal nil, bzr.cat_file(bzr.head, + Scm::Diff.new(:path => "file2.txt")) + end + end + + def test_cat_file_parent + with_bzrlib_repository('bzr') do |bzr| + expected = <<-EXPECTED +first file +second line +EXPECTED + assert_equal expected, + bzr.cat_file_parent(Scm::Commit::new(:token => 6), + Scm::Diff.new(:path => "file1.txt")) + + # file2.txt has been removed in commit #5 + expected = <<-EXPECTED +another file +EXPECTED + assert_equal expected, + bzr.cat_file_parent(Scm::Commit.new(:token => 5), + Scm::Diff.new(:path => "file2.txt")) + end + end + + end +end diff --git a/test/unit/bzrlib_head_test.rb b/test/unit/bzrlib_head_test.rb new file mode 100644 index 00000000..d1ae1d3e --- /dev/null +++ b/test/unit/bzrlib_head_test.rb @@ -0,0 +1,18 @@ +require File.dirname(__FILE__) + '/../test_helper' + +module Scm::Adapters + class BzrBzrlibHeadTest < Scm::Test + + def test_head_and_parents + with_bzrlib_repository('bzr') do |bzr| + assert_equal 'obnox@samba.org-20090204004942-73rnw0izen42f154', bzr.head_token + assert_equal 'obnox@samba.org-20090204004942-73rnw0izen42f154', bzr.head.token + assert bzr.head.diffs.any? # diffs should be populated + + assert_equal 'obnox@samba.org-20090204002540-gmana8tk5f9gboq9', bzr.parents(bzr.head).first.token + assert bzr.parents(bzr.head).first.diffs.any? + end + end + + end +end From 8b804af2f55a013d0631785c7bb348f9dcb14af9 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Wed, 14 Sep 2011 10:27:57 -0400 Subject: [PATCH 098/219] Fixes OTWO-988, completely ignores kind_changed entries in the log. bzr generates kind_changed entries when file-kind changes, e.g symlink changed to a file. These entries are now completely ignored. Tests are added for ignoring directory entries and kind_changed entries. --- lib/scm/parsers/bzr_xml_parser.rb | 9 ++- test/unit/bzr_xml_parser_test.rb | 92 +++++++++++++++++++++++++++++-- 2 files changed, 95 insertions(+), 6 deletions(-) diff --git a/lib/scm/parsers/bzr_xml_parser.rb b/lib/scm/parsers/bzr_xml_parser.rb index ed970b8d..77f44a3c 100644 --- a/lib/scm/parsers/bzr_xml_parser.rb +++ b/lib/scm/parsers/bzr_xml_parser.rb @@ -10,6 +10,7 @@ class BazaarListener def initialize(callback) @callback = callback @merge_commit = [] + @state = :none end attr_accessor :text, :commit, :diff @@ -23,6 +24,7 @@ def tag_start(name, attrs) @diffs = [] when 'added', 'modified', 'removed', 'renamed' @action = name + @state = :collect_files when 'file' @before_path = attrs['oldpath'] when 'merge' @@ -45,8 +47,13 @@ def tag_end(name) when 'timestamp' @commit.committer_date = Time.parse(@text) when 'file' - @diffs.concat(parse_diff(@action, @text, @before_path)) + if @state == :collect_files + @diffs.concat(parse_diff(@action, @text, @before_path)) + end @before_path = nil + @text = nil + when 'added', 'modified', 'removed', 'renamed' + @state = :none when 'affected-files' @commit.diffs = remove_dupes(@diffs) when 'merge' diff --git a/test/unit/bzr_xml_parser_test.rb b/test/unit/bzr_xml_parser_test.rb index 713df529..2d24912f 100644 --- a/test/unit/bzr_xml_parser_test.rb +++ b/test/unit/bzr_xml_parser_test.rb @@ -3,10 +3,6 @@ module Scm::Parsers class BzrXmlParserTest < Scm::Test - #def test_basic - # assert_convert(BzrXmlParser, DATA_DIR + '/simple.svn_xml_log', DATA_DIR + '/simple.ohlog') - #end - def test_empty_array assert_equal([], BzrXmlParser.parse('')) end @@ -86,5 +82,91 @@ def test_verbose_xml assert_equal "A", c.diffs[3].action end - end + # When an directory is deleted, bzr outputs one delete entry + # per file and one for the directory. For empty dirs, there + # is only one directory remove entry. + # Ohloh keeps file delete entries but ignores directory + # delete entry. + def test_ignore_dir_delete_xml + xml = <<-XML + + + + 720.9.33 + jano.vesely@gmail.com-20110127220929-d3af6kj4d53lh70t + + jano.vesely@gmail.com-20110125225108-0vxoig7z3d3q0w0w + vojtechhorky@users.sourceforge.net-20110126145255-4xdar4rxwcrh6s0a + + Jan Vesely <jano.vesely@gmail.com> + helenos + Thu 2011-01-27 23:09:29 +0100 + + + + uspace/lib/net/include/nil_interface.h + uspace/srv/hw/bus/usb/ + uspace/srv/hw/bus/usb/hcd/ + + + + + XML + commits = BzrXmlParser.parse(xml) + assert_equal 1, commits.size + + c = commits.first + assert_equal 1, c.diffs.size + assert_equal "uspace/lib/net/include/nil_interface.h", c.diffs.first.path + end + + # bzr also outputs a kind_changed entry when file kind changes, for example + # a symlink is changed to file. + # Ohloh ignores such changes. + def test_ignore_kind_changed_xml + xml = <<-XML + + + + 720.9.33 + jano.vesely@gmail.com-20110127220929-d3af6kj4d53lh70t + + jano.vesely@gmail.com-20110125225108-0vxoig7z3d3q0w0w + vojtechhorky@users.sourceforge.net-20110126145255-4xdar4rxwcrh6s0a + + Jan Vesely <jano.vesely@gmail.com> + helenos + Thu 2011-01-27 23:09:29 +0100 + + + + uspace/lib/net/include/nil_interface.h + + + uspace/app/tester/mm/mapping1.c + + + uspace/lib/usb/include/usb/hcd.h + uspace/lib/usb/include/usb/addrkeep.h + + + .bzrignore + + + + + XML + commits = BzrXmlParser.parse(xml) + assert_equal 1, commits.size + + c = commits.first + assert_equal 3, c.diffs.size + assert_equal "D", c.diffs[0].action + assert_equal "uspace/lib/net/include/nil_interface.h", c.diffs[0].path + assert_equal "A", c.diffs[1].action + assert_equal "uspace/app/tester/mm/mapping1.c", c.diffs[1].path + assert_equal "M", c.diffs[2].action + assert_equal ".bzrignore", c.diffs[2].path + end + end end From efae60b8113f16d212308089f9c1bf8bba2ab1a2 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Thu, 6 Oct 2011 11:51:55 -0400 Subject: [PATCH 099/219] Updates bzrlib based adapter to use APIs only (instead of cmd_* classes). cmd_* based adapter was leaking memory. Details are here - https://answers.launchpad.net/bzr/+question/173096 --- lib/scm/adapters/bzrlib/bzrlib_commands.py | 58 +++++++++++----------- lib/scm/adapters/bzrlib/cat_file.rb | 17 +++---- lib/scm/adapters/bzrlib/head.rb | 18 ++----- lib/scm/adapters/bzrlib_adapter.rb | 16 +++--- 4 files changed, 50 insertions(+), 59 deletions(-) diff --git a/lib/scm/adapters/bzrlib/bzrlib_commands.py b/lib/scm/adapters/bzrlib/bzrlib_commands.py index 3ccf0f82..f49f0f33 100644 --- a/lib/scm/adapters/bzrlib/bzrlib_commands.py +++ b/lib/scm/adapters/bzrlib/bzrlib_commands.py @@ -1,36 +1,36 @@ -from bzrlib.builtins import cmd_cat -from bzrlib.builtins import cmd_log +from bzrlib.branch import Branch from bzrlib.revisionspec import RevisionSpec -import StringIO -import os -# Get contents of a file for specific revision. -def bzr_cat(repository_url, filename, revision): - os.chdir(repository_url) - spec = RevisionSpec.from_string(revision) - output = StringIO.StringIO() - cmd = cmd_cat() - cmd.outf = output - cmd.run_direct(filename=filename, revision=[spec], name_from_revision=True) - return output.getvalue() +class BzrCommander: + def __init__(self, repository_url): + self.branch = Branch.open(repository_url) + self.branch.lock_read() + #self.repository = self.branch.repository + + def get_file_content(self, filename, revision): + rev_spec = RevisionSpec.from_string(revision) + tree = rev_spec.as_tree(self.branch) + file_id = tree.path2id(filename) + if file_id == None: + return None + content = tree.get_file_text(file_id) + #if isinstance(content, unicode): + # content = content.encode('UTF-8') + return content + + def get_parent_tokens(self, revision): + revision = RevisionSpec.from_string(revision) + tree = revision.as_tree(self.branch) + parents = tree.get_parent_ids() + #print parents + return parents + + def cleanup(): + self.branch.unlock() -# Get log for a specific revision. -def bzr_log(repository_url, change): - os.chdir(repository_url) - change_rev = RevisionSpec.from_string(change) - output = StringIO.StringIO() - cmd = cmd_log() - cmd.outf = output - cmd.run_direct(file_list=None, show_ids=True, change=[change_rev], limit=1) - val = output.getvalue() - if isinstance(val, unicode): - return val.encode('utf-8') - else: - return val if __name__ == "__main__": #print bzr_cat('/home/amujumdar/bzrlib_examples/bzr.2.1', 'bzrlib/transport/local.py', 'revid:pqm@pqm.ubuntu.com-20090624225712-x20543g8bpv6e9ny') - #print bzr_log('/home/amujumdar/bzrlib_examples/bzr.2.1', 'bzrlib/transport/local.py', show_ids=True, change='revid:pqm@pqm.ubuntu.com-20090624225712-x20543g8bpv6e9ny', limit=1) - #print bzr_log('/home/amujumdar/app/ohloh_scm/test/repositories/bzr', change='revid:obnox@samba.org-20090204004942-73rnw0izen42f154') - print bzr_log('/home/amujumdar/app/ohloh_scm/test/repositories/bzr', change='1') + cmd = BzrCommander('/home/amujumdar/bzrlib_examples/bzr.2.1') + print cmd.get_file_content('bzrlib/transport/local.py', 'revid:pqm@pqm.ubuntu.com-20090624225712-x20543g8bpv6e9ny'), diff --git a/lib/scm/adapters/bzrlib/cat_file.rb b/lib/scm/adapters/bzrlib/cat_file.rb index 740e0a3b..90122029 100644 --- a/lib/scm/adapters/bzrlib/cat_file.rb +++ b/lib/scm/adapters/bzrlib/cat_file.rb @@ -10,18 +10,17 @@ def cat_file_parent(commit, diff) end def cat(revision, path) - pwd = Dir.pwd begin - out = bzrlib_commands.bzr_cat(self.url, path, to_rev_param(revision, false)).to_s - rescue => expt - # return nil if err =~ / is not present in revision / - if expt.message =~ / is not present in revision / - out = nil + content = bzr_commander.get_file_content(path, to_rev_param(revision, false)) + # When file is not present in a revision, get_file_content returns None python object. + # None cannot be used as nil, hence must be compared to nil and converted. + if content != nil + out = content.to_s else - raise RuntimeError.new(expt.message) + out = nil end - ensure - Dir.chdir(pwd) + rescue => expt + raise RuntimeError.new(expt.message) end out end diff --git a/lib/scm/adapters/bzrlib/head.rb b/lib/scm/adapters/bzrlib/head.rb index 7b7e36ee..1467338c 100644 --- a/lib/scm/adapters/bzrlib/head.rb +++ b/lib/scm/adapters/bzrlib/head.rb @@ -10,25 +10,13 @@ def head end def parent_tokens(commit) - #run("cd '#{url}' && bzr log --long --show-id --limit 1 -c #{to_rev_param(commit.token)} | grep ^parent | cut -f2 -d' '").split("\n") - s = bzr_log(to_rev_param(commit.token, false)) - bzr_log(to_rev_param(commit.token, false)).scan(/^parent:\s(.*)$/)[0] + tokens = [] + bzr_commander.get_parent_tokens(to_rev_param(commit.token, false)).to_enum.each {|t| tokens << t} + return tokens end def parents(commit) parent_tokens(commit).collect { |token| verbose_commit(token) } end - - def bzr_log(revision) - pwd = Dir.pwd - begin - out = bzrlib_commands.bzr_log(self.url, revision) - rescue => expt - raise RuntimeError.new(expt.message) - ensure - Dir.chdir(pwd) - end - out.to_s - end end end diff --git a/lib/scm/adapters/bzrlib_adapter.rb b/lib/scm/adapters/bzrlib_adapter.rb index 7e06501d..a97ad5a6 100644 --- a/lib/scm/adapters/bzrlib_adapter.rb +++ b/lib/scm/adapters/bzrlib_adapter.rb @@ -6,14 +6,18 @@ class BzrlibAdapter < BzrAdapter def english_name "Bazaar" end - def bzrlib_commands - @bzrlib_commands ||= begin - ENV['PYTHONPATH'] = File.dirname(__FILE__) + '/bzrlib' - RubyPython.start - RubyPython.import('bzrlib_commands') - end + def setup + ENV['PYTHONPATH'] = File.dirname(__FILE__) + '/bzrlib' + RubyPython.start + @bzrlib = RubyPython.import('bzrlib_commands') + @commander = @bzrlib.BzrCommander.new(url) + end + def bzr_commander + setup unless @commander + return @commander end def cleaup + bzr_commander.cleanup RubyPython.stop end end From 655f1ef5f388d4d06b559a84966e6a399e3f2650 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Thu, 6 Oct 2011 22:46:44 -0400 Subject: [PATCH 100/219] Incorporates Robin's code cleanup. --- lib/scm/adapters/bzrlib/cat_file.rb | 32 +++++++---------------------- lib/scm/adapters/bzrlib/head.rb | 15 +------------- lib/scm/adapters/bzrlib_adapter.rb | 11 +++++----- 3 files changed, 14 insertions(+), 44 deletions(-) diff --git a/lib/scm/adapters/bzrlib/cat_file.rb b/lib/scm/adapters/bzrlib/cat_file.rb index 90122029..cd726e6f 100644 --- a/lib/scm/adapters/bzrlib/cat_file.rb +++ b/lib/scm/adapters/bzrlib/cat_file.rb @@ -1,34 +1,16 @@ module Scm::Adapters class BzrlibAdapter < BzrAdapter - def cat_file(commit, diff) - cat(commit.token, diff.path) - end - - def cat_file_parent(commit, diff) - first_parent_token = parent_tokens(commit).first - cat(first_parent_token, diff.path) if first_parent_token - end def cat(revision, path) - begin - content = bzr_commander.get_file_content(path, to_rev_param(revision, false)) - # When file is not present in a revision, get_file_content returns None python object. - # None cannot be used as nil, hence must be compared to nil and converted. - if content != nil - out = content.to_s - else - out = nil - end - rescue => expt - raise RuntimeError.new(expt.message) + content = bzr_commander.get_file_content(path, to_rev_param(revision, false)) + # When file is not present in a revision, get_file_content returns None python object. + # None cannot be used as nil, hence must be compared to nil and converted. + if content != nil + content.to_s + else + nil end - out end - # Bzr doesn't like it when the filename includes a colon - # Also, fix the case where the filename includes a single quote - def escape(path) - path.gsub(/[:]/) { |c| '\\' + c }.gsub("'", "''") - end end end diff --git a/lib/scm/adapters/bzrlib/head.rb b/lib/scm/adapters/bzrlib/head.rb index 1467338c..4f88f6d3 100644 --- a/lib/scm/adapters/bzrlib/head.rb +++ b/lib/scm/adapters/bzrlib/head.rb @@ -1,22 +1,9 @@ module Scm::Adapters class BzrlibAdapter < BzrAdapter - def head_token - run("bzr log --limit 1 --show-id #{url} 2> /dev/null | grep ^revision-id | cut -f2 -d' '").strip - #bzr_log(nil).scan(/^revision-id:\s(.*)$/)[0][0].strip - end - - def head - verbose_commit(head_token) - end def parent_tokens(commit) - tokens = [] - bzr_commander.get_parent_tokens(to_rev_param(commit.token, false)).to_enum.each {|t| tokens << t} - return tokens + bzr_commander.get_parent_tokens(to_rev_param(commit.token, false)).to_enum end - def parents(commit) - parent_tokens(commit).collect { |token| verbose_commit(token) } - end end end diff --git a/lib/scm/adapters/bzrlib_adapter.rb b/lib/scm/adapters/bzrlib_adapter.rb index a97ad5a6..8216387e 100644 --- a/lib/scm/adapters/bzrlib_adapter.rb +++ b/lib/scm/adapters/bzrlib_adapter.rb @@ -2,24 +2,25 @@ require 'rubypython' module Scm::Adapters - class BzrlibAdapter < BzrAdapter - def english_name - "Bazaar" - end + class BzrlibAdapter < BzrAdapter + def setup ENV['PYTHONPATH'] = File.dirname(__FILE__) + '/bzrlib' RubyPython.start @bzrlib = RubyPython.import('bzrlib_commands') @commander = @bzrlib.BzrCommander.new(url) end + def bzr_commander setup unless @commander return @commander end - def cleaup + + def cleanup bzr_commander.cleanup RubyPython.stop end + end end From 286cc46756f217cfc0e17dc7a15d40eb9ea0a32b Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Fri, 7 Oct 2011 14:04:53 -0400 Subject: [PATCH 101/219] Implements IPC/pipe based bzr adapter. This commit changes the BzrlibAdapter to use an out-of-process Python process serving bzr commands. bzrlib_pipe_server implements a command loop, where it expects commands on stdin, sends status/ control-info on stderr and actual data on stdout. BzrlibAdapter acts as a client. --- lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb | 86 +++++++++++++++ lib/scm/adapters/bzrlib/bzrlib_pipe_server.py | 101 ++++++++++++++++++ lib/scm/adapters/bzrlib/cat_file.rb | 8 +- lib/scm/adapters/bzrlib/head.rb | 2 +- lib/scm/adapters/bzrlib_adapter.rb | 16 ++- 5 files changed, 197 insertions(+), 16 deletions(-) create mode 100644 lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb create mode 100644 lib/scm/adapters/bzrlib/bzrlib_pipe_server.py diff --git a/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb b/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb new file mode 100644 index 00000000..3a7e0d65 --- /dev/null +++ b/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb @@ -0,0 +1,86 @@ +require 'rubygems' +require 'open4' +require 'stringio' + +class BzrPipeClient + def initialize(repository_url) + @repository_url = repository_url + @py_script = File.dirname(__FILE__) + '/bzrlib_pipe_server.py' + end + + def start + @pid, @stdin, @stdout, @stderr = Open4::popen4 "python #{@py_script}" + open_repository + end + + def open_repository + send_command("REP_OPEN|#{@repository_url}") + end + def cat_file(revision, file) + send_command("CAT_FILE|#{revision}|#{file}", true) + end + + def parent_tokens(revision) + send_command("PAR_TKNS|#{revision}", true).split('|') + end + + def send_command(cmd, capture_output=false) + #puts "COMMAND - #{cmd}" + STDOUT.flush + outbuf = StringIO.new + errbuf = StringIO.new + + # send the command + @stdin.puts cmd + @stdin.flush + + # get status on stderr, first letter indicates state, + # remaing value indicates length of the file content + status = @stderr.read(10) + #puts "STATUS - #{status}" + flag = status[0,1] + size = status[1,10].to_i + if flag == 'F' + return nil + elsif flag == 'E' + error = @stdout.read(size) + raise RuntimeError.new("Exception in server process\n#{error}") + end + + # read content from stdout + if capture_output + return @stdout.read(size) + end + end + + def shutdown + send_command("QUIT") + Process.waitpid(@pid, Process::WNOHANG) + end +end + +def cat_all_files(client, datafile) + count = 0 + bytes = 0 + File.open(datafile).each do |line| + parts = line.split('|') + count = count + 1 + bytes = bytes + client.cat_file(parts[0], parts[1]).size + puts "file=#{count}, bytes=#{bytes}" + end +end + +def all_parent_tokens(client, datafile) + File.open(datafile).each do |line| + parts = line.split('|') + puts client.parent_tokens(parts[0]) + end +end + +#datafile = 'revs_only.txt' +#c = BzrPipeClient.new('/home/amujumdar/bzrlib_examples/bzr.2.1') +#c.start +#all_parent_tokens(c, datafile) +#cat_all_files(c,datafile) +#c.shutdown + diff --git a/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py b/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py new file mode 100644 index 00000000..83124818 --- /dev/null +++ b/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py @@ -0,0 +1,101 @@ +from bzrlib.branch import Branch +from bzrlib.revisionspec import RevisionSpec +import sys +import time +import traceback + +class BzrCommander: + def __init__(self, repository_url): + self.branch = Branch.open(repository_url) + self.branch.lock_read() + + def get_file_content(self, filename, revision): + rev_spec = RevisionSpec.from_string(revision) + tree = rev_spec.as_tree(self.branch) + file_id = tree.path2id(filename) + if file_id == None: + return None + content = tree.get_file_text(file_id) + return content + + def get_parent_tokens(self, revision): + rev_spec = RevisionSpec.from_string(revision) + tree = rev_spec.as_tree(self.branch) + parents = tree.get_parent_ids() + return parents + + def cleanup(self): + self.branch.unlock() + +class Command: + def __init__(self, line): + self.args = line.rstrip().split('|') + + def get_action(self): + return self.args[0] + + def get_arg(self, num): + return self.args[num] + +def send_status(code, data_len): + sys.stderr.write('%s%09d' % (code, data_len)) + sys.stderr.flush() + +def send_success(data_len=0): + send_status('T', data_len) + +def send_failure(data_len=0): + send_status('F', data_len) + +def send_error(data_len=0): + send_status('E', data_len) + +def send_data(result): + sys.stdout.write(result) + sys.stdout.flush() + +def exit_delayed(status, delay=1): + time.sleep(delay) + sys.exit(status) + +def command_loop(): + while True: + cmd = Command(sys.stdin.readline()) + if cmd.get_action() == 'REP_OPEN': + commander = BzrCommander(cmd.get_arg(1)) + send_success() + elif cmd.get_action() == 'CAT_FILE': + content = commander.get_file_content(cmd.get_arg(2), cmd.get_arg(1)) + if content == None: + send_failure() + else: + send_success(len(content)) + send_data(content) + elif cmd.get_action() == 'PAR_TKNS': + tokens = commander.get_parent_tokens(cmd.get_arg(1)) + tokens = '|'.join(tokens) + send_success(len(tokens)) + send_data(tokens) + elif cmd.get_action() == 'QUIT': + commander.cleanup() + send_success() + exit_delayed(status=0) + else: + error = "Invalid Command - %s" % cmd.get_action() + send_error(len(error)) + send_data(error) + exit_delayed(status=1) + +if __name__ == "__main__": + try: + command_loop() + #commander = BzrCommander('/home/amujumdar/bzrlib_examples/bzr.2.1') + #tokens = commander.get_parent_tokens('mbp@sourcefrog.net-20050309040929-eee0eb3e6d1e7627') + #tokens = commander.get_parent_tokens('XXXXXXXXXXXXXX') + #tokens = '|'.join(tokens) + #print tokens + except: + exc_trace = traceback.format_exc() + send_error(len(exc_trace)) + send_data(exc_trace) + exit_delayed(status=1) diff --git a/lib/scm/adapters/bzrlib/cat_file.rb b/lib/scm/adapters/bzrlib/cat_file.rb index cd726e6f..082eac8e 100644 --- a/lib/scm/adapters/bzrlib/cat_file.rb +++ b/lib/scm/adapters/bzrlib/cat_file.rb @@ -2,14 +2,10 @@ module Scm::Adapters class BzrlibAdapter < BzrAdapter def cat(revision, path) - content = bzr_commander.get_file_content(path, to_rev_param(revision, false)) + content = bzr_client.cat_file(to_rev_param(revision, false), path) # When file is not present in a revision, get_file_content returns None python object. # None cannot be used as nil, hence must be compared to nil and converted. - if content != nil - content.to_s - else - nil - end + return content end end diff --git a/lib/scm/adapters/bzrlib/head.rb b/lib/scm/adapters/bzrlib/head.rb index 4f88f6d3..69255d73 100644 --- a/lib/scm/adapters/bzrlib/head.rb +++ b/lib/scm/adapters/bzrlib/head.rb @@ -2,7 +2,7 @@ module Scm::Adapters class BzrlibAdapter < BzrAdapter def parent_tokens(commit) - bzr_commander.get_parent_tokens(to_rev_param(commit.token, false)).to_enum + bzr_client.parent_tokens(to_rev_param(commit.token, false)) end end diff --git a/lib/scm/adapters/bzrlib_adapter.rb b/lib/scm/adapters/bzrlib_adapter.rb index 8216387e..7195b74a 100644 --- a/lib/scm/adapters/bzrlib_adapter.rb +++ b/lib/scm/adapters/bzrlib_adapter.rb @@ -1,24 +1,22 @@ require 'rubygems' require 'rubypython' +require 'lib/scm/adapters/bzrlib/bzrlib_pipe_client' module Scm::Adapters class BzrlibAdapter < BzrAdapter def setup - ENV['PYTHONPATH'] = File.dirname(__FILE__) + '/bzrlib' - RubyPython.start - @bzrlib = RubyPython.import('bzrlib_commands') - @commander = @bzrlib.BzrCommander.new(url) + @bzr_client = BzrPipeClient.new(url) + @bzr_client.start end - def bzr_commander - setup unless @commander - return @commander + def bzr_client + setup unless @bzr_client + return @bzr_client end def cleanup - bzr_commander.cleanup - RubyPython.stop + @bzr_client.shutdown end end From ee0d7aa06e073358975cd9a9bf4da39548136769 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Fri, 7 Oct 2011 14:05:19 -0400 Subject: [PATCH 102/219] Implements IPC/pipe based bzr adapter. This commit changes the BzrlibAdapter to use an out-of-process Python process serving bzr commands. bzrlib_pipe_server implements a command loop, where it expects commands on stdin, sends status/ control-info on stderr and actual data on stdout. BzrlibAdapter acts as a client. --- lib/scm/adapters/bzrlib/bzrlib_pipe_server.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py b/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py index 83124818..1a2b9200 100644 --- a/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py +++ b/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py @@ -4,7 +4,7 @@ import time import traceback -class BzrCommander: +class BzrPipeServer: def __init__(self, repository_url): self.branch = Branch.open(repository_url) self.branch.lock_read() @@ -62,7 +62,7 @@ def command_loop(): while True: cmd = Command(sys.stdin.readline()) if cmd.get_action() == 'REP_OPEN': - commander = BzrCommander(cmd.get_arg(1)) + commander = BzrPipeServer(cmd.get_arg(1)) send_success() elif cmd.get_action() == 'CAT_FILE': content = commander.get_file_content(cmd.get_arg(2), cmd.get_arg(1)) @@ -89,7 +89,7 @@ def command_loop(): if __name__ == "__main__": try: command_loop() - #commander = BzrCommander('/home/amujumdar/bzrlib_examples/bzr.2.1') + #commander = BzrPipeServer('/home/amujumdar/bzrlib_examples/bzr.2.1') #tokens = commander.get_parent_tokens('mbp@sourcefrog.net-20050309040929-eee0eb3e6d1e7627') #tokens = commander.get_parent_tokens('XXXXXXXXXXXXXX') #tokens = '|'.join(tokens) From 9041bcf5a304a50a1e11def4c3404316b92189bd Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Fri, 7 Oct 2011 14:51:54 -0400 Subject: [PATCH 103/219] Incorporates Robin's code review; no need to prefix revid with API calls. --- lib/scm/adapters/bzr/misc.rb | 11 ++--------- lib/scm/adapters/bzrlib/cat_file.rb | 2 +- lib/scm/adapters/bzrlib/head.rb | 2 +- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/lib/scm/adapters/bzr/misc.rb b/lib/scm/adapters/bzr/misc.rb index dc996016..07d69413 100644 --- a/lib/scm/adapters/bzr/misc.rb +++ b/lib/scm/adapters/bzr/misc.rb @@ -13,10 +13,7 @@ def ls_tree(token) run("cd #{path} && bzr ls -V -r #{to_rev_param(token)}").split("\n") end - # If you want to pass a revision-id as a bzr parameter, you - # must prefix it with "revid:". This takes care of that. - # When passed to bzrlib calls, we don't need to enquote it. - def to_rev_param(r=nil, enquote=true) + def to_rev_param(r=nil) case r when nil 1 @@ -25,11 +22,7 @@ def to_rev_param(r=nil, enquote=true) when /^\d+$/ r else - if enquote - "'revid:#{r.to_s}'" - else - "revid:#{r.to_s}" - end + "'revid:#{r.to_s}'" end end diff --git a/lib/scm/adapters/bzrlib/cat_file.rb b/lib/scm/adapters/bzrlib/cat_file.rb index 082eac8e..accfa87c 100644 --- a/lib/scm/adapters/bzrlib/cat_file.rb +++ b/lib/scm/adapters/bzrlib/cat_file.rb @@ -2,7 +2,7 @@ module Scm::Adapters class BzrlibAdapter < BzrAdapter def cat(revision, path) - content = bzr_client.cat_file(to_rev_param(revision, false), path) + content = bzr_client.cat_file(revision, path) # When file is not present in a revision, get_file_content returns None python object. # None cannot be used as nil, hence must be compared to nil and converted. return content diff --git a/lib/scm/adapters/bzrlib/head.rb b/lib/scm/adapters/bzrlib/head.rb index 69255d73..fe1f1364 100644 --- a/lib/scm/adapters/bzrlib/head.rb +++ b/lib/scm/adapters/bzrlib/head.rb @@ -2,7 +2,7 @@ module Scm::Adapters class BzrlibAdapter < BzrAdapter def parent_tokens(commit) - bzr_client.parent_tokens(to_rev_param(commit.token, false)) + bzr_client.parent_tokens(commit.token) end end From e07c5129474fda2c7fe2a2acb2b53e158e4827ad Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Fri, 7 Oct 2011 14:53:27 -0400 Subject: [PATCH 104/219] Incorporate Robin's code review comment. --- test/unit/bzrlib_cat_file_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/bzrlib_cat_file_test.rb b/test/unit/bzrlib_cat_file_test.rb index 518087e8..1fe1e4b5 100644 --- a/test/unit/bzrlib_cat_file_test.rb +++ b/test/unit/bzrlib_cat_file_test.rb @@ -1,7 +1,7 @@ require File.dirname(__FILE__) + '/../test_helper' module Scm::Adapters - class BzrCatFileTest < Scm::Test + class BzrlibCatFileTest < Scm::Test def test_cat_file with_bzrlib_repository('bzr') do |bzr| From 0b555545fe762bd5d881230810e8b5530d3b2358 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Fri, 7 Oct 2011 14:54:07 -0400 Subject: [PATCH 105/219] Incorporates Robin's code review; remove unnecessary comment and return. --- lib/scm/adapters/bzrlib/cat_file.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/scm/adapters/bzrlib/cat_file.rb b/lib/scm/adapters/bzrlib/cat_file.rb index accfa87c..06eb4059 100644 --- a/lib/scm/adapters/bzrlib/cat_file.rb +++ b/lib/scm/adapters/bzrlib/cat_file.rb @@ -3,9 +3,6 @@ class BzrlibAdapter < BzrAdapter def cat(revision, path) content = bzr_client.cat_file(revision, path) - # When file is not present in a revision, get_file_content returns None python object. - # None cannot be used as nil, hence must be compared to nil and converted. - return content end end From 4250995943296469e8db78f00ed61b7bb268b0eb Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Fri, 7 Oct 2011 14:54:47 -0400 Subject: [PATCH 106/219] Incorporates Robin's code review; remove commented test code. --- lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb b/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb index 3a7e0d65..86ccd241 100644 --- a/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb +++ b/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb @@ -76,11 +76,3 @@ def all_parent_tokens(client, datafile) puts client.parent_tokens(parts[0]) end end - -#datafile = 'revs_only.txt' -#c = BzrPipeClient.new('/home/amujumdar/bzrlib_examples/bzr.2.1') -#c.start -#all_parent_tokens(c, datafile) -#cat_all_files(c,datafile) -#c.shutdown - From 045a80cce2c9d478cee2d1ede04e138293f23636 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Fri, 7 Oct 2011 14:59:14 -0400 Subject: [PATCH 107/219] Removes unused code. --- lib/scm/adapters/bzrlib/bzrlib_commands.py | 36 ---------------------- 1 file changed, 36 deletions(-) delete mode 100644 lib/scm/adapters/bzrlib/bzrlib_commands.py diff --git a/lib/scm/adapters/bzrlib/bzrlib_commands.py b/lib/scm/adapters/bzrlib/bzrlib_commands.py deleted file mode 100644 index f49f0f33..00000000 --- a/lib/scm/adapters/bzrlib/bzrlib_commands.py +++ /dev/null @@ -1,36 +0,0 @@ -from bzrlib.branch import Branch -from bzrlib.revisionspec import RevisionSpec - -class BzrCommander: - def __init__(self, repository_url): - self.branch = Branch.open(repository_url) - self.branch.lock_read() - #self.repository = self.branch.repository - - def get_file_content(self, filename, revision): - rev_spec = RevisionSpec.from_string(revision) - tree = rev_spec.as_tree(self.branch) - file_id = tree.path2id(filename) - if file_id == None: - return None - content = tree.get_file_text(file_id) - #if isinstance(content, unicode): - # content = content.encode('UTF-8') - return content - - def get_parent_tokens(self, revision): - revision = RevisionSpec.from_string(revision) - tree = revision.as_tree(self.branch) - parents = tree.get_parent_ids() - #print parents - return parents - - def cleanup(): - self.branch.unlock() - - -if __name__ == "__main__": - #print bzr_cat('/home/amujumdar/bzrlib_examples/bzr.2.1', 'bzrlib/transport/local.py', 'revid:pqm@pqm.ubuntu.com-20090624225712-x20543g8bpv6e9ny') - cmd = BzrCommander('/home/amujumdar/bzrlib_examples/bzr.2.1') - print cmd.get_file_content('bzrlib/transport/local.py', 'revid:pqm@pqm.ubuntu.com-20090624225712-x20543g8bpv6e9ny'), - From 13cd276cd3fbc59af6f7cf76ab3a272b56a4b021 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Fri, 7 Oct 2011 15:01:06 -0400 Subject: [PATCH 108/219] Removes unnecessary commented-out code. --- lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb | 3 --- lib/scm/adapters/bzrlib/bzrlib_pipe_server.py | 5 ----- 2 files changed, 8 deletions(-) diff --git a/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb b/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb index 86ccd241..f74c060a 100644 --- a/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb +++ b/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb @@ -25,8 +25,6 @@ def parent_tokens(revision) end def send_command(cmd, capture_output=false) - #puts "COMMAND - #{cmd}" - STDOUT.flush outbuf = StringIO.new errbuf = StringIO.new @@ -37,7 +35,6 @@ def send_command(cmd, capture_output=false) # get status on stderr, first letter indicates state, # remaing value indicates length of the file content status = @stderr.read(10) - #puts "STATUS - #{status}" flag = status[0,1] size = status[1,10].to_i if flag == 'F' diff --git a/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py b/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py index 1a2b9200..53acb91f 100644 --- a/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py +++ b/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py @@ -89,11 +89,6 @@ def command_loop(): if __name__ == "__main__": try: command_loop() - #commander = BzrPipeServer('/home/amujumdar/bzrlib_examples/bzr.2.1') - #tokens = commander.get_parent_tokens('mbp@sourcefrog.net-20050309040929-eee0eb3e6d1e7627') - #tokens = commander.get_parent_tokens('XXXXXXXXXXXXXX') - #tokens = '|'.join(tokens) - #print tokens except: exc_trace = traceback.format_exc() send_error(len(exc_trace)) From fa63b762dcd193e0360303f9952f5e582b874767 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Fri, 7 Oct 2011 15:08:04 -0400 Subject: [PATCH 109/219] Fixes slice parameter. --- lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb b/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb index f74c060a..cb95a868 100644 --- a/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb +++ b/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb @@ -36,7 +36,7 @@ def send_command(cmd, capture_output=false) # remaing value indicates length of the file content status = @stderr.read(10) flag = status[0,1] - size = status[1,10].to_i + size = status[1,9].to_i if flag == 'F' return nil elsif flag == 'E' From cc0ba85a9d08a1581974edd864e9c602c9359eff Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Fri, 7 Oct 2011 15:14:20 -0400 Subject: [PATCH 110/219] Removes unnecessary parameter from send_command method. --- lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb b/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb index cb95a868..742cbd42 100644 --- a/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb +++ b/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb @@ -17,14 +17,14 @@ def open_repository send_command("REP_OPEN|#{@repository_url}") end def cat_file(revision, file) - send_command("CAT_FILE|#{revision}|#{file}", true) + send_command("CAT_FILE|#{revision}|#{file}") end def parent_tokens(revision) - send_command("PAR_TKNS|#{revision}", true).split('|') + send_command("PAR_TKNS|#{revision}").split('|') end - def send_command(cmd, capture_output=false) + def send_command(cmd) outbuf = StringIO.new errbuf = StringIO.new @@ -45,9 +45,7 @@ def send_command(cmd, capture_output=false) end # read content from stdout - if capture_output - return @stdout.read(size) - end + return @stdout.read(size) end def shutdown From f5351acb9709aa58b9397f1087b6ddfc1c3dfb05 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Tue, 11 Oct 2011 13:04:08 -0400 Subject: [PATCH 111/219] OTWO-1023 - Fixes BzrXmlParser to capture first author when present. BzrXmlParser depends on bzr's xmloutput plugin. This plugin does not emit authors. See the bug report for info - https://bugs.launchpad.net/bzr-xmloutput/+bug/618307 We have patched the xmloutput plugin and have submitted a patch to xmloutput plugin. Meanwhile, we'll deploy patched version on slaves. --- lib/scm/parsers/bzr_xml_parser.rb | 10 +++ .../repositories/bzr_with_authors/.bzr/README | 3 + .../bzr_with_authors/.bzr/branch-format | 1 + .../bzr_with_authors/.bzr/branch/branch.conf | 0 .../bzr_with_authors/.bzr/branch/format | 1 + .../.bzr/branch/last-revision | 1 + .../bzr_with_authors/.bzr/branch/tags | 0 .../bzr_with_authors/.bzr/checkout/conflicts | 1 + .../bzr_with_authors/.bzr/checkout/dirstate | Bin 0 -> 513 bytes .../bzr_with_authors/.bzr/checkout/format | 1 + .../bzr_with_authors/.bzr/checkout/views | 0 .../bzr_with_authors/.bzr/repository/format | 1 + .../1326ecee2f4f69991771137c5307689a.cix | Bin 0 -> 149 bytes .../1326ecee2f4f69991771137c5307689a.iix | Bin 0 -> 195 bytes .../1326ecee2f4f69991771137c5307689a.rix | 6 ++ .../1326ecee2f4f69991771137c5307689a.six | 5 ++ .../1326ecee2f4f69991771137c5307689a.tix | Bin 0 -> 220 bytes .../adf730b6cf7c7959afcedb87e155654d.cix | Bin 0 -> 184 bytes .../adf730b6cf7c7959afcedb87e155654d.iix | Bin 0 -> 166 bytes .../adf730b6cf7c7959afcedb87e155654d.rix | Bin 0 -> 166 bytes .../adf730b6cf7c7959afcedb87e155654d.six | 5 ++ .../adf730b6cf7c7959afcedb87e155654d.tix | 6 ++ .../d2613fcfb5e48e79073b96270782f95c.cix | Bin 0 -> 148 bytes .../d2613fcfb5e48e79073b96270782f95c.iix | Bin 0 -> 187 bytes .../d2613fcfb5e48e79073b96270782f95c.rix | Bin 0 -> 187 bytes .../d2613fcfb5e48e79073b96270782f95c.six | 5 ++ .../d2613fcfb5e48e79073b96270782f95c.tix | Bin 0 -> 210 bytes .../.bzr/repository/pack-names | Bin 0 -> 197 bytes .../1326ecee2f4f69991771137c5307689a.pack | Bin 0 -> 956 bytes .../adf730b6cf7c7959afcedb87e155654d.pack | Bin 0 -> 1001 bytes .../d2613fcfb5e48e79073b96270782f95c.pack | Bin 0 -> 919 bytes test/repositories/bzr_with_authors/test.txt | 1 + test/unit/bzr_commits_test.rb | 26 ++++++++ test/unit/bzr_xml_parser_test.rb | 60 ++++++++++++++++++ 34 files changed, 133 insertions(+) create mode 100644 test/repositories/bzr_with_authors/.bzr/README create mode 100644 test/repositories/bzr_with_authors/.bzr/branch-format create mode 100644 test/repositories/bzr_with_authors/.bzr/branch/branch.conf create mode 100644 test/repositories/bzr_with_authors/.bzr/branch/format create mode 100644 test/repositories/bzr_with_authors/.bzr/branch/last-revision create mode 100644 test/repositories/bzr_with_authors/.bzr/branch/tags create mode 100644 test/repositories/bzr_with_authors/.bzr/checkout/conflicts create mode 100644 test/repositories/bzr_with_authors/.bzr/checkout/dirstate create mode 100644 test/repositories/bzr_with_authors/.bzr/checkout/format create mode 100644 test/repositories/bzr_with_authors/.bzr/checkout/views create mode 100644 test/repositories/bzr_with_authors/.bzr/repository/format create mode 100644 test/repositories/bzr_with_authors/.bzr/repository/indices/1326ecee2f4f69991771137c5307689a.cix create mode 100644 test/repositories/bzr_with_authors/.bzr/repository/indices/1326ecee2f4f69991771137c5307689a.iix create mode 100644 test/repositories/bzr_with_authors/.bzr/repository/indices/1326ecee2f4f69991771137c5307689a.rix create mode 100644 test/repositories/bzr_with_authors/.bzr/repository/indices/1326ecee2f4f69991771137c5307689a.six create mode 100644 test/repositories/bzr_with_authors/.bzr/repository/indices/1326ecee2f4f69991771137c5307689a.tix create mode 100644 test/repositories/bzr_with_authors/.bzr/repository/indices/adf730b6cf7c7959afcedb87e155654d.cix create mode 100644 test/repositories/bzr_with_authors/.bzr/repository/indices/adf730b6cf7c7959afcedb87e155654d.iix create mode 100644 test/repositories/bzr_with_authors/.bzr/repository/indices/adf730b6cf7c7959afcedb87e155654d.rix create mode 100644 test/repositories/bzr_with_authors/.bzr/repository/indices/adf730b6cf7c7959afcedb87e155654d.six create mode 100644 test/repositories/bzr_with_authors/.bzr/repository/indices/adf730b6cf7c7959afcedb87e155654d.tix create mode 100644 test/repositories/bzr_with_authors/.bzr/repository/indices/d2613fcfb5e48e79073b96270782f95c.cix create mode 100644 test/repositories/bzr_with_authors/.bzr/repository/indices/d2613fcfb5e48e79073b96270782f95c.iix create mode 100644 test/repositories/bzr_with_authors/.bzr/repository/indices/d2613fcfb5e48e79073b96270782f95c.rix create mode 100644 test/repositories/bzr_with_authors/.bzr/repository/indices/d2613fcfb5e48e79073b96270782f95c.six create mode 100644 test/repositories/bzr_with_authors/.bzr/repository/indices/d2613fcfb5e48e79073b96270782f95c.tix create mode 100644 test/repositories/bzr_with_authors/.bzr/repository/pack-names create mode 100644 test/repositories/bzr_with_authors/.bzr/repository/packs/1326ecee2f4f69991771137c5307689a.pack create mode 100644 test/repositories/bzr_with_authors/.bzr/repository/packs/adf730b6cf7c7959afcedb87e155654d.pack create mode 100644 test/repositories/bzr_with_authors/.bzr/repository/packs/d2613fcfb5e48e79073b96270782f95c.pack create mode 100644 test/repositories/bzr_with_authors/test.txt diff --git a/lib/scm/parsers/bzr_xml_parser.rb b/lib/scm/parsers/bzr_xml_parser.rb index 77f44a3c..1d17978b 100644 --- a/lib/scm/parsers/bzr_xml_parser.rb +++ b/lib/scm/parsers/bzr_xml_parser.rb @@ -11,6 +11,7 @@ def initialize(callback) @callback = callback @merge_commit = [] @state = :none + @authors = [] end attr_accessor :text, :commit, :diff @@ -30,6 +31,9 @@ def tag_start(name, attrs) when 'merge' # This is a merge commit, save it and pop it after all branch commits @merge_commit.push(@commit) + when 'authors' + @state = :collect_authors + @authors = [] end end @@ -44,6 +48,8 @@ def tag_end(name) when 'committer' @commit.committer_name = @text[/(.+?)(\s+<(.+)>)/, 1] @commit.committer_email = @text[/(.+?)(\s+<(.+)>)/, 3] + when 'author' + @authors << {:author_name => @text[/(.+?)(\s+<(.+)>)/, 1], :author_email => @text[/(.+?)(\s+<(.+)>)/, 3] } when 'timestamp' @commit.committer_date = Time.parse(@text) when 'file' @@ -58,6 +64,10 @@ def tag_end(name) @commit.diffs = remove_dupes(@diffs) when 'merge' @commit = @merge_commit.pop + when 'authors' + @commit.author_name = @authors[0][:author_name] + @commit.author_email = @authors[0][:author_email] + @authors.clear end end diff --git a/test/repositories/bzr_with_authors/.bzr/README b/test/repositories/bzr_with_authors/.bzr/README new file mode 100644 index 00000000..4f8e767e --- /dev/null +++ b/test/repositories/bzr_with_authors/.bzr/README @@ -0,0 +1,3 @@ +This is a Bazaar control directory. +Do not change any files in this directory. +See http://bazaar-vcs.org/ for more information about Bazaar. diff --git a/test/repositories/bzr_with_authors/.bzr/branch-format b/test/repositories/bzr_with_authors/.bzr/branch-format new file mode 100644 index 00000000..9eb09b73 --- /dev/null +++ b/test/repositories/bzr_with_authors/.bzr/branch-format @@ -0,0 +1 @@ +Bazaar-NG meta directory, format 1 diff --git a/test/repositories/bzr_with_authors/.bzr/branch/branch.conf b/test/repositories/bzr_with_authors/.bzr/branch/branch.conf new file mode 100644 index 00000000..e69de29b diff --git a/test/repositories/bzr_with_authors/.bzr/branch/format b/test/repositories/bzr_with_authors/.bzr/branch/format new file mode 100644 index 00000000..dc392f44 --- /dev/null +++ b/test/repositories/bzr_with_authors/.bzr/branch/format @@ -0,0 +1 @@ +Bazaar Branch Format 7 (needs bzr 1.6) diff --git a/test/repositories/bzr_with_authors/.bzr/branch/last-revision b/test/repositories/bzr_with_authors/.bzr/branch/last-revision new file mode 100644 index 00000000..de93b6d7 --- /dev/null +++ b/test/repositories/bzr_with_authors/.bzr/branch/last-revision @@ -0,0 +1 @@ +3 test@example.com-20111011162601-ud1nidteswfdbhbu diff --git a/test/repositories/bzr_with_authors/.bzr/branch/tags b/test/repositories/bzr_with_authors/.bzr/branch/tags new file mode 100644 index 00000000..e69de29b diff --git a/test/repositories/bzr_with_authors/.bzr/checkout/conflicts b/test/repositories/bzr_with_authors/.bzr/checkout/conflicts new file mode 100644 index 00000000..0dc2d3a0 --- /dev/null +++ b/test/repositories/bzr_with_authors/.bzr/checkout/conflicts @@ -0,0 +1 @@ +BZR conflict list format 1 diff --git a/test/repositories/bzr_with_authors/.bzr/checkout/dirstate b/test/repositories/bzr_with_authors/.bzr/checkout/dirstate new file mode 100644 index 0000000000000000000000000000000000000000..7c6ed0de3a3c6a41f55f36c364be9f6008afe175 GIT binary patch literal 513 zcmbVJO-lnY5Y2gi#ezrKl4N$1rl$rhwI>m^S4lQWZM$EjiCg>YO%)Zzi^4o+80O=> znG3B>O8MMu{UNAebJwVlyWY3SL00=3=qv}uK?s~I>tg$8yWqF>Fw1F1P_TzEw@1|u zjh)neTTo00IfGG#Nf8a{wkB1L&gdr{QHF2=Lcv@6==(l=byO4p3b9iz4lZzQpM^V( z1wjU-rVdFdZ{>nLXtTa)mavxcN~GNK@~)I}aV?SLg226XluH=?;FyOdw pz!~F}tEQkSuFG@}YSffrpa{x$IdZlCMb7%1*6}Pt8fqP0a&x z4Y_hs^MGVgetA5Qm0pqo604ZQdvYglg8>i2fh#kWly9gVG!i;&QRm{=$ijR3@Ye5p x!r!E4T>Bkx$7gx5*DNc4uQPItC#QWouhsED%O{BI(4~xk=4+W(`0biS;M1& literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_authors/.bzr/repository/indices/1326ecee2f4f69991771137c5307689a.rix b/test/repositories/bzr_with_authors/.bzr/repository/indices/1326ecee2f4f69991771137c5307689a.rix new file mode 100644 index 00000000..4a9e6cea --- /dev/null +++ b/test/repositories/bzr_with_authors/.bzr/repository/indices/1326ecee2f4f69991771137c5307689a.rix @@ -0,0 +1,6 @@ +B+Tree Graph Index 2 +node_ref_lists=1 +key_elements=1 +len=1 +row_lengths=1 +xœ]ËKƒ @QÇ®‚ Ðð“´ƒ&nå¨@5|‚võm§ÜÙ¹õ:ðüX±ÔOHGě݌sþK Í8mŽ¿V÷UÝ;³˜6@j[Kòl"Øàš e÷µCþû'¡¸ ñË•ÛŠï^¤Û ™$r„uWã8+¼ \ No newline at end of file diff --git a/test/repositories/bzr_with_authors/.bzr/repository/indices/1326ecee2f4f69991771137c5307689a.six b/test/repositories/bzr_with_authors/.bzr/repository/indices/1326ecee2f4f69991771137c5307689a.six new file mode 100644 index 00000000..a2afde6b --- /dev/null +++ b/test/repositories/bzr_with_authors/.bzr/repository/indices/1326ecee2f4f69991771137c5307689a.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/test/repositories/bzr_with_authors/.bzr/repository/indices/1326ecee2f4f69991771137c5307689a.tix b/test/repositories/bzr_with_authors/.bzr/repository/indices/1326ecee2f4f69991771137c5307689a.tix new file mode 100644 index 0000000000000000000000000000000000000000..066c97f8ab6052da4c44d4dba91e4f3f4d6a587a GIT binary patch literal 220 zcmV<203-iGD^zl2Wgtg#VQ^?5Np56icpx$gZf|5|Uvgz;UuuY2$RcrNtvq?yU;NoL+0=wH;lu<2E;O*Xz%fL;=YBle%+F WJze|8aU3#%g@U3gxXRyH3PTeF`CwrH literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_authors/.bzr/repository/indices/adf730b6cf7c7959afcedb87e155654d.cix b/test/repositories/bzr_with_authors/.bzr/repository/indices/adf730b6cf7c7959afcedb87e155654d.cix new file mode 100644 index 0000000000000000000000000000000000000000..6b4cd91c425435f7a4ec53c09cffa619b852e93c GIT binary patch literal 184 zcmZ?L4k=1aRd6p#EXYvs%u7kFP%z@k%TGy-FG@{|&&ez%1*6}Pt8fqP0a&x z4Y_hs^K6Z{it@|jfvohB43JpG9M#hsd6^A47#yzKx4JX*7`mJ?xRJ2beS2PJgzBRJ{?ab6s=RuGF&aw1VQ~88haH OKKALIRaZ4#dJh1H{6#4M literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_authors/.bzr/repository/indices/adf730b6cf7c7959afcedb87e155654d.six b/test/repositories/bzr_with_authors/.bzr/repository/indices/adf730b6cf7c7959afcedb87e155654d.six new file mode 100644 index 00000000..a2afde6b --- /dev/null +++ b/test/repositories/bzr_with_authors/.bzr/repository/indices/adf730b6cf7c7959afcedb87e155654d.six @@ -0,0 +1,5 @@ +B+Tree Graph Index 2 +node_ref_lists=0 +key_elements=1 +len=0 +row_lengths= diff --git a/test/repositories/bzr_with_authors/.bzr/repository/indices/adf730b6cf7c7959afcedb87e155654d.tix b/test/repositories/bzr_with_authors/.bzr/repository/indices/adf730b6cf7c7959afcedb87e155654d.tix new file mode 100644 index 00000000..7135df2c --- /dev/null +++ b/test/repositories/bzr_with_authors/.bzr/repository/indices/adf730b6cf7c7959afcedb87e155654d.tix @@ -0,0 +1,6 @@ +B+Tree Graph Index 2 +node_ref_lists=1 +key_elements=2 +len=2 +row_lengths=1 +xœ­ÍKƒ @QÇ®‚ `øH ƒ&î¤A>&*BðQÔÕ·:ïàNï3¹çê´oÁíÐÁ˜Jé/Á¸8LRŒ–qÚO×FÓi£C™K°:ãªÍb‹Yöè¡êì:ÃýðÀŠlk©§MUMýfJÓô q‰¢¬…ìÜ+Çxw9ÇjÖ¾$rtoå¯úW*Äø×%í•ÝKÄ \ No newline at end of file diff --git a/test/repositories/bzr_with_authors/.bzr/repository/indices/d2613fcfb5e48e79073b96270782f95c.cix b/test/repositories/bzr_with_authors/.bzr/repository/indices/d2613fcfb5e48e79073b96270782f95c.cix new file mode 100644 index 0000000000000000000000000000000000000000..a426a203dc5bd1dc1c193d0a436c12ba988061fb GIT binary patch literal 148 zcmZ?L4k=1aRd6p#EXYvs%u7kFP%z@k%TGy-FG@{|&&ez%1*6}Pt8fqP0a&x z4Y_hs^MGVgetA5Qm0pqo604ZQdhj%Fg8~mjz&W3T9Dg0VI}bPLetdAyML+L-_51SU wbw?w9TC(S9y^*>mz13k>Os3YgMB(d+cO%zsCS1Q;C7?`z_}uwnP5DbB+CofvO(t#CAN*|+Z_ zr`$6O_uGezS*^dCeLi#Zw$Z*xr587M|F)97I<25Md)f+y2TKYWrkrf?*Z#x1f0yvF lox4AH-d`H%{pi-8u(Q<>GUYA`0ro9IELZ+B-d|@}4**t1QO5uP literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_authors/.bzr/repository/indices/d2613fcfb5e48e79073b96270782f95c.rix b/test/repositories/bzr_with_authors/.bzr/repository/indices/d2613fcfb5e48e79073b96270782f95c.rix new file mode 100644 index 0000000000000000000000000000000000000000..215205dcbe86fd9a73b09ce2231227379809406b GIT binary patch literal 187 zcmZ?L4k=1aRd6p#EXYvs%u7kFP%z@k%TGy-FG@{|&&ezs`?Zj%_5KARa}Px=35xnl=hmmE*^$`o=<`r&G!zkS72Bv|917!Pus$MWv;jWNk96uw=d`OQnTVK7dw5$l{ScPO1Itg KjydAE$8`WgZeHyG literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_authors/.bzr/repository/pack-names b/test/repositories/bzr_with_authors/.bzr/repository/pack-names new file mode 100644 index 0000000000000000000000000000000000000000..16e3d82c6c909d6c539a4312331267983d0e743e GIT binary patch literal 197 zcmV;$06PCdD^zl2Wgtg#VQ^?5Np56icpx$gZf|5|Uvgz;UuK4eE-^SM3PLqD z3JPaqVljFOG&Bk`HVSy0OH(RIEiO?=%gjktC@n}yEJ;mKNUBuGP0XuQNGvVM$S*49 z0s!%J4G=;yG&TwfXJcY9dI~Z#G72;@H41o~m5@np!!Qg*19Znz^a2VjQA3zl;YhKY1NEG>ivmTvN*4sUc%R_=^zq^^O&cv8K`VtCI0#4(Z)u;F#6-b4-$n^k ziglGyE(qkZdh~o;7~dJ7x{b%z^mGK$6ytdshTkkAE3cOFNXfW(FX=IF?DyHPJ37bpNFyutG? z?IeVHT7~~%0bsj)&0Vn5$+gxuA^YYwP@3)Z$7X9yv$E*hJimu=E-Tsl44)UgeWXG% zG%^YbXJcY9dI~Z!I0`a3I0|^2MUP8v#2^fYr7k(eT!1Q&2O+E81Q~1#Ix`{4v+0F; z&63Wd3ok6&-~X9^-a@>mai?+3^ErrxU=GpU>2xDJX}CpLqSS3G4>-k~^Xd`~w{<3R zS0{C)l)9?bbzMvQ3A|0b8c)0B??Wmv!CdI&%z0SoqPjIZP7nG+EfLg!nz}%JZyM~- z24j2QRMcQyw~f+ui`bP6?!`=dT2dZg7PPD%^aao9LGK|y|7AK|_T`3ZOjx!KMj!nq zibIJmHs#e)3h_<^D-hn{k+dXB)XYhnx*;JC@(_D_o2Ued#& zk(iyG+3mlctgS@v!z7adf@oXO`DrpKVW3PTjHx(m?-4)cG+W%|?-#UajRnGSVI&)Sge$VeyuS4w;Z~+~5NRK&T*H zHvm4tb$!dn`{n5z^jSIyV7Xhi2tEVN&sN1 zidF>5MT0Xsv({d#K`p=eWI&g)K(rMTa#}9Sq-8iNE4xuI-57nJ)=YX-+*1y;v@H&| zuo%3rkyB~KGeQ{eDcV}( eyitB&zSR4yWkOx3Tai{@{HK4eE-^SM3PLk7 z3JPaqVljFOGB64;G75N{OXDg@EiO?=%gjmT0stD71N%ZTI0_19V`4FS3OEWd3V56Y z000000YWk|FbWE1V`4FS3NkP@3N$n@3V58Qk4sL&Fc5|-v71wH0aqSBlDI2Qz!lKM zo(XN9N^MelFYX7G*mPIK;@|zRPrjbwdp|JA0V?lp1qcQ*@Hy}EB`c#5@g{Gq_iF5F z-zHZoF9%rUYXz4dA|2rtHOz-ERyS%KZ0DhoAtC#ps~RetT0!)ZLnc0!LX|}Q>e+1h>PSa z0@Uydk3ZZwNXPYu{|`{`Z<=r9bA+@)F)}p@3TIoPltBjC*#EmG1GI+^sv!QH7OW3&h$oY1Mm(7)t1_}kyxX) zjc$8clEkV~l8Z_q)_KFVMWkcg#^B#oSoYVxAjD@sgPm}<(-vGh^Wdiq%Re_&GhO<5 zKQCNQ{UyEKi>#DQvRwZB&x7|;TTr%cmD56%O%9|RD*+KCirNXFzQp1e`rT(CLNYfu z3JPaqVljFOGBz^`Gd48}c$|ffTWZ5F5JjOY$p#!e)>u|VDeY%Jx`v>~Bv!45k>r?U z$z4V5w*UPYxD59m&gJXLdoC|22UQ)kME)dA3c=M%8HIe)qq-kHmd_=bUEB)lsnkQfC#-*hFV0;8H*Gd3AL> ztEG-9mmiCrQmP6wpacejA?J)A`Ot4XkeP0-xD*>_Ig|frHC+n;`}G~`d2?!`U)H;w z*V7fFS$++-a;zJ#_+1&Li?{8O^1Uge0&JxKV5}3vFm!@AGQeJ2t2IYs5Jis)wb4D2 XALJ%q)RlyMkFGl9k3`>!VtpG$T8X}D literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_authors/.bzr/repository/packs/d2613fcfb5e48e79073b96270782f95c.pack b/test/repositories/bzr_with_authors/.bzr/repository/packs/d2613fcfb5e48e79073b96270782f95c.pack new file mode 100644 index 0000000000000000000000000000000000000000..f33482995b44aaca80577e58465e79684107efcc GIT binary patch literal 919 zcmV;I18Dq0VR~UK4eE-^SM3PLn6 z3JPaqVljFOGB^q{Fba5_OA{(dEiO?=%gjktC@n}yEJ;n_0su;p2MR(mGdKzgXJcY9 zdI~Z!Gzv5{Fba5_m5)ts!Y~wsk-B@Q=mm_ho#)uBI6<#a`R6%={K~N#$h~^Mg49L3 zgT*XHni&eC=C`74%gMbXQ^O|g7t>Zw^Ul%)M=nGl#J+>n+TyX{yl|_yJ<(g;GK?H8KhcXJcY9dI~Z#I0`c{GYWW|O^-=# z#2^qwr7Sr`Ux3JfnY`+oAcjJoX@Lj150>)_@26osVBJ!_I#j@B z-V;= z5QP`Lh%ev>4E{q=l}cSz>ay#IpP?qkU;&Qn9JJ>tZnCes80jtMeQ)0A?;rhS-r zG8h5ao=HDVCM5{8V=rRhTk*bJmPzqY9QpK+Ct?1b2isOxNAoGu$6J(m?9>SL{jTc tpr-8<)*96W^`cdRB3;!|cdG7*;$T~r>qq_x9s8ISPoNF}KSR2sfkmEQs}%qM literal 0 HcmV?d00001 diff --git a/test/repositories/bzr_with_authors/test.txt b/test/repositories/bzr_with_authors/test.txt new file mode 100644 index 00000000..ea1cc16a --- /dev/null +++ b/test/repositories/bzr_with_authors/test.txt @@ -0,0 +1 @@ +test file updated by many authors diff --git a/test/unit/bzr_commits_test.rb b/test/unit/bzr_commits_test.rb index e34fd125..fab7e339 100644 --- a/test/unit/bzr_commits_test.rb +++ b/test/unit/bzr_commits_test.rb @@ -267,6 +267,32 @@ def test_commit_tokens_with_colon_character end end + def test_committer_and_author_name + with_bzr_repository('bzr_with_authors') do |bzr| + commits = [] + bzr.each_commit do |c| + commits << c + end + assert_equal 3, commits.size + + assert_equal 'Initial.', commits[0].message + assert_equal 'Abhay Mujumdar', commits[0].committer_name + assert_equal nil, commits[0].author_name + assert_equal nil, commits[0].author_email + + assert_equal 'Updated.', commits[1].message + assert_equal 'Abhay Mujumdar', commits[1].committer_name + assert_equal 'John Doe', commits[1].author_name + assert_equal 'johndoe@example.com', commits[1].author_email + + # When there are multiple authors, first one is captured. + assert_equal 'Updated by two authors.', commits[2].message + assert_equal 'test', commits[2].committer_name + assert_equal 'John Doe', commits[2].author_name + assert_equal 'johndoe@example.com', commits[2].author_email + end + end + protected def revision_ids diff --git a/test/unit/bzr_xml_parser_test.rb b/test/unit/bzr_xml_parser_test.rb index 2d24912f..4db9da9b 100644 --- a/test/unit/bzr_xml_parser_test.rb +++ b/test/unit/bzr_xml_parser_test.rb @@ -168,5 +168,65 @@ def test_ignore_kind_changed_xml assert_equal "M", c.diffs[2].action assert_equal ".bzrignore", c.diffs[2].path end + + def test_different_author_and_committer + xml = <<-XML + + + 1 + amujumdar@blackducksoftware.com-20111011152356-90nluwydpw9g4ncu + Abhay Mujumdar <amujumdar@blackducksoftware.com> + bzr_with_authors + Tue 2011-10-11 11:23:56 -0400 + + + + 2 + amujumdar@blackducksoftware.com-20111011152412-l9ehyruiezws32kj + + amujumdar@blackducksoftware.com-20111011152356-90nluwydpw9g4ncu + + Abhay Mujumdar <amujumdar@blackducksoftware.com> + + John Doe <johndoe@example.com> + + bzr_with_authors + Tue 2011-10-11 11:24:12 -0400 + + + + 3 + test@example.com-20111011162601-ud1nidteswfdbhbu + + amujumdar@blackducksoftware.com-20111011152412-l9ehyruiezws32kj + + test <test@example.com> + + Jim Beam <jimbeam@example.com> + Jane Smith <janesmith@example.com> + + bzr_with_authors + Tue 2011-10-11 12:26:01 -0400 + + + + XML + commits = BzrXmlParser.parse(xml) + c = commits[0] + assert_equal "Abhay Mujumdar", c.committer_name + assert_equal "amujumdar@blackducksoftware.com", c.committer_email + + c = commits[1] + assert_equal "Abhay Mujumdar", c.committer_name + assert_equal "amujumdar@blackducksoftware.com", c.committer_email + assert_equal "John Doe", c.author_name + assert_equal "johndoe@example.com", c.author_email + + c = commits[2] + assert_equal "test", c.committer_name + assert_equal "test@example.com", c.committer_email + assert_equal "Jim Beam", c.author_name + assert_equal "jimbeam@example.com", c.author_email + end end end From 19761daa7ca525c75bb18340544ad4489e0f704e Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Tue, 11 Oct 2011 13:16:36 -0400 Subject: [PATCH 112/219] Adds minor tweaks to the test. --- test/unit/bzr_xml_parser_test.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/unit/bzr_xml_parser_test.rb b/test/unit/bzr_xml_parser_test.rb index 4db9da9b..21eaa4bc 100644 --- a/test/unit/bzr_xml_parser_test.rb +++ b/test/unit/bzr_xml_parser_test.rb @@ -209,6 +209,17 @@ def test_different_author_and_committer Tue 2011-10-11 12:26:01 -0400 + + 4 + test@example.com-20111011162601-dummyrevision + + test@example.com-20111011162601-ud1nidteswfdbhbu + + test <test@example.com> + bzr_with_authors + Tue 2011-10-11 12:28:01 -0400 + + XML commits = BzrXmlParser.parse(xml) @@ -227,6 +238,12 @@ def test_different_author_and_committer assert_equal "test@example.com", c.committer_email assert_equal "Jim Beam", c.author_name assert_equal "jimbeam@example.com", c.author_email + + c = commits[3] + assert_equal "test", c.committer_name + assert_equal "test@example.com", c.committer_email + assert_equal nil, c.author_name + assert_equal nil, c.author_email end end end From 5a9e88f40f5b0dce99187ebf413302adcd1c51c8 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Tue, 11 Oct 2011 11:10:44 -0700 Subject: [PATCH 113/219] OTWO-1043 Fixes :after functionality in BzrAdapter If the commit specified by the :after option was a merge commit, then the BzrAdapter would incorrectly return some commits that precede the :after commit. Bzr does not natively support a "show me all commits after X" option. Thus, we request all commits *beginning* with X, then attempt to remove X itself from the result set. The problem here is that if X is a merge commit, then the Bzr log will include not just X but also all of the branch commits brought in by X. These branch commits will be emitted by the BzrXmlParser before X. So rather than simply delete X from the result set, we now delete X *and all prior commits* from the result set. --- lib/scm/adapters/bzr/commits.rb | 40 +++++++++----------- test/unit/bzr_commits_test.rb | 66 +++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 23 deletions(-) diff --git a/lib/scm/adapters/bzr/commits.rb b/lib/scm/adapters/bzr/commits.rb index 72cffc0e..863744d0 100644 --- a/lib/scm/adapters/bzr/commits.rb +++ b/lib/scm/adapters/bzr/commits.rb @@ -8,16 +8,7 @@ def commit_count(opts={}) # Return the list of commit tokens following +after+. def commit_tokens(opts={}) - tokens = commits(opts).map { |c| c.token } - - # Bzr returns everything after *and including* after. - # We want to exclude it. - after = opts[:after] - if tokens.any? && tokens.first == after - tokens[1..-1] - else - tokens - end + commits(opts).map(&:token) end # Returns a list of shallow commits (i.e., the diffs are not populated). @@ -30,11 +21,11 @@ def commits(opts={}) log = run("#{rev_list_command(opts)} | cat") a = Scm::Parsers::BzrXmlParser.parse(log) - if a.any? && a.first.token == after - a[1..-1] - else - a - end + if after && i = a.index { |commit| commit.token == after } + a[(i+1)..-1] + else + a + end end # Returns a single commit, including its diffs @@ -48,14 +39,17 @@ def verbose_commit(token) # This is designed to prevent excessive RAM usage when we # encounter a massive repository. Only a single commit is ever # held in memory at once. - def each_commit(opts={}) - after = opts[:after] - open_log_file(opts) do |io| - Scm::Parsers::BzrXmlParser.parse(io) do |commit| - yield remove_directories(commit) if block_given? && commit.token != after - end - end - end + def each_commit(opts={}) + after = opts[:after] + skip_commits = !!after # Don't emit any commits until the 'after' resume point passes + + open_log_file(opts) do |io| + Scm::Parsers::BzrXmlParser.parse(io) do |commit| + yield remove_directories(commit) if block_given? && !skip_commits + skip_commits = false if commit.token == after + end + end + end # Ohloh tracks only files, not directories. This function removes directories # from the commit diffs. diff --git a/test/unit/bzr_commits_test.rb b/test/unit/bzr_commits_test.rb index fab7e339..edc2c654 100644 --- a/test/unit/bzr_commits_test.rb +++ b/test/unit/bzr_commits_test.rb @@ -19,6 +19,13 @@ def test_commit_count_with_branches end end + def test_commit_count_after_merge + with_bzr_repository('bzr_with_branch') do |bzr| + last_commit = bzr.commits.last + assert_equal 0, bzr.commit_count(:trunk_only => false, :after => last_commit.token) + end + end + def test_commit_count_trunk_only with_bzr_repository('bzr_with_branch') do |bzr| # Only 3 commits are on main line @@ -35,6 +42,20 @@ def test_commit_tokens_after end end + def test_commit_tokens_after_merge + with_bzr_repository('bzr_with_branch') do |bzr| + last_commit = bzr.commits.last + assert_equal [], bzr.commit_tokens(:trunk_only => false, :after => last_commit.token) + end + end + + def test_commit_tokens_after_nested_merge + with_bzr_repository('bzr_with_nested_branches') do |bzr| + last_commit = bzr.commits.last + assert_equal [], bzr.commit_tokens(:trunk_only => false, :after => last_commit.token) + end + end + def test_commit_tokens_trunk_only_false # Funny business with commit ordering has been fixed by BzrXmlParser. # Now we always see branch commits before merge commit. @@ -112,6 +133,20 @@ def test_commits_trunk_only_true end end + def test_commits_after_merge + with_bzr_repository('bzr_with_branch') do |bzr| + last_commit = bzr.commits.last + assert_equal [], bzr.commits(:trunk_only => false, :after => last_commit.token) + end + end + + def test_commits_after_nested_merge + with_bzr_repository('bzr_with_nested_branches') do |bzr| + last_commit = bzr.commits.last + assert_equal [], bzr.commits(:trunk_only => false, :after => last_commit.token) + end + end + def test_nested_branches_commits_trunk_only_false with_bzr_repository('bzr_with_nested_branches') do |bzr| assert_equal [ @@ -206,6 +241,37 @@ def test_each_commit_trunk_only_true end end + def test_each_commit_after_merge + with_bzr_repository('bzr_with_branch') do |bzr| + last_commit = bzr.commits.last + + commits = [] + bzr.each_commit(:trunk_only => false, :after => last_commit.token) { |c| commits << c } + assert_equal [], commits + end + end + + def test_each_commit_after_nested_merge_at_tip + with_bzr_repository('bzr_with_nested_branches') do |bzr| + last_commit = bzr.commits.last + + commits = [] + bzr.each_commit(:trunk_only => false, :after => last_commit.token) { |c| commits << c } + assert_equal [], commits + end + end + + def test_each_commit_after_nested_merge_not_at_tip + with_bzr_repository('bzr_with_nested_branches') do |bzr| + last_commit = bzr.commits.last + next_to_last_commit = bzr.commits[-2] + + yielded_commits = [] + bzr.each_commit(:trunk_only => false, :after => next_to_last_commit.token) { |c| yielded_commits << c } + assert_equal [last_commit.token], yielded_commits.map(&:token) + end + end + def test_nested_branches_each_commit_trunk_only_false with_bzr_repository('bzr_with_nested_branches') do |bzr| commits = [] From aa671781732fdddd87008d993e6001f292992f9d Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Tue, 11 Oct 2011 14:54:56 -0400 Subject: [PATCH 114/219] Removes unused StringIO objects. --- lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb b/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb index 742cbd42..514b2130 100644 --- a/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb +++ b/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb @@ -1,6 +1,5 @@ require 'rubygems' require 'open4' -require 'stringio' class BzrPipeClient def initialize(repository_url) @@ -25,9 +24,6 @@ def parent_tokens(revision) end def send_command(cmd) - outbuf = StringIO.new - errbuf = StringIO.new - # send the command @stdin.puts cmd @stdin.flush From 4593645dec62171061230a00f82aff7ba880270b Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Tue, 11 Oct 2011 14:59:27 -0400 Subject: [PATCH 115/219] Makes IPC commands less-cryptic. --- lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb | 4 ++-- lib/scm/adapters/bzrlib/bzrlib_pipe_server.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb b/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb index 514b2130..aece32f7 100644 --- a/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb +++ b/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb @@ -13,14 +13,14 @@ def start end def open_repository - send_command("REP_OPEN|#{@repository_url}") + send_command("REPO_OPEN|#{@repository_url}") end def cat_file(revision, file) send_command("CAT_FILE|#{revision}|#{file}") end def parent_tokens(revision) - send_command("PAR_TKNS|#{revision}").split('|') + send_command("PARENT_TOKENS|#{revision}").split('|') end def send_command(cmd) diff --git a/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py b/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py index 53acb91f..24b692cb 100644 --- a/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py +++ b/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py @@ -61,7 +61,7 @@ def exit_delayed(status, delay=1): def command_loop(): while True: cmd = Command(sys.stdin.readline()) - if cmd.get_action() == 'REP_OPEN': + if cmd.get_action() == 'REPO_OPEN': commander = BzrPipeServer(cmd.get_arg(1)) send_success() elif cmd.get_action() == 'CAT_FILE': @@ -71,7 +71,7 @@ def command_loop(): else: send_success(len(content)) send_data(content) - elif cmd.get_action() == 'PAR_TKNS': + elif cmd.get_action() == 'PARENT_TOKENS': tokens = commander.get_parent_tokens(cmd.get_arg(1)) tokens = '|'.join(tokens) send_success(len(tokens)) From 8383f6d96f028e5c61a465fdbaaa06bc0cfc7ef9 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Tue, 11 Oct 2011 15:57:54 -0400 Subject: [PATCH 116/219] Removes unnecessary require. --- lib/scm/adapters/bzrlib_adapter.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/scm/adapters/bzrlib_adapter.rb b/lib/scm/adapters/bzrlib_adapter.rb index 7195b74a..5cfdb342 100644 --- a/lib/scm/adapters/bzrlib_adapter.rb +++ b/lib/scm/adapters/bzrlib_adapter.rb @@ -1,5 +1,4 @@ require 'rubygems' -require 'rubypython' require 'lib/scm/adapters/bzrlib/bzrlib_pipe_client' module Scm::Adapters From 5796ef14f496d357bba008e456d39b6740c80937 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Wed, 12 Oct 2011 16:11:15 -0400 Subject: [PATCH 117/219] Adds relevant tests from BzrParser tests. --- lib/scm/parsers/bzr_xml_parser.rb | 27 +++++-- test/unit/bzr_xml_parser_test.rb | 117 ++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+), 6 deletions(-) diff --git a/lib/scm/parsers/bzr_xml_parser.rb b/lib/scm/parsers/bzr_xml_parser.rb index 1d17978b..c2261239 100644 --- a/lib/scm/parsers/bzr_xml_parser.rb +++ b/lib/scm/parsers/bzr_xml_parser.rb @@ -110,17 +110,18 @@ def strip_trailing_asterisk(path) end def remove_dupes(diffs) + BzrXmlParser.remove_dupes(diffs) # Bazaar may report that a file was added and modified in a single commit. # Reduce these cases to a single 'A' action. - diffs.delete_if do |d| - d.action == 'M' && diffs.select { |x| x.path == d.path && x.action == 'A' }.any? - end + #diffs.delete_if do |d| + # d.action == 'M' && diffs.select { |x| x.path == d.path && x.action == 'A' }.any? + #end # Bazaar may report that a file was both deleted and added in a single commit. # Reduce these cases to a single 'M' action. - diffs.each do |d| - d.action = 'M' if diffs.select { |x| x.path == d.path }.size > 1 - end.uniq + #diffs.each do |d| + # d.action = 'M' if diffs.select { |x| x.path == d.path }.size > 1 + #end.uniq end end @@ -137,5 +138,19 @@ def self.internal_parse(buffer, opts) def self.scm 'bzr' end + + def self.remove_dupes(diffs) + # Bazaar may report that a file was added and modified in a single commit. + # Reduce these cases to a single 'A' action. + diffs.delete_if do |d| + d.action == 'M' && diffs.select { |x| x.path == d.path && x.action == 'A' }.any? + end + + # Bazaar may report that a file was both deleted and added in a single commit. + # Reduce these cases to a single 'M' action. + diffs.each do |d| + d.action = 'M' if diffs.select { |x| x.path == d.path }.size > 1 + end.uniq + end end end diff --git a/test/unit/bzr_xml_parser_test.rb b/test/unit/bzr_xml_parser_test.rb index 21eaa4bc..b69360a9 100644 --- a/test/unit/bzr_xml_parser_test.rb +++ b/test/unit/bzr_xml_parser_test.rb @@ -245,5 +245,122 @@ def test_different_author_and_committer assert_equal nil, c.author_name assert_equal nil, c.author_email end + + def test_rename + xml = <<-XML + + + 10 + test@example.com-20110725174345-brbpkwumeh07aoh8 + + amujumdar@blackducksoftware.com-20110722185038-e0i4d1mdxwpipxc4 + + test <test@example.com> + myproject + Mon 2011-07-25 13:43:45 -0400 + + + + subdir/test_b.txt + + + + + XML + commits = BzrXmlParser.parse(xml) + assert_equal 1, commits.size + assert_equal 2, commits.first.diffs.size + assert_equal 'D', commits.first.diffs.first.action + assert_equal 'test1.txt', commits.first.diffs.first.path + + assert_equal 'A', commits.first.diffs.last.action + assert_equal 'subdir/test_b.txt', commits.first.diffs.last.path + end + + def test_remove_dupes_add_remove + diffs = BzrXmlParser.remove_dupes([ Scm::Diff.new(:action => "A", :path => "foo"), + Scm::Diff.new(:action => "D", :path => "foo") ]) + assert_equal 1, diffs.size + assert_equal 'M', diffs.first.action + assert_equal 'foo', diffs.first.path + end + + # A complex delete/rename/modify test. + # Removed test_a.txt, Renamed test3.txt to test_a.txt, edited test_a.txt + # + # This is what Ohloh expects to see: + # + # D test3.txt + # M test_a.txt + # + def test_complex_rename + xml = <<-XML + + + 11 + test@example.com-20111012191732-h3bt3lp6l38vbm9v + + test@example.com-20110725174345-brbpkwumeh07aoh8 + + test <test@example.com> + myproject + Wed 2011-10-12 15:17:32 -0400 + + + + test_a.txt + + + test_a.txt + + + test_a.txt + + + + + XML + diffs = BzrXmlParser.parse(xml).first.diffs + diffs.sort! { |a,b| a.action <=> b.action } + assert_equal 2, diffs.size + assert_equal 'D', diffs.first.action + assert_equal 'test3.txt', diffs.first.path + assert_equal 'M', diffs.last.action + assert_equal 'test_a.txt', diffs.last.path + end + + # This test-case also tests rename and modify in the same commit. + # A rename and modify should result in a DELETE and an ADD. + def test_strip_trailing_asterisk_from_executables + xml = <<-XML + + + 14 + test@example.com-20111012195747-seei62z2wmefjhmo + + test@example.com-20111012195606-0shla0kf4e8hq4mq + + test <test@example.com> + myproject + Wed 2011-10-12 15:57:47 -0400 + + + + renamed_arch + + + renamed_arch* + + + + + XML + diffs = BzrXmlParser.parse(xml).first.diffs + diffs.sort! { |a,b| a.action <=> b.action } + assert_equal 'A', diffs[0].action + assert_equal 'renamed_arch', diffs[0].path + assert_equal 'D', diffs[1].action + assert_equal 'arch', diffs[1].path + end end end From 4dcb7a6a83a444534f42e0a4a7108f3c684a28b4 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Thu, 13 Oct 2011 12:37:37 -0400 Subject: [PATCH 118/219] OTWO-1048 - Captures committer/author name/email correctly. --- lib/scm/parsers/bzr_xml_parser.rb | 31 ++++++++++++---------- test/unit/bzr_xml_parser_test.rb | 43 +++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 14 deletions(-) diff --git a/lib/scm/parsers/bzr_xml_parser.rb b/lib/scm/parsers/bzr_xml_parser.rb index c2261239..4a34928f 100644 --- a/lib/scm/parsers/bzr_xml_parser.rb +++ b/lib/scm/parsers/bzr_xml_parser.rb @@ -46,10 +46,12 @@ def tag_end(name) when 'message' @commit.message = @cdata when 'committer' - @commit.committer_name = @text[/(.+?)(\s+<(.+)>)/, 1] - @commit.committer_email = @text[/(.+?)(\s+<(.+)>)/, 3] + committer = BzrXmlParser.capture_name(@text) + @commit.committer_name = committer[0] + @commit.committer_email = committer[1] when 'author' - @authors << {:author_name => @text[/(.+?)(\s+<(.+)>)/, 1], :author_email => @text[/(.+?)(\s+<(.+)>)/, 3] } + author = BzrXmlParser.capture_name(@text) + @authors << {:author_name => author[0], :author_email => author[1]} when 'timestamp' @commit.committer_date = Time.parse(@text) when 'file' @@ -111,22 +113,12 @@ def strip_trailing_asterisk(path) def remove_dupes(diffs) BzrXmlParser.remove_dupes(diffs) - # Bazaar may report that a file was added and modified in a single commit. - # Reduce these cases to a single 'A' action. - #diffs.delete_if do |d| - # d.action == 'M' && diffs.select { |x| x.path == d.path && x.action == 'A' }.any? - #end - - # Bazaar may report that a file was both deleted and added in a single commit. - # Reduce these cases to a single 'M' action. - #diffs.each do |d| - # d.action = 'M' if diffs.select { |x| x.path == d.path }.size > 1 - #end.uniq end end class BzrXmlParser < Parser + NAME_REGEX = /^(.+?)(\s+<(.+)>\s*)?$/ def self.internal_parse(buffer, opts) buffer = '' if buffer.is_a?(StringIO) and buffer.length < 2 begin @@ -152,5 +144,16 @@ def self.remove_dupes(diffs) d.action = 'M' if diffs.select { |x| x.path == d.path }.size > 1 end.uniq end + + # Bazaar expects committer/author to be specified in this format + # Name , or John Doe + # However, we find many variations in the real world including + # ones where only email is specified as name. + def self.capture_name(text) + parts = text.match(NAME_REGEX).to_a + name = parts[1] || parts[0] + email = parts[3] + [name, email] + end end end diff --git a/test/unit/bzr_xml_parser_test.rb b/test/unit/bzr_xml_parser_test.rb index b69360a9..847be7b6 100644 --- a/test/unit/bzr_xml_parser_test.rb +++ b/test/unit/bzr_xml_parser_test.rb @@ -362,5 +362,48 @@ def test_strip_trailing_asterisk_from_executables assert_equal 'D', diffs[1].action assert_equal 'arch', diffs[1].path end + + def test_committer_name_capture + name, email = BzrXmlParser.capture_name('John') + assert_equal name, 'John' + assert_equal email, nil + assert_equal ['John Doe', nil], BzrXmlParser.capture_name('John Doe') + assert_equal ['John Doe jdoe@example.com', nil], BzrXmlParser.capture_name('John Doe jdoe@example.com') + assert_equal ['John Doe ', nil], BzrXmlParser.capture_name('John Doe jdoe@example.com>') + assert_equal ['John Doe', 'jdoe@example.com'], BzrXmlParser.capture_name('John Doe ') + assert_equal ['John Doe', 'jdoe@example.com'], BzrXmlParser.capture_name('John Doe ') + assert_equal ['jdoe@example.com', nil], BzrXmlParser.capture_name('jdoe@example.com') + xml = <<-XML + + + 15 + a@b.com-20111013152207-q8uec9pp1330gfbh + + test@example.com-20111012195747-seei62z2wmefjhmo + + a@b.com + + author@c.com + + myproject + Thu 2011-10-13 11:22:07 -0400 + + + + test_a.txt + + + + + XML + c = BzrXmlParser.parse(xml).first + assert_equal 'M', c.diffs.first.action + assert_equal 'test_a.txt', c.diffs.first.path + assert_equal 'a@b.com', c.committer_name + assert_equal nil, c.committer_email + assert_equal 'author@c.com', c.author_name + assert_equal nil, c.author_email + end end end From 4cef2828300838825eed41928bf18bf66cd927f9 Mon Sep 17 00:00:00 2001 From: jared Date: Mon, 21 Nov 2011 23:53:52 +0100 Subject: [PATCH 119/219] updated readme with markdown syntax and instructions for installing the patched xmloutput plugin for bazaar --- README | 51 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/README b/README index 533d2eb4..6ae5aa42 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -= Ohloh SCM +# Ohloh SCM The Ohloh source control management library @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . -== Overview +## Overview Ohloh SCM is an abstraction layer for source control management systems, allowing an application to interoperate with various SCMs using a @@ -25,7 +25,7 @@ single interface. It was originally developed at Ohloh, and is used to generate the reports at www.ohloh.net. -== System Requirements +## System Requirements Ohloh SCM is developed on Mac OS X 10.5 and Ubuntu 6.06 LTS. Other Linux environments should also work, but your mileage may vary. @@ -47,16 +47,43 @@ hg 1.1.2 If you are using CVS instead of CVSNT, you can potentially try creating a shell alias or symlink mapping 'cvsnt' to 'cvs'. -== Running +## Running + +Ensure that cvsnt, svn, svnadmin, svnsync, git, and hg are all on your path. You'll also need to ensure that you have the xmloutput plugin installed for bazaar. + +### Installing The XmlOutput Plugin + $ cd ~ + $ mkdir .bazaar + $ cd .bazaar + $ mkdir plugins + $ cd plugins + +Now checkout the latest version of the xmloutput plugin (0.8.8 as of 11/21/2011). + + $ bzr branch lp:~amujumdar/bzr-xmloutput/emit_authors + +The default checkout directory is poorly named and bazaar will complain about this unless it is renamed. + + $ mv emit_authors xmloutput + +Now you just need to install the xmloutput plugin + + $ cd xmloutput + $ python setup.py build_ext -i + +Verify that the plugin was installed correctly + + $ bzr plugins + +You should see some text like "xmloutput 0.8.8" -Ensure that cvsnt, svn, svnadmin, svnsync, git, and hg are all on your path. Then you can run the unit tests: -$ rake + $ rake You can load the library into your own Ruby application by requiring lib/scm.rb. -= Functionality +# Functionality For each tracked repository, Ohloh uses the SCM library to maintain a private local mirror. The SCM library hides the differences between source control @@ -74,27 +101,23 @@ tasks on the local mirror: 1. Pull changes -- From a remote repository URL, pull any changes to the local mirror. This step may involve conversion from one system to another. - 2. Push changes -- From the local mirror, push any changes to another Ohloh server. This is required to create backup copies and perform load balancing on the Ohloh cluster, and typically occurs over ssh. - 3. Commit log -- Given the last known commit, report the list of new commits, if any, including their diffs. - 4. Cat file or parent -- Given a commit, return either the contents of a single file, or that file's previous contents. - 5. Export tree -- Given a commit, export the entire contents of the source tree to a specified temp directory. The adapter must also implement validation routines used to filter user inputs and confirm the presence of the remote server. -= Contact Ohloh +# Contact Ohloh For more information visit the Ohloh website: - http://labs.ohloh.net +[Ohloh Labs](http://labs.ohloh.net) You can reach Ohloh via email at: - info@ohloh.net +[info@ohloh.net](mailto:info@ohloh.net) From f0e7ea626a1252e126ac309f1327fb689c7e46a4 Mon Sep 17 00:00:00 2001 From: jared Date: Tue, 22 Nov 2011 00:00:26 +0100 Subject: [PATCH 120/219] Renamed the readme file I renamed the readme file so that GitHub will display it nicely. --- README => README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename README => README.md (100%) diff --git a/README b/README.md similarity index 100% rename from README rename to README.md From 29c311d8073b04bcb8142bd8cf19102be21ea400 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Wed, 30 Nov 2011 12:55:47 -0800 Subject: [PATCH 121/219] OTWO-415 First pass at using python library for hg cat --- .gitignore | 1 + lib/scm.rb | 1 + lib/scm/adapters/hglib/cat_file.rb | 9 ++++ lib/scm/adapters/hglib/client.rb | 52 ++++++++++++++++++ lib/scm/adapters/hglib/server.py | 86 ++++++++++++++++++++++++++++++ lib/scm/adapters/hglib_adapter.rb | 24 +++++++++ test/test_helper.rb | 4 ++ test/unit/hglib_cat_file_test.rb | 47 ++++++++++++++++ 8 files changed, 224 insertions(+) create mode 100644 lib/scm/adapters/hglib/cat_file.rb create mode 100644 lib/scm/adapters/hglib/client.rb create mode 100644 lib/scm/adapters/hglib/server.py create mode 100644 lib/scm/adapters/hglib_adapter.rb create mode 100644 test/unit/hglib_cat_file_test.rb diff --git a/.gitignore b/.gitignore index 3bc5d675..d411dd7f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.swp *.pyc pkg/ +*.cache diff --git a/lib/scm.rb b/lib/scm.rb index a0f5f1b3..60b014c8 100644 --- a/lib/scm.rb +++ b/lib/scm.rb @@ -16,6 +16,7 @@ module Scm require 'lib/scm/adapters/svn_chain_adapter' require 'lib/scm/adapters/git_adapter' require 'lib/scm/adapters/hg_adapter' +require 'lib/scm/adapters/hglib_adapter' require 'lib/scm/adapters/bzr_adapter' require 'lib/scm/adapters/bzrlib_adapter' require 'lib/scm/adapters/factory' diff --git a/lib/scm/adapters/hglib/cat_file.rb b/lib/scm/adapters/hglib/cat_file.rb new file mode 100644 index 00000000..180e6fe5 --- /dev/null +++ b/lib/scm/adapters/hglib/cat_file.rb @@ -0,0 +1,9 @@ +module Scm::Adapters + class HglibAdapter < HgAdapter + + def cat(revision, path) + hg_client.cat_file(revision, path) + end + + end +end diff --git a/lib/scm/adapters/hglib/client.rb b/lib/scm/adapters/hglib/client.rb new file mode 100644 index 00000000..8efe01c9 --- /dev/null +++ b/lib/scm/adapters/hglib/client.rb @@ -0,0 +1,52 @@ +require 'rubygems' +require 'open4' + +class HglibClient + def initialize(repository_url) + @repository_url = repository_url + @py_script = File.dirname(__FILE__) + '/server.py' + end + + def start + @pid, @stdin, @stdout, @stderr = Open4::popen4 "python #{@py_script}" + open_repository + end + + def open_repository + send_command("REPO_OPEN\t#{@repository_url}") + end + + def cat_file(revision, file) + send_command("CAT_FILE\t#{revision}\t#{file}") + end + + def parent_tokens(revision) + send_command("PARENT_TOKENS\t#{revision}").split("\t") + end + + def send_command(cmd) + # send the command + @stdin.puts cmd + @stdin.flush + + # get status on stderr, first letter indicates state, + # remaing value indicates length of the file content + status = @stderr.read(10) + flag = status[0,1] + size = status[1,9].to_i + if flag == 'F' + return nil + elsif flag == 'E' + error = @stdout.read(size) + raise RuntimeError.new("Exception in server process\n#{error}") + end + + # read content from stdout + return @stdout.read(size) + end + + def shutdown + send_command("QUIT") + Process.waitpid(@pid, Process::WNOHANG) + end +end diff --git a/lib/scm/adapters/hglib/server.py b/lib/scm/adapters/hglib/server.py new file mode 100644 index 00000000..c829cea7 --- /dev/null +++ b/lib/scm/adapters/hglib/server.py @@ -0,0 +1,86 @@ +import sys +import time +import traceback + +from mercurial import ui, hg + +class HglibPipeServer: + def __init__(self, repository_url): + self.ui = ui.ui() + self.repository = hg.repository(self.ui, repository_url) + + def get_file_content(self, filename, revision): + c = self.repository.changectx(revision) + fc = c[filename] + contents = fc.data() + return contents + + def get_parent_tokens(self, revision): + return None + +class Command: + def __init__(self, line): + self.args = line.rstrip().split('\t') + + def get_action(self): + return self.args[0] + + def get_arg(self, num): + return self.args[num] + +def send_status(code, data_len): + sys.stderr.write('%s%09d' % (code, data_len)) + sys.stderr.flush() + +def send_success(data_len=0): + send_status('T', data_len) + +def send_failure(data_len=0): + send_status('F', data_len) + +def send_error(data_len=0): + send_status('E', data_len) + +def send_data(result): + sys.stdout.write(result) + sys.stdout.flush() + +def exit_delayed(status, delay=1): + time.sleep(delay) + sys.exit(status) + +def command_loop(): + while True: + cmd = Command(sys.stdin.readline()) + if cmd.get_action() == 'REPO_OPEN': + commander = HglibPipeServer(cmd.get_arg(1)) + send_success() + elif cmd.get_action() == 'CAT_FILE': + content = commander.get_file_content(cmd.get_arg(2), cmd.get_arg(1)) + if content == None: + send_failure() + else: + send_success(len(content)) + send_data(content) + elif cmd.get_action() == 'PARENT_TOKENS': + tokens = commander.get_parent_tokens(cmd.get_arg(1)) + tokens = '|'.join(tokens) + send_success(len(tokens)) + send_data(tokens) + elif cmd.get_action() == 'QUIT': + send_success() + exit_delayed(status=0) + else: + error = "Invalid Command - %s" % cmd.get_action() + send_error(len(error)) + send_data(error) + exit_delayed(status=1) + +if __name__ == "__main__": + try: + command_loop() + except: + exc_trace = traceback.format_exc() + send_error(len(exc_trace)) + send_data(exc_trace) + exit_delayed(status=1) diff --git a/lib/scm/adapters/hglib_adapter.rb b/lib/scm/adapters/hglib_adapter.rb new file mode 100644 index 00000000..6520a94c --- /dev/null +++ b/lib/scm/adapters/hglib_adapter.rb @@ -0,0 +1,24 @@ +require 'rubygems' +require 'lib/scm/adapters/hglib/client' + +module Scm::Adapters + class HglibAdapter < HgAdapter + + def setup + hg_client = HglibClient.new(url) + hg_client.start + hg_client + end + + def hg_client + @hg_client ||= setup + end + + def cleanup + @hg_client && @hg_client.shutdown + end + + end +end + +require 'lib/scm/adapters/hglib/cat_file' diff --git a/test/test_helper.rb b/test/test_helper.rb index 484de92b..797d2f69 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -93,6 +93,10 @@ def with_hg_repository(name) with_repository(Scm::Adapters::HgAdapter, name) { |hg| yield hg } end + def with_hglib_repository(name) + with_repository(Scm::Adapters::HglibAdapter, name) { |hg| yield hg } + end + def with_bzr_repository(name) with_repository(Scm::Adapters::BzrAdapter, name) { |bzr| yield bzr } end diff --git a/test/unit/hglib_cat_file_test.rb b/test/unit/hglib_cat_file_test.rb new file mode 100644 index 00000000..1c249dd7 --- /dev/null +++ b/test/unit/hglib_cat_file_test.rb @@ -0,0 +1,47 @@ +require File.dirname(__FILE__) + '/../test_helper' + +module Scm::Adapters + class HglibCatFileTest < Scm::Test + + def test_cat_file + with_hglib_repository('hg') do |hg| +expected = <<-EXPECTED +/* Hello, World! */ + +/* + * This file is not covered by any license, especially not + * the GNU General Public License (GPL). Have fun! + */ + +#include +main() +{ + printf("Hello, World!\\n"); +} +EXPECTED + + # The file was deleted in revision 468336c6671c. Check that it does not exist now, but existed in parent. + # assert_equal nil, hg.cat_file(Scm::Commit.new(:token => '75532c1e1f1d'), Scm::Diff.new(:path => 'helloworld.c')) + assert_equal expected, hg.cat_file_parent(Scm::Commit.new(:token => '75532c1e1f1d'), Scm::Diff.new(:path => 'helloworld.c')) + assert_equal expected, hg.cat_file(Scm::Commit.new(:token => '468336c6671c'), Scm::Diff.new(:path => 'helloworld.c')) + end + end + + # Ensure that we escape bash-significant characters like ' and & when they appear in the filename + def test_funny_file_name_chars + Scm::ScratchDir.new do |dir| + # Make a file with a problematic filename + funny_name = '#|file_name` $(&\'")#' + File.open(File.join(dir, funny_name), 'w') { |f| f.write "contents" } + + # Add it to an hg repository + `cd #{dir} && hg init && hg add * && hg commit -m test` + + # Confirm that we can read the file back + hg = HglibAdapter.new(:url => dir).normalize + assert_equal "contents", hg.cat_file(hg.head, Scm::Diff.new(:path => funny_name)) + end + end + + end +end From 20d25e2823a6f035fc53bfd07ec519e54d4dc0f3 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Wed, 30 Nov 2011 15:35:18 -0800 Subject: [PATCH 122/219] OTWO-415 Rake passes using HglibAdapter --- lib/scm/adapters/hglib/cat_file.rb | 9 ++++++-- lib/scm/adapters/hglib/client.rb | 10 ++++++++- lib/scm/adapters/hglib/head.rb | 9 ++++++++ lib/scm/adapters/hglib/server.py | 34 ++++++++++++++---------------- lib/scm/adapters/hglib_adapter.rb | 1 + test/unit/hglib_cat_file_test.rb | 2 +- test/unit/hglib_head_test.rb | 18 ++++++++++++++++ 7 files changed, 61 insertions(+), 22 deletions(-) create mode 100644 lib/scm/adapters/hglib/head.rb create mode 100644 test/unit/hglib_head_test.rb diff --git a/lib/scm/adapters/hglib/cat_file.rb b/lib/scm/adapters/hglib/cat_file.rb index 180e6fe5..d22e2ae5 100644 --- a/lib/scm/adapters/hglib/cat_file.rb +++ b/lib/scm/adapters/hglib/cat_file.rb @@ -1,9 +1,14 @@ module Scm::Adapters class HglibAdapter < HgAdapter - def cat(revision, path) - hg_client.cat_file(revision, path) + def cat_file(commit, diff) + hg_client.cat_file(commit.token, diff.path) end + def cat_file_parent(commit, diff) + tokens = parent_tokens(commit) + hg_client.cat_file(tokens.first, diff.path) if tokens.first + end + end end diff --git a/lib/scm/adapters/hglib/client.rb b/lib/scm/adapters/hglib/client.rb index 8efe01c9..65c414c9 100644 --- a/lib/scm/adapters/hglib/client.rb +++ b/lib/scm/adapters/hglib/client.rb @@ -17,7 +17,15 @@ def open_repository end def cat_file(revision, file) - send_command("CAT_FILE\t#{revision}\t#{file}") + begin + send_command("CAT_FILE\t#{revision}\t#{file}") + rescue RuntimeError => e + if e.message =~ /not found in manifest/ + return nil # File does not exist. + else + raise + end + end end def parent_tokens(revision) diff --git a/lib/scm/adapters/hglib/head.rb b/lib/scm/adapters/hglib/head.rb new file mode 100644 index 00000000..48ba2078 --- /dev/null +++ b/lib/scm/adapters/hglib/head.rb @@ -0,0 +1,9 @@ +module Scm::Adapters + class HglibAdapter < HgAdapter + + def parent_tokens(commit) + hg_client.parent_tokens(commit.token) + end + + end +end diff --git a/lib/scm/adapters/hglib/server.py b/lib/scm/adapters/hglib/server.py index c829cea7..fc01f3b2 100644 --- a/lib/scm/adapters/hglib/server.py +++ b/lib/scm/adapters/hglib/server.py @@ -16,7 +16,9 @@ def get_file_content(self, filename, revision): return contents def get_parent_tokens(self, revision): - return None + c = self.repository.changectx(revision) + parents = [p.hex() for p in c.parents() if p.hex() != '0000000000000000000000000000000000000000'] + return parents class Command: def __init__(self, line): @@ -45,42 +47,38 @@ def send_data(result): sys.stdout.write(result) sys.stdout.flush() -def exit_delayed(status, delay=1): - time.sleep(delay) - sys.exit(status) - def command_loop(): while True: - cmd = Command(sys.stdin.readline()) - if cmd.get_action() == 'REPO_OPEN': + s = sys.stdin.readline() + cmd = Command(s) + if s == '' or cmd.get_action() == 'QUIT': + sys.exit(0) + elif cmd.get_action() == 'REPO_OPEN': commander = HglibPipeServer(cmd.get_arg(1)) send_success() elif cmd.get_action() == 'CAT_FILE': - content = commander.get_file_content(cmd.get_arg(2), cmd.get_arg(1)) - if content == None: - send_failure() - else: + try: + content = commander.get_file_content(cmd.get_arg(2), cmd.get_arg(1)) send_success(len(content)) send_data(content) + except Exception: + send_failure() # Assume file not found elif cmd.get_action() == 'PARENT_TOKENS': tokens = commander.get_parent_tokens(cmd.get_arg(1)) - tokens = '|'.join(tokens) + tokens = '\n'.join(tokens) send_success(len(tokens)) send_data(tokens) - elif cmd.get_action() == 'QUIT': - send_success() - exit_delayed(status=0) else: error = "Invalid Command - %s" % cmd.get_action() send_error(len(error)) send_data(error) - exit_delayed(status=1) + sys.exit(1) if __name__ == "__main__": try: command_loop() - except: + except Exception: exc_trace = traceback.format_exc() send_error(len(exc_trace)) send_data(exc_trace) - exit_delayed(status=1) + sys.exit(1) diff --git a/lib/scm/adapters/hglib_adapter.rb b/lib/scm/adapters/hglib_adapter.rb index 6520a94c..0a153628 100644 --- a/lib/scm/adapters/hglib_adapter.rb +++ b/lib/scm/adapters/hglib_adapter.rb @@ -22,3 +22,4 @@ def cleanup end require 'lib/scm/adapters/hglib/cat_file' +require 'lib/scm/adapters/hglib/head' diff --git a/test/unit/hglib_cat_file_test.rb b/test/unit/hglib_cat_file_test.rb index 1c249dd7..b110d0a9 100644 --- a/test/unit/hglib_cat_file_test.rb +++ b/test/unit/hglib_cat_file_test.rb @@ -21,7 +21,7 @@ def test_cat_file EXPECTED # The file was deleted in revision 468336c6671c. Check that it does not exist now, but existed in parent. - # assert_equal nil, hg.cat_file(Scm::Commit.new(:token => '75532c1e1f1d'), Scm::Diff.new(:path => 'helloworld.c')) + assert_equal nil, hg.cat_file(Scm::Commit.new(:token => '75532c1e1f1d'), Scm::Diff.new(:path => 'helloworld.c')) assert_equal expected, hg.cat_file_parent(Scm::Commit.new(:token => '75532c1e1f1d'), Scm::Diff.new(:path => 'helloworld.c')) assert_equal expected, hg.cat_file(Scm::Commit.new(:token => '468336c6671c'), Scm::Diff.new(:path => 'helloworld.c')) end diff --git a/test/unit/hglib_head_test.rb b/test/unit/hglib_head_test.rb new file mode 100644 index 00000000..f10ed0ed --- /dev/null +++ b/test/unit/hglib_head_test.rb @@ -0,0 +1,18 @@ +require File.dirname(__FILE__) + '/../test_helper' + +module Scm::Adapters + class HgHeadTest < Scm::Test + + def test_head_and_parents + with_hglib_repository('hg') do |hg| + assert_equal '75532c1e1f1d', hg.head_token + assert_equal '75532c1e1f1de55c2271f6fd29d98efbe35397c4', hg.head.token + assert hg.head.diffs.any? # diffs should be populated + + assert_equal '468336c6671cbc58237a259d1b7326866afc2817', hg.parents(hg.head).first.token + assert hg.parents(hg.head).first.diffs.any? + end + end + + end +end From 50572a9d054c055e16033216644f101ac2a383bc Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Thu, 1 Dec 2011 10:30:06 -0800 Subject: [PATCH 123/219] Fixes "\n" vs "\t" error in server output --- lib/scm/adapters/hglib/server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scm/adapters/hglib/server.py b/lib/scm/adapters/hglib/server.py index fc01f3b2..aaa46f6f 100644 --- a/lib/scm/adapters/hglib/server.py +++ b/lib/scm/adapters/hglib/server.py @@ -65,7 +65,7 @@ def command_loop(): send_failure() # Assume file not found elif cmd.get_action() == 'PARENT_TOKENS': tokens = commander.get_parent_tokens(cmd.get_arg(1)) - tokens = '\n'.join(tokens) + tokens = '\t'.join(tokens) send_success(len(tokens)) send_data(tokens) else: From 7528067879c3ab50299cb087401a34b8e3686868 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Mon, 5 Dec 2011 13:55:28 -0800 Subject: [PATCH 124/219] OTWO-204 Allow spaces in Subversion file paths --- lib/scm/adapters/svn/validation.rb | 4 ++-- test/unit/svn_validation_test.rb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/scm/adapters/svn/validation.rb b/lib/scm/adapters/svn/validation.rb index 67d77757..d996401d 100644 --- a/lib/scm/adapters/svn/validation.rb +++ b/lib/scm/adapters/svn/validation.rb @@ -1,11 +1,11 @@ module Scm::Adapters class SvnAdapter < AbstractAdapter def self.url_regex - /^(file|http|https|svn):\/\/(\/)?[A-Za-z0-9_\-\.]+(:\d+)?(\/[A-Za-z0-9_\-\.\/\+%^~]*)?$/ + /^(file|http|https|svn):\/\/(\/)?[A-Za-z0-9_\-\.]+(:\d+)?(\/[A-Za-z0-9_\-\.\/\+%^~ ]*)?$/ end def self.public_url_regex - /^(http|https|svn):\/\/[A-Za-z0-9_\-\.]+(:\d+)?(\/[A-Za-z0-9_\-\.\/\+%^~]*)?$/ + /^(http|https|svn):\/\/[A-Za-z0-9_\-\.]+(:\d+)?(\/[A-Za-z0-9_\-\.\/\+%^~ ]*)?$/ end def normalize diff --git a/test/unit/svn_validation_test.rb b/test/unit/svn_validation_test.rb index d3b6ef32..4c610c1c 100644 --- a/test/unit/svn_validation_test.rb +++ b/test/unit/svn_validation_test.rb @@ -12,7 +12,6 @@ def test_rejected_urls [ nil, "", "foo", "http:/", "http:://", "http://", "sourceforge.net/svn/project/trunk", # missing a protocol prefix "http://robin@svn.sourceforge.net/", # must not include a username with the url - "http://svn.sourceforge.net/asdf/asdf/ malicious code", # no spaces allowed "/home/robin/cvs", # local file paths not allowed "git://kernel.org/whatever/linux.git", # git protocol is not allowed ":pserver:anonymous:@juicereceiver.cvs.sourceforge.net:/cvsroot/juicereceiver", # pserver is just wrong @@ -38,7 +37,8 @@ def test_accepted_urls "http://svn.gnome.org/svn/gtk+/trunk", # + character OK "http://svn.gnome.org", # no path, no trailing /, just a domain name is OK "http://brlcad.svn.sourceforge.net/svnroot/brlcad/rt^3/trunk", # a caret ^ is allowed - "http://www.thus.ch/~patrick/svn/pvalsecc" # ~ is allowed + "http://www.thus.ch/~patrick/svn/pvalsecc", # ~ is allowed + "http://franklinmath.googlecode.com/svn/trunk/Franklin Math", # space is allowed in path ].each do |url| # Accepted for both internal and public use [true, false].each do |p| From c02a79162985a3309c7f8ea5a17f31e642cbda64 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Tue, 20 Dec 2011 13:23:43 -0500 Subject: [PATCH 125/219] Fixes encoding issue for non-ascii file names. --- lib/scm/adapters/bzrlib/bzrlib_pipe_server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py b/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py index 24b692cb..57854392 100644 --- a/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py +++ b/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py @@ -12,7 +12,7 @@ def __init__(self, repository_url): def get_file_content(self, filename, revision): rev_spec = RevisionSpec.from_string(revision) tree = rev_spec.as_tree(self.branch) - file_id = tree.path2id(filename) + file_id = tree.path2id(unicode(filename, 'utf8')) if file_id == None: return None content = tree.get_file_text(file_id) From 62693053b7d077a35d771c4876ca2384548b5ffb Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Thu, 22 Dec 2011 13:53:16 -0500 Subject: [PATCH 126/219] OTWO-1177 Fixes non-ascii filename handling in BzrlibAdapter." Also adds an example file to test/repositories/bzr repository and a test. --- lib/scm/adapters/bzrlib/bzrlib_pipe_server.py | 2 +- .../bzr/.bzr/branch/last-revision | 2 +- test/repositories/bzr/.bzr/checkout/dirstate | Bin 1084 -> 1404 bytes .../62f9cada7c58bce361b9b852d180ff56.iix | Bin 0 -> 179 bytes .../62f9cada7c58bce361b9b852d180ff56.rix | Bin 0 -> 175 bytes .../62f9cada7c58bce361b9b852d180ff56.six | 5 +++++ .../62f9cada7c58bce361b9b852d180ff56.tix | Bin 0 -> 164 bytes .../bzr/.bzr/repository/pack-names | Bin 359 -> 409 bytes .../62f9cada7c58bce361b9b852d180ff56.pack | Bin 0 -> 809 bytes "test/repositories/bzr/C\303\251dric.txt" | 2 ++ test/unit/bzr_cat_file_test.rb | 12 ++++++++++++ test/unit/bzrlib_cat_file_test.rb | 12 ++++++++++++ 12 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 test/repositories/bzr/.bzr/repository/indices/62f9cada7c58bce361b9b852d180ff56.iix create mode 100644 test/repositories/bzr/.bzr/repository/indices/62f9cada7c58bce361b9b852d180ff56.rix create mode 100644 test/repositories/bzr/.bzr/repository/indices/62f9cada7c58bce361b9b852d180ff56.six create mode 100644 test/repositories/bzr/.bzr/repository/indices/62f9cada7c58bce361b9b852d180ff56.tix create mode 100644 test/repositories/bzr/.bzr/repository/packs/62f9cada7c58bce361b9b852d180ff56.pack create mode 100644 "test/repositories/bzr/C\303\251dric.txt" diff --git a/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py b/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py index 24b692cb..57854392 100644 --- a/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py +++ b/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py @@ -12,7 +12,7 @@ def __init__(self, repository_url): def get_file_content(self, filename, revision): rev_spec = RevisionSpec.from_string(revision) tree = rev_spec.as_tree(self.branch) - file_id = tree.path2id(filename) + file_id = tree.path2id(unicode(filename, 'utf8')) if file_id == None: return None content = tree.get_file_text(file_id) diff --git a/test/repositories/bzr/.bzr/branch/last-revision b/test/repositories/bzr/.bzr/branch/last-revision index 9a8027d9..a13831a2 100644 --- a/test/repositories/bzr/.bzr/branch/last-revision +++ b/test/repositories/bzr/.bzr/branch/last-revision @@ -1 +1 @@ -6 obnox@samba.org-20090204004942-73rnw0izen42f154 +7 test@example.com-20111222183733-y91if5npo3pe8ifs diff --git a/test/repositories/bzr/.bzr/checkout/dirstate b/test/repositories/bzr/.bzr/checkout/dirstate index 7643466d7cc833579e3e5d223468b67c1c491283..915a42979fab85afa8ecfd772a29295bd37c4ce7 100644 GIT binary patch delta 466 zcmdnP@rP@InvbEenSr^bfsut7S6*pud}>}vQD$nfm4X?UAwx-Oafw4}MPhD2PO4sV zey*;OfuW(Hk&%(1g|WG@v2LZMVP=|XUO~QbL8?V&TJgjJg?jUS4){!oXm_kVmqq3|tHh&WBf~6lEssl~j~4B*R$9&M`Bw&`mZlEa%I# zG$_wVEKM@bGBnmToSe;Qr~tIy(aivh!;I1$9X;I*K#B}V_Upp}Df9A@P@rFZ!kpoL y4fli@c>$}mFGM<&Y0hLRW<9XeTtl&$69`c#&OB%G9jHQg18fRIAqsCYCj$U9`-?RI delta 258 zcmeyvwTEMZnv|ufp@FHXnV|(&UTJQ8YF#m3fXDgP}Rl T)(Qe(vOWt?sS#01C0UaJGr3dC diff --git a/test/repositories/bzr/.bzr/repository/indices/62f9cada7c58bce361b9b852d180ff56.iix b/test/repositories/bzr/.bzr/repository/indices/62f9cada7c58bce361b9b852d180ff56.iix new file mode 100644 index 0000000000000000000000000000000000000000..b7998a5ae9a3da765b9c09455fdc15b8bc47ca39 GIT binary patch literal 179 zcmWNIK@Ni;5CFNBSMUK1yI_?=6Vpr6R~W2IYpOuNr0VO-VJ4Zw-0f*?5|3o#M?C#R zy8!OPL_;DsEOXxS4f&UjfficHmju3$FAk#*d!Ow(+B&3ng;E-cQcJ0g#;R4x|Kxm< z*XW?p%reF|%3DvnUE@OaE39P#07QgNwMtcof!Q@a1{JBBU1m%+=2Bn+IuLkOoc{qu CMl{6$ literal 0 HcmV?d00001 diff --git a/test/repositories/bzr/.bzr/repository/indices/62f9cada7c58bce361b9b852d180ff56.rix b/test/repositories/bzr/.bzr/repository/indices/62f9cada7c58bce361b9b852d180ff56.rix new file mode 100644 index 0000000000000000000000000000000000000000..61bda8a4c2fa50b55516d3c4db526df9f0ddbc3d GIT binary patch literal 175 zcmW;DOA3Q96hP68vx;m$$>&+kpdg);u0mpcX+!fP5vs1f(&0UDZ{{$juzNB2%^q>V zjR_jlf>S{|c~{qZ74(DqgdPLNe|n53ra7i}OlLgXVF19?1t|RiaqKi9 literal 0 HcmV?d00001 diff --git a/test/repositories/bzr/.bzr/repository/indices/62f9cada7c58bce361b9b852d180ff56.six b/test/repositories/bzr/.bzr/repository/indices/62f9cada7c58bce361b9b852d180ff56.six new file mode 100644 index 00000000..1206f930 --- /dev/null +++ b/test/repositories/bzr/.bzr/repository/indices/62f9cada7c58bce361b9b852d180ff56.six @@ -0,0 +1,5 @@ +Bazaar Graph Index 1 +node_ref_lists=0 +key_elements=1 +len=0 + diff --git a/test/repositories/bzr/.bzr/repository/indices/62f9cada7c58bce361b9b852d180ff56.tix b/test/repositories/bzr/.bzr/repository/indices/62f9cada7c58bce361b9b852d180ff56.tix new file mode 100644 index 0000000000000000000000000000000000000000..3719aa072a5a7c9d1bcb4c05dbe40e1c67d87752 GIT binary patch literal 164 zcmYkzF%H5Y6aY|GIRzJ>>E~B1Llfg-JVk@_H$^EWfNAULO`IIx@UG@#OcJ+b;w0{2 zpiKY|%RqgivG*>Q+$sK|y(dpIg&#eI4!9kXvsKxOR5bu7rJ%)A(@I;z>U6zM=Ka7Y opafPZmkVuXj-D#J%>U(#D0dBRJchVnq}Gj@u>%v05`dcXFB}Uo8vpK4eE-^SM3PLe6 zGYSeHiwFP!00002|CPK2mk;800092osr9G z!!Q&?_x=i@LRWFBt1HD4jYFXy67(c0v21MBar*Uj3ZdPmo7tV=Ff)g7N_{3JOyw;s zrW?*->-w(d3;;Oips+!#uNqR6dFXKnD#eK)kurclWTTl%O3JyiRc&Vk(Gr@{F#xoug>Uvwu_ z?HF8=W|x!swD6`a4d5wzN#1f`7&(P&a75e%Mw85=^|ZMWF|{%qxpF}dJL#*|<2 z!_3PG*JGG#4vaC*Icr5DM19rFP0BApEZDj!k(Nwgl~TZz<%2<#oV^Hbbi?th#dvGA zm`2O1UBt7yyA@f9@_w}BnqeC=) nJl5Wg@3bFovCw`1cZnylRF6!3h2H-Azf_+kvc2kQ0ssI-xng=h literal 0 HcmV?d00001 diff --git "a/test/repositories/bzr/C\303\251dric.txt" "b/test/repositories/bzr/C\303\251dric.txt" new file mode 100644 index 00000000..9d6265cc --- /dev/null +++ "b/test/repositories/bzr/C\303\251dric.txt" @@ -0,0 +1,2 @@ +first file +second line diff --git a/test/unit/bzr_cat_file_test.rb b/test/unit/bzr_cat_file_test.rb index 1924f368..93331684 100644 --- a/test/unit/bzr_cat_file_test.rb +++ b/test/unit/bzr_cat_file_test.rb @@ -19,6 +19,18 @@ def test_cat_file end end + def test_cat_file_non_ascii_name + with_bzr_repository('bzr') do |bzr| + expected = <<-EXPECTED +first file +second line +EXPECTED + assert_equal expected, + bzr.cat_file(Scm::Commit::new(:token => 7), + Scm::Diff.new(:path => "Cédric.txt")) + end + end + def test_cat_file_parent with_bzr_repository('bzr') do |bzr| expected = <<-EXPECTED diff --git a/test/unit/bzrlib_cat_file_test.rb b/test/unit/bzrlib_cat_file_test.rb index 1fe1e4b5..32b58ddd 100644 --- a/test/unit/bzrlib_cat_file_test.rb +++ b/test/unit/bzrlib_cat_file_test.rb @@ -19,6 +19,18 @@ def test_cat_file end end + def test_cat_file_non_ascii_name + with_bzrlib_repository('bzr') do |bzr| + expected = <<-EXPECTED +first file +second line +EXPECTED + assert_equal expected, + bzr.cat_file(Scm::Commit::new(:token => 7), + Scm::Diff.new(:path => "Cédric.txt")) + end + end + def test_cat_file_parent with_bzrlib_repository('bzr') do |bzr| expected = <<-EXPECTED From 92e6ec45ea26c9ddfef9b1f992a513fe4387a641 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Fri, 6 Jan 2012 11:08:47 -0800 Subject: [PATCH 127/219] OTWO-1206 Ruby 1.9.2 compatibility No longer compatible with Ruby 1.8.7 --- Rakefile | 4 ++-- lib/scm/adapters/abstract/sha1.rb | 4 ++-- lib/scm/adapters/svn/pull.rb | 1 + lib/scm/parsers/bzr_xml_parser.rb | 1 - lib/scm/parsers/svn_xml_parser.rb | 3 +-- test/unit/svn_commits_test.rb | 10 +++++----- test/unit/svn_convert_test.rb | 2 +- 7 files changed, 12 insertions(+), 13 deletions(-) diff --git a/Rakefile b/Rakefile index 0b49d124..cf03307d 100644 --- a/Rakefile +++ b/Rakefile @@ -3,7 +3,7 @@ require 'rake/clean' require 'rake/testtask' require 'rubygems' -require 'rake/gempackagetask' +require 'rubygems/package_task' spec = Gem::Specification.new do |s| s.name = 'ohloh_scm' @@ -21,7 +21,7 @@ spec = Gem::Specification.new do |s| s.test_files = FileList["test/**/*"] end -Rake::GemPackageTask.new(spec) do |pkg| +Gem::PackageTask.new(spec) do |pkg| pkg.need_tar = true pkg.need_zip = true end diff --git a/lib/scm/adapters/abstract/sha1.rb b/lib/scm/adapters/abstract/sha1.rb index 8a00bbad..f26601a1 100644 --- a/lib/scm/adapters/abstract/sha1.rb +++ b/lib/scm/adapters/abstract/sha1.rb @@ -1,4 +1,4 @@ -require 'sha1' +require 'digest/sha1' NULL_SHA1 = '0000000000000000000000000000000000000000' unless defined?(NULL_SHA1) @@ -11,7 +11,7 @@ class AbstractAdapter # that match those generated natively by Git. def compute_sha1(blob) - blob.to_s == '' ? NULL_SHA1 : SHA1.sha1("blob #{blob.length}\0#{blob}").to_s + blob.to_s == '' ? NULL_SHA1 : Digest::SHA1.hexdigest("blob #{blob.length}\0#{blob}") end # Populates the SHA1 values for each diff in a commit. diff --git a/lib/scm/adapters/svn/pull.rb b/lib/scm/adapters/svn/pull.rb index 58266d89..be6d9e3e 100644 --- a/lib/scm/adapters/svn/pull.rb +++ b/lib/scm/adapters/svn/pull.rb @@ -42,6 +42,7 @@ def svnadmin_create_local FileUtils.rmdir path run "svnadmin create #{path}" FileUtils.cp pre_revprop_change_template, pre_revprop_change_path + FileUtils.chmod 0755, pre_revprop_change_path end def svnadmin_create_remote diff --git a/lib/scm/parsers/bzr_xml_parser.rb b/lib/scm/parsers/bzr_xml_parser.rb index 4a34928f..902d3b9b 100644 --- a/lib/scm/parsers/bzr_xml_parser.rb +++ b/lib/scm/parsers/bzr_xml_parser.rb @@ -1,4 +1,3 @@ -require 'parsedate' require 'rexml/document' require 'rexml/streamlistener' diff --git a/lib/scm/parsers/svn_xml_parser.rb b/lib/scm/parsers/svn_xml_parser.rb index 8bb7f6ea..d28a77e4 100644 --- a/lib/scm/parsers/svn_xml_parser.rb +++ b/lib/scm/parsers/svn_xml_parser.rb @@ -1,4 +1,3 @@ -require 'parsedate' require 'rexml/document' require 'rexml/streamlistener' @@ -33,7 +32,7 @@ def tag_end(name) when 'author' @commit.committer_name = @text when 'date' - @commit.committer_date = Time.utc(*ParseDate.parsedate(@text)) + @commit.committer_date = Time.parse(@text).round.utc when 'path' @diff.path = @text @commit.diffs << @diff diff --git a/test/unit/svn_commits_test.rb b/test/unit/svn_commits_test.rb index 7a16525c..582dc336 100644 --- a/test/unit/svn_commits_test.rb +++ b/test/unit/svn_commits_test.rb @@ -207,11 +207,11 @@ def test_each_commit assert_equal [1, 2, 3, 4, 5], commits.collect { |c| c.token } assert_equal ['robin','robin','robin','jason','jason'], commits.collect { |c| c.committer_name } - assert commits[0].committer_date - Time.utc(2006,6,11,18,28,0) < 1 # commits include milliseconds - assert commits[1].committer_date - Time.utc(2006,6,11,18,32,13) < 1 - assert commits[2].committer_date - Time.utc(2006,6,11,18,34,17) < 1 - assert commits[3].committer_date - Time.utc(2006,7,14,22,17,8) < 1 - assert commits[4].committer_date - Time.utc(2006,7,14,23,7,15) < 1 + assert_equal Time.utc(2006,6,11,18,28, 0), commits[0].committer_date + assert_equal Time.utc(2006,6,11,18,32,14), commits[1].committer_date + assert_equal Time.utc(2006,6,11,18,34,18), commits[2].committer_date + assert_equal Time.utc(2006,7,14,22,17, 9), commits[3].committer_date + assert_equal Time.utc(2006,7,14,23, 7,16), commits[4].committer_date assert_equal "Initial Checkin\n", commits[0].message assert_equal "added makefile", commits[1].message diff --git a/test/unit/svn_convert_test.rb b/test/unit/svn_convert_test.rb index b7c01acb..3c5533c8 100644 --- a/test/unit/svn_convert_test.rb +++ b/test/unit/svn_convert_test.rb @@ -16,7 +16,7 @@ def test_basic_convert # Because Subversion does not track authors (only committers), # the Subversion committer becomes the Git author. assert_equal c.committer_name, dest_commits[i].author_name - assert_equal c.committer_date, dest_commits[i].author_date + assert_equal c.committer_date.round, dest_commits[i].author_date # The svn-to-git conversion process loses the trailing \n for single-line messages assert_equal c.message.strip, dest_commits[i].message.strip From db8cf0e4653e11c3f7cd24220dcb52fad2d7c3d4 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Wed, 25 Jan 2012 22:50:37 -0500 Subject: [PATCH 128/219] Fixes tests broken by test data for OTWO-1177. --- test/unit/bzr_commits_test.rb | 15 ++++++++------- test/unit/bzr_head_test.rb | 6 +++--- test/unit/bzr_misc_test.rb | 5 +++-- test/unit/bzrlib_head_test.rb | 6 +++--- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/test/unit/bzr_commits_test.rb b/test/unit/bzr_commits_test.rb index edc2c654..b8c0d5b0 100644 --- a/test/unit/bzr_commits_test.rb +++ b/test/unit/bzr_commits_test.rb @@ -5,9 +5,9 @@ class BzrCommitsTest < Scm::Test def test_commit_count with_bzr_repository('bzr') do |bzr| - assert_equal 6, bzr.commit_count - assert_equal 5, bzr.commit_count(:after => revision_ids.first) - assert_equal 1, bzr.commit_count(:after => revision_ids[4]) + assert_equal 7, bzr.commit_count + assert_equal 6, bzr.commit_count(:after => revision_ids.first) + assert_equal 1, bzr.commit_count(:after => revision_ids[5]) assert_equal 0, bzr.commit_count(:after => revision_ids.last) end end @@ -36,8 +36,8 @@ def test_commit_count_trunk_only def test_commit_tokens_after with_bzr_repository('bzr') do |bzr| assert_equal revision_ids, bzr.commit_tokens - assert_equal revision_ids[1..5], bzr.commit_tokens(:after => revision_ids.first) - assert_equal revision_ids[5..5], bzr.commit_tokens(:after => revision_ids[4]) + assert_equal revision_ids[1..6], bzr.commit_tokens(:after => revision_ids.first) + assert_equal revision_ids[6..6], bzr.commit_tokens(:after => revision_ids[5]) assert_equal [], bzr.commit_tokens(:after => revision_ids.last) end end @@ -183,7 +183,7 @@ def test_nested_branches_commits_trunk_only_true def test_commits with_bzr_repository('bzr') do |bzr| assert_equal revision_ids, bzr.commits.collect { |c| c.token } - assert_equal revision_ids[5..5], bzr.commits(:after => revision_ids[4]).collect { |c| c.token } + assert_equal revision_ids[6..6], bzr.commits(:after => revision_ids[5]).collect { |c| c.token } assert_equal [], bzr.commits(:after => revision_ids.last).collect { |c| c.token } # Check that the diffs are not populated @@ -368,7 +368,8 @@ def revision_ids 'obnox@samba.org-20090204002453-u70a3ehf3ae9kay1', # 3 'obnox@samba.org-20090204002518-yb0x153oa6mhoodu', # 4 'obnox@samba.org-20090204002540-gmana8tk5f9gboq9', # 5 - 'obnox@samba.org-20090204004942-73rnw0izen42f154' # 6 + 'obnox@samba.org-20090204004942-73rnw0izen42f154', # 6 + 'test@example.com-20111222183733-y91if5npo3pe8ifs', # 7 ] end diff --git a/test/unit/bzr_head_test.rb b/test/unit/bzr_head_test.rb index 18e8e0df..0becedd2 100644 --- a/test/unit/bzr_head_test.rb +++ b/test/unit/bzr_head_test.rb @@ -5,11 +5,11 @@ class BzrHeadTest < Scm::Test def test_head_and_parents with_bzr_repository('bzr') do |bzr| - assert_equal 'obnox@samba.org-20090204004942-73rnw0izen42f154', bzr.head_token - assert_equal 'obnox@samba.org-20090204004942-73rnw0izen42f154', bzr.head.token + assert_equal 'test@example.com-20111222183733-y91if5npo3pe8ifs', bzr.head_token + assert_equal 'test@example.com-20111222183733-y91if5npo3pe8ifs', bzr.head.token assert bzr.head.diffs.any? # diffs should be populated - assert_equal 'obnox@samba.org-20090204002540-gmana8tk5f9gboq9', bzr.parents(bzr.head).first.token + assert_equal 'obnox@samba.org-20090204004942-73rnw0izen42f154', bzr.parents(bzr.head).first.token assert bzr.parents(bzr.head).first.diffs.any? end end diff --git a/test/unit/bzr_misc_test.rb b/test/unit/bzr_misc_test.rb index a1d4c3a4..c33c69ad 100644 --- a/test/unit/bzr_misc_test.rb +++ b/test/unit/bzr_misc_test.rb @@ -14,7 +14,8 @@ def test_exist def test_ls_tree with_bzr_repository('bzr') do |bzr| - assert_equal ['file1.txt', + assert_equal ['Cédric.txt', + 'file1.txt', 'file3.txt', 'file4.txt', 'file5.txt'], @@ -26,7 +27,7 @@ def test_export with_bzr_repository('bzr') do |bzr| Scm::ScratchDir.new do |dir| bzr.export(dir) - assert_equal ['.', '..', 'file1.txt', 'file3.txt', 'file4.txt', 'file5.txt'], Dir.entries(dir).sort + assert_equal ['.', '..', 'Cédric.txt', 'file1.txt', 'file3.txt', 'file4.txt', 'file5.txt'], Dir.entries(dir).sort end end end diff --git a/test/unit/bzrlib_head_test.rb b/test/unit/bzrlib_head_test.rb index d1ae1d3e..1bc1fe85 100644 --- a/test/unit/bzrlib_head_test.rb +++ b/test/unit/bzrlib_head_test.rb @@ -5,11 +5,11 @@ class BzrBzrlibHeadTest < Scm::Test def test_head_and_parents with_bzrlib_repository('bzr') do |bzr| - assert_equal 'obnox@samba.org-20090204004942-73rnw0izen42f154', bzr.head_token - assert_equal 'obnox@samba.org-20090204004942-73rnw0izen42f154', bzr.head.token + assert_equal 'test@example.com-20111222183733-y91if5npo3pe8ifs', bzr.head_token + assert_equal 'test@example.com-20111222183733-y91if5npo3pe8ifs', bzr.head.token assert bzr.head.diffs.any? # diffs should be populated - assert_equal 'obnox@samba.org-20090204002540-gmana8tk5f9gboq9', bzr.parents(bzr.head).first.token + assert_equal 'obnox@samba.org-20090204004942-73rnw0izen42f154', bzr.parents(bzr.head).first.token assert bzr.parents(bzr.head).first.diffs.any? end end From 4991eb4485e350224ae04a51cdab9cb351e0fbff Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Fri, 27 Jan 2012 08:22:28 -0800 Subject: [PATCH 129/219] OTWO-1277 Replaces erronenous bzr 'pull' with 'revert' --- lib/scm/adapters/bzr/pull.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scm/adapters/bzr/pull.rb b/lib/scm/adapters/bzr/pull.rb index f7456031..ec51ffa9 100644 --- a/lib/scm/adapters/bzr/pull.rb +++ b/lib/scm/adapters/bzr/pull.rb @@ -12,7 +12,7 @@ def pull(from, &block) run "rm -rf '#{self.url}'" run "bzr branch '#{from.url}' '#{self.url}'" else - run "cd '#{self.url}' && bzr pull && bzr pull --overwrite '#{from.url}'" + run "cd '#{self.url}' && bzr revert && bzr pull --overwrite '#{from.url}'" end yield(1,1) if block_given? # Progress bar callback From 68b9ecc722336eeceefa4f6887007a2b9e5d3fb1 Mon Sep 17 00:00:00 2001 From: Robin Luckey Date: Thu, 8 Mar 2012 19:25:08 -0800 Subject: [PATCH 130/219] OTWO-1412 Upgrades Bzr repositories after every pull We can't know when it's required, but it's fatal to miss it, So we force a `bzr upgrade` after every pull. --- lib/scm/adapters/bzr/pull.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/scm/adapters/bzr/pull.rb b/lib/scm/adapters/bzr/pull.rb index ec51ffa9..ff0e3680 100644 --- a/lib/scm/adapters/bzr/pull.rb +++ b/lib/scm/adapters/bzr/pull.rb @@ -11,6 +11,7 @@ def pull(from, &block) run "mkdir -p '#{self.url}'" run "rm -rf '#{self.url}'" run "bzr branch '#{from.url}' '#{self.url}'" + clean_up_disk else run "cd '#{self.url}' && bzr revert && bzr pull --overwrite '#{from.url}'" end @@ -18,5 +19,20 @@ def pull(from, &block) yield(1,1) if block_given? # Progress bar callback end + def clean_up_disk + # Usually a `bzr upgrade` is unnecessary, but it's fatal to miss it when + # required. Because I don't know how to detect in advance whether we + # actually need it, we play it safe and always upgrade. + # + # Unfortunately, not only can we not know whether it is required, + # but the command fails and raises when the upgrade is not required. + + begin + run "cd '#{self.url}' && bzr upgrade" + rescue RuntimeError => e + raise unless e.message =~ /already at the most recent format/ + end + end + end end From fa9af52d85adcb8d50d4403880eece84b134ce9c Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Wed, 4 Apr 2012 01:04:58 -0400 Subject: [PATCH 131/219] OTWO-1412 Initializes bzr properly and sets up logger. If bzr logger is not set, warning messages generated by bzr get suppressed and an error is logged to stderr instead, telling us that logger is not initialized. This was causing bzr Sloc jobs to die or hang in some cases. --- lib/scm/adapters/bzrlib/bzrlib_pipe_server.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py b/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py index 57854392..fdac2201 100644 --- a/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py +++ b/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py @@ -1,8 +1,10 @@ from bzrlib.branch import Branch from bzrlib.revisionspec import RevisionSpec +from cStringIO import StringIO import sys import time import traceback +import logging class BzrPipeServer: def __init__(self, repository_url): @@ -88,6 +90,9 @@ def command_loop(): if __name__ == "__main__": try: + stream = StringIO() + handler = logging.StreamHandler(stream) + logging.getLogger('bzr').addHandler(handler) command_loop() except: exc_trace = traceback.format_exc() From 8be6be387a3b706cb8775c984ad173180e5b9197 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Wed, 4 Apr 2012 16:42:37 -0400 Subject: [PATCH 132/219] OTWO-1412 Redirects logger to os.devnull Also removes previous fix for this ticket that force upgraded repos. --- lib/scm/adapters/bzr/pull.rb | 16 ---------------- lib/scm/adapters/bzrlib/bzrlib_pipe_server.py | 5 ++--- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/lib/scm/adapters/bzr/pull.rb b/lib/scm/adapters/bzr/pull.rb index ff0e3680..ec51ffa9 100644 --- a/lib/scm/adapters/bzr/pull.rb +++ b/lib/scm/adapters/bzr/pull.rb @@ -11,7 +11,6 @@ def pull(from, &block) run "mkdir -p '#{self.url}'" run "rm -rf '#{self.url}'" run "bzr branch '#{from.url}' '#{self.url}'" - clean_up_disk else run "cd '#{self.url}' && bzr revert && bzr pull --overwrite '#{from.url}'" end @@ -19,20 +18,5 @@ def pull(from, &block) yield(1,1) if block_given? # Progress bar callback end - def clean_up_disk - # Usually a `bzr upgrade` is unnecessary, but it's fatal to miss it when - # required. Because I don't know how to detect in advance whether we - # actually need it, we play it safe and always upgrade. - # - # Unfortunately, not only can we not know whether it is required, - # but the command fails and raises when the upgrade is not required. - - begin - run "cd '#{self.url}' && bzr upgrade" - rescue RuntimeError => e - raise unless e.message =~ /already at the most recent format/ - end - end - end end diff --git a/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py b/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py index fdac2201..f751cf81 100644 --- a/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py +++ b/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py @@ -1,6 +1,6 @@ from bzrlib.branch import Branch from bzrlib.revisionspec import RevisionSpec -from cStringIO import StringIO +import os import sys import time import traceback @@ -90,8 +90,7 @@ def command_loop(): if __name__ == "__main__": try: - stream = StringIO() - handler = logging.StreamHandler(stream) + handler = logging.FileHandler(os.devnull) logging.getLogger('bzr').addHandler(handler) command_loop() except: From ce112d2489662935dac428054c75b6f566d90e28 Mon Sep 17 00:00:00 2001 From: Paddy Date: Mon, 28 May 2012 11:54:54 +0530 Subject: [PATCH 133/219] OTWO-1489 Added a validation for SVN Repo URL if empty --- lib/scm/adapters/svn/validation.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/scm/adapters/svn/validation.rb b/lib/scm/adapters/svn/validation.rb index d996401d..01f538dc 100644 --- a/lib/scm/adapters/svn/validation.rb +++ b/lib/scm/adapters/svn/validation.rb @@ -26,6 +26,7 @@ def validate_username # If the URL is a simple directory path, make sure it is prefixed by file:// def path_to_file_url(path) + return nil if path.blank? url =~ /:\/\// ? url : 'file://' + File.expand_path(path) end From 8f5bd10a997057ccdce9ecec6a3a919ca389f33c Mon Sep 17 00:00:00 2001 From: Paddy Date: Fri, 1 Jun 2012 12:45:50 +0530 Subject: [PATCH 134/219] OTWO-1489 Added a validation for SVN Repo URL if empty --- lib/scm/adapters/svn/validation.rb | 2 +- test/unit/svn_validation_test.rb | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/scm/adapters/svn/validation.rb b/lib/scm/adapters/svn/validation.rb index 01f538dc..790d113d 100644 --- a/lib/scm/adapters/svn/validation.rb +++ b/lib/scm/adapters/svn/validation.rb @@ -26,7 +26,7 @@ def validate_username # If the URL is a simple directory path, make sure it is prefixed by file:// def path_to_file_url(path) - return nil if path.blank? + return nil if path.empty? url =~ /:\/\// ? url : 'file://' + File.expand_path(path) end diff --git a/test/unit/svn_validation_test.rb b/test/unit/svn_validation_test.rb index 4c610c1c..c41c5716 100644 --- a/test/unit/svn_validation_test.rb +++ b/test/unit/svn_validation_test.rb @@ -7,6 +7,16 @@ def test_valid_usernames assert !SvnAdapter.new(:username => username).validate_username end end + + def test_for_blank_svn_urls + svn = SvnAdapter.new(:url =>"") + assert_nil svn.path_to_file_url(svn.url) + end + + def test_for_non_blank_svn_urls + svn = SvnAdapter.new(:url =>"/home/rapbhan") + assert_equal 'file:///home/rapbhan', svn.path_to_file_url(svn.url) + end def test_rejected_urls [ nil, "", "foo", "http:/", "http:://", "http://", From 8dde2ecec7eb42385280cf638c349e27c7df1bc4 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Thu, 12 Jul 2012 14:37:14 -0400 Subject: [PATCH 135/219] Stream git commit log to a file before parsing Commit log for large git repositories doesn't fit in memory. We started seeing failing import jobs for large git repositories. This patch writes the log to a file before parsing it so that we don't hold the entire log in memory. --- lib/scm/adapters/git/commits.rb | 34 +++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/lib/scm/adapters/git/commits.rb b/lib/scm/adapters/git/commits.rb index 0acb4d64..7f5ff579 100644 --- a/lib/scm/adapters/git/commits.rb +++ b/lib/scm/adapters/git/commits.rb @@ -40,10 +40,12 @@ def each_commit(opts={}) # because Ohloh ignores merge diffs anyway. previous = nil - Scm::Parsers::GitStyledParser.parse(log(opts)) do |e| - yield fixup_null_merge(e) unless previous && previous.token == e.token - previous = e - end + open_log_file(opts) do |io| + Scm::Parsers::GitStyledParser.parse(io) do |e| + yield fixup_null_merge(e) unless previous && previous.token == e.token + previous = e + end + end end # Returns a single commit, including its diffs @@ -85,6 +87,30 @@ def log(opts={}) end end + + # Same as log() method above, except that it writes the log to + # a file. + def open_log_file(opts={}) + if has_branch? + if opts[:after] && opts[:after]==self.head_token + '' # Nothing new. + else + begin + run "#{rev_list_command(opts)} | xargs -n 1 #{Scm::Parsers::GitStyledParser.whatchanged} > #{log_filename}" + File.open(log_filename, 'r') { |io| yield io } + ensure + File.delete(log_filename) if FileTest.exist?(log_filename) + end + end + else + '' + end + end + + def log_filename + File.join('/tmp', (self.url).gsub(/\W/,'') + '.log') + end + def rev_list_command(opts={}) up_to = opts[:up_to] || branch_name range = opts[:after] ? "#{opts[:after]}..#{up_to}" : up_to From 7d1159b616cfa0f9961da0a63966f7048eeec5ab Mon Sep 17 00:00:00 2001 From: Sathishkumar Natesan Date: Wed, 21 Aug 2013 18:17:31 +0530 Subject: [PATCH 136/219] OTWO-2738 Bump up git version to 1.8.2 and fix nothing_to_commit check With the updated Git client the status message pattern has changed from 'nothing to commit *' to 'nothing to commit, *'. So this fix will make our library to work across the older and newer versions. --- README.md | 8 ++++---- lib/scm/adapters/git/commit_all.rb | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 6ae5aa42..32de660b 100644 --- a/README.md +++ b/README.md @@ -39,10 +39,10 @@ shell. In order to pass the unit tests, all three systems must be installed and on your path. Ohloh uses the following versions, and other versions are totally unsupported at this time: -cvsnt 2.5.03 -svn 1.4.2 -git 1.6.0.4 -hg 1.1.2 +cvsnt 2.5.03 +svn 1.4.2 +git 1.8.2.1 +hg 1.1.2 If you are using CVS instead of CVSNT, you can potentially try creating a shell alias or symlink mapping 'cvsnt' to 'cvs'. diff --git a/lib/scm/adapters/git/commit_all.rb b/lib/scm/adapters/git/commit_all.rb index 4ee7fbb6..353f6c5f 100644 --- a/lib/scm/adapters/git/commit_all.rb +++ b/lib/scm/adapters/git/commit_all.rb @@ -64,7 +64,7 @@ def message_filename # True if there are pending changes to commit. def anything_to_commit? - run("cd '#{self.url}' && git status | tail -1") =~ /nothing to commit / ? false : true + run("cd '#{self.url}' && git status | tail -1") =~ /nothing to commit/ ? false : true end # Ensures that the repository directory exists, and that the git database has been initialized. From eb55711e96fcebfd4204f393738dcf135cfaa435 Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Fri, 4 Oct 2013 09:00:11 -0400 Subject: [PATCH 137/219] Adds Ohloh partner badge --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 32de660b..08eb3185 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![Ohloh SCM on Ohloh](https://www.ohloh.net/p/ohloh_scm/widgets/project_partner_badge.gif)](https://www.ohloh.net/p/ohloh_scm) + # Ohloh SCM The Ohloh source control management library From 17e2556fea2e86cad53659f3b2658f98e20e214c Mon Sep 17 00:00:00 2001 From: Abhay Mujumdar Date: Fri, 4 Oct 2013 14:58:58 -0400 Subject: [PATCH 138/219] Adds encoding header to files containing non-ascii chars --- test/unit/bzr_cat_file_test.rb | 1 + test/unit/bzr_misc_test.rb | 1 + test/unit/bzrlib_cat_file_test.rb | 1 + 3 files changed, 3 insertions(+) diff --git a/test/unit/bzr_cat_file_test.rb b/test/unit/bzr_cat_file_test.rb index 93331684..50377c66 100644 --- a/test/unit/bzr_cat_file_test.rb +++ b/test/unit/bzr_cat_file_test.rb @@ -1,3 +1,4 @@ +#encoding: utf-8 require File.dirname(__FILE__) + '/../test_helper' module Scm::Adapters diff --git a/test/unit/bzr_misc_test.rb b/test/unit/bzr_misc_test.rb index c33c69ad..5ca17d6e 100644 --- a/test/unit/bzr_misc_test.rb +++ b/test/unit/bzr_misc_test.rb @@ -1,3 +1,4 @@ +#encoding: utf-8 require File.dirname(__FILE__) + '/../test_helper' module Scm::Adapters diff --git a/test/unit/bzrlib_cat_file_test.rb b/test/unit/bzrlib_cat_file_test.rb index 32b58ddd..6c43203f 100644 --- a/test/unit/bzrlib_cat_file_test.rb +++ b/test/unit/bzrlib_cat_file_test.rb @@ -1,3 +1,4 @@ +#encoding: utf-8 require File.dirname(__FILE__) + '/../test_helper' module Scm::Adapters From a8782a6da122ddf2f9f284b8a38242c13caedc2d Mon Sep 17 00:00:00 2001 From: Sathishkumar Natesan Date: Thu, 23 Jan 2014 22:11:33 +0530 Subject: [PATCH 139/219] OTWO-2996 Default to EPOCH time when the git parser don't find a date Currently, it defaults to Time.now.utc which is not reasonably fair. Also git commands like git log/show defaults to epoch time. --- lib/scm/parsers/git_styled_parser.rb | 4 +- test/unit/git_styled_parser_test.rb | 85 ++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 test/unit/git_styled_parser_test.rb diff --git a/lib/scm/parsers/git_styled_parser.rb b/lib/scm/parsers/git_styled_parser.rb index 3966ddd2..3f0ab39e 100644 --- a/lib/scm/parsers/git_styled_parser.rb +++ b/lib/scm/parsers/git_styled_parser.rb @@ -42,7 +42,9 @@ def self.internal_parse(io, opts) elsif line =~ /^Author: (.+)$/ e.author_name = $1 elsif line =~ /^Date: (.*)$/ - e.author_date = Time.parse($1).utc # Note strongly: MUST be RFC2822 format to parse properly + # default to EPOCH when there's no date info + e.author_date = Time.at(0).utc if $1.strip.empty? + e.author_date ||= Time.parse($1).utc # Note strongly: MUST be RFC2822 format to parse properly elsif line == "__BEGIN_COMMENT__" state = :message elsif line =~ /^AuthorEmail: (.+)$/ diff --git a/test/unit/git_styled_parser_test.rb b/test/unit/git_styled_parser_test.rb new file mode 100644 index 00000000..90b36c2c --- /dev/null +++ b/test/unit/git_styled_parser_test.rb @@ -0,0 +1,85 @@ +require File.dirname(__FILE__) + '/../test_helper' + +module Scm::Parsers + class GitStyledParserTest < Scm::Test + + def test_empty_array + assert_equal([], GitStyledParser.parse('')) + end + + def test_log_parser_no_date +sample_log = <<-SAMPLE +__BEGIN_COMMIT__ +Commit: 1df547800dcd168e589bb9b26b4039bff3a7f7e4 +Author: Jason Allen +AuthorEmail: jason@ohloh.net +Date: +__BEGIN_COMMENT__ + moving COPYING + +__END_COMMENT__ +SAMPLE + + commits = GitStyledParser.parse(sample_log) + assert_equal 1, commits.size + assert_equal Time.utc(1970,1,1,0,0,0), commits[0].author_date + end + + def test_log_parser_default +sample_log = < Date: Mon, 27 Jan 2014 16:58:48 -0500 Subject: [PATCH 140/219] OTWO-2996 Use strict time format check using Time.rfc2822 to handle bogus dates --- lib/scm/parsers/git_styled_parser.rb | 10 +++++++--- test/unit/git_styled_parser_test.rb | 20 +++++++++++++++++++- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/lib/scm/parsers/git_styled_parser.rb b/lib/scm/parsers/git_styled_parser.rb index 3f0ab39e..b13379db 100644 --- a/lib/scm/parsers/git_styled_parser.rb +++ b/lib/scm/parsers/git_styled_parser.rb @@ -42,9 +42,8 @@ def self.internal_parse(io, opts) elsif line =~ /^Author: (.+)$/ e.author_name = $1 elsif line =~ /^Date: (.*)$/ - # default to EPOCH when there's no date info - e.author_date = Time.at(0).utc if $1.strip.empty? - e.author_date ||= Time.parse($1).utc # Note strongly: MUST be RFC2822 format to parse properly + # MUST be RFC2822 format to parse properly, else defaults to epoch time + e.author_date = parse_commit_date($1) elsif line == "__BEGIN_COMMENT__" state = :message elsif line =~ /^AuthorEmail: (.+)$/ @@ -81,5 +80,10 @@ def self.internal_parse(io, opts) yield e if e end + + def self.parse_commit_date(date) + t = Time.rfc2822(date) rescue Time.at(0) + t.utc + end end end diff --git a/test/unit/git_styled_parser_test.rb b/test/unit/git_styled_parser_test.rb index 90b36c2c..c8f949cc 100644 --- a/test/unit/git_styled_parser_test.rb +++ b/test/unit/git_styled_parser_test.rb @@ -7,7 +7,7 @@ def test_empty_array assert_equal([], GitStyledParser.parse('')) end - def test_log_parser_no_date + def test_log_parser_nil_date sample_log = <<-SAMPLE __BEGIN_COMMIT__ Commit: 1df547800dcd168e589bb9b26b4039bff3a7f7e4 @@ -17,6 +17,24 @@ def test_log_parser_no_date __BEGIN_COMMENT__ moving COPYING +__END_COMMENT__ +SAMPLE + + commits = GitStyledParser.parse(sample_log) + assert_equal 1, commits.size + assert_equal Time.utc(1970,1,1,0,0,0), commits[0].author_date + end + + def test_log_parser_bogus_date +sample_log = <<-SAMPLE +__BEGIN_COMMIT__ +Commit: 1df547800dcd168e589bb9b26b4039bff3a7f7e4 +Author: Jason Allen +AuthorEmail: jason@ohloh.net +Date: Mon, Jan 01 2012 05:00:00 -0500 +__BEGIN_COMMENT__ + moving COPYING + __END_COMMENT__ SAMPLE From becdca209707edeb6c5f3173094f4844e0b2dd5c Mon Sep 17 00:00:00 2001 From: Sathishkumar Natesan Date: Mon, 27 Jan 2014 18:17:58 -0500 Subject: [PATCH 141/219] OTWO-2996 Rename parse_commit_date to parse_date as it can be used to parse author/committer date --- lib/scm/parsers/git_styled_parser.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/scm/parsers/git_styled_parser.rb b/lib/scm/parsers/git_styled_parser.rb index b13379db..51ee194c 100644 --- a/lib/scm/parsers/git_styled_parser.rb +++ b/lib/scm/parsers/git_styled_parser.rb @@ -43,7 +43,7 @@ def self.internal_parse(io, opts) e.author_name = $1 elsif line =~ /^Date: (.*)$/ # MUST be RFC2822 format to parse properly, else defaults to epoch time - e.author_date = parse_commit_date($1) + e.author_date = parse_date($1) elsif line == "__BEGIN_COMMENT__" state = :message elsif line =~ /^AuthorEmail: (.+)$/ @@ -81,7 +81,7 @@ def self.internal_parse(io, opts) yield e if e end - def self.parse_commit_date(date) + def self.parse_date(date) t = Time.rfc2822(date) rescue Time.at(0) t.utc end From f32ef97b426dd29190e5c21d9b089fe4d76d77d7 Mon Sep 17 00:00:00 2001 From: Peter Degen-Portnoy Date: Fri, 21 Feb 2014 16:49:21 -0500 Subject: [PATCH 142/219] Change Git Validation to convert https and http protocols for git and web urls to git protocol --- lib/scm/adapters/git/validation.rb | 8 ++++-- test/unit/git_validation_test.rb | 45 ++++++++++++++++++++++-------- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/lib/scm/adapters/git/validation.rb b/lib/scm/adapters/git/validation.rb index 3f985bf9..90d99ee4 100644 --- a/lib/scm/adapters/git/validation.rb +++ b/lib/scm/adapters/git/validation.rb @@ -10,17 +10,19 @@ def self.public_url_regex def normalize super - @url = read_only_url + @url = normalize_url @branch_name = 'master' if @branch_name.to_s == '' self end # Given a Github read-write URL, return a read-only URL. # Otherwise, return the original URL. - def read_only_url + def normalize_url case @url - when /^https:\/\/\w+@github.com\/(.+)\.git$/ + when /^https?:\/\/\w+@github.com\/(.+)\.git$/ "git://github.com/#{$1}.git" + when /^https?:\/\/github.com\/(.+)/ + "git://github.com/#{$1}" when /^git@github.com:(.+)\.git$/ "git://github.com/#{$1}.git" else diff --git a/test/unit/git_validation_test.rb b/test/unit/git_validation_test.rb index a80b2e68..2bdba5bc 100644 --- a/test/unit/git_validation_test.rb +++ b/test/unit/git_validation_test.rb @@ -23,7 +23,11 @@ def test_accepted_urls "https://kernel.org/pub/scm/git/git.git", "https://kernel.org:8080/pub/scm/git/git.git", "git://kernel.org/~foo/git.git", - "http://git.onerussian.com/pub/deb/impose+.git" + "http://git.onerussian.com/pub/deb/impose+.git", + "https://Person@github.com/Person/some_repo.git", + "http://Person@github.com/Person/some_repo.git", + "https://github.com/Person/some_repo", + "http://github.com/Person/some_repo" ].each do |url| git = GitAdapter.new(:url => url) assert !git.validate_url @@ -41,32 +45,49 @@ def test_guess_forge assert_equal 'kernel.org', git.guess_forge end - def test_read_only_url - assert_equal nil, GitAdapter.new(:url => nil).read_only_url - assert_equal '', GitAdapter.new(:url => '').read_only_url - assert_equal 'foo', GitAdapter.new(:url => 'foo').read_only_url + def test_normalize_url + assert_equal nil, GitAdapter.new(:url => nil).normalize_url + assert_equal '', GitAdapter.new(:url => '').normalize_url + assert_equal 'foo', GitAdapter.new(:url => 'foo').normalize_url # A non-Github URL: no change assert_equal 'git://kernel.org/pub/scm/git/git.git', - GitAdapter.new(:url => 'git://kernel.org/pub/scm/git/git.git').read_only_url + GitAdapter.new(:url => 'git://kernel.org/pub/scm/git/git.git').normalize_url # A Github read-write URL: converted to read-only assert_equal 'git://github.com/robinluckey/ohcount.git', - GitAdapter.new(:url => 'https://robinluckey@github.com/robinluckey/ohcount.git').read_only_url + GitAdapter.new(:url => 'https://robinluckey@github.com/robinluckey/ohcount.git').normalize_url # A Github read-write URL: converted to read-only assert_equal 'git://github.com/robinluckey/ohcount.git', - GitAdapter.new(:url => 'git@github.com:robinluckey/ohcount.git').read_only_url + GitAdapter.new(:url => 'git@github.com:robinluckey/ohcount.git').normalize_url # A Github read-only URL: no change assert_equal 'git://github.com/robinluckey/ohcount.git', - GitAdapter.new(:url => 'git@github.com:robinluckey/ohcount.git').read_only_url + GitAdapter.new(:url => 'git@github.com:robinluckey/ohcount.git').normalize_url end def test_normalize_converts_to_read_only - git = GitAdapter.new(:url => 'https://robinluckey@github.com/robinluckey/ohcount.git') - git.normalize - assert_equal 'git://github.com/robinluckey/ohcount.git', git.url + normalize_url_test('https://robinluckey@github.com/robinluckey/ohcount.git', 'git://github.com/robinluckey/ohcount.git') + end + + def test_normalize_handles_https_with_user_at_github_format + normalize_url_test('http://Person@github.com/Person/something.git', 'git://github.com/Person/something.git') + end + + def test_normalize_handles_https_web_url + normalize_url_test('https://github.com/Person/something', 'git://github.com/Person/something') end + + def test_normalize_handles_http_web_url + normalize_url_test('http://github.com/Person/something', 'git://github.com/Person/something') + end + + private + def normalize_url_test(url, result_url) + git = GitAdapter.new(:url => url) + git.normalize + assert_equal result_url, git.url + end end end From 09d419f8a83db120ca409e793a95574afe9e5900 Mon Sep 17 00:00:00 2001 From: Peter Degen-Portnoy Date: Fri, 21 Feb 2014 17:05:08 -0500 Subject: [PATCH 143/219] Update comment to reflect behavior of normalize_url method --- lib/scm/adapters/git/validation.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/scm/adapters/git/validation.rb b/lib/scm/adapters/git/validation.rb index 90d99ee4..eba20539 100644 --- a/lib/scm/adapters/git/validation.rb +++ b/lib/scm/adapters/git/validation.rb @@ -15,8 +15,10 @@ def normalize self end - # Given a Github read-write URL, return a read-only URL. - # Otherwise, return the original URL. + # Given a Github read-write URL, return a git protocol read-only URL + # Given a Github web URL, return a git protocol read-only URL + # Given a Git read-write protocol URL, return a git protocol read-only URL + # Else, return the URL def normalize_url case @url when /^https?:\/\/\w+@github.com\/(.+)\.git$/ From f31045322263cc6050be83682c6f0faa32b73d76 Mon Sep 17 00:00:00 2001 From: Peter Degen-Portnoy Date: Thu, 6 Mar 2014 11:11:44 -0500 Subject: [PATCH 144/219] Normalize_Branch_Name: set the branch name when normalizing an SvnAdapter recalc_branch_name has to handle exceptions thrown when the URL is really a file system --- lib/scm/adapters/svn/misc.rb | 4 ++-- lib/scm/adapters/svn/validation.rb | 11 ++++++++--- test/unit/svn_validation_test.rb | 24 ++++++++++++++++++------ 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/lib/scm/adapters/svn/misc.rb b/lib/scm/adapters/svn/misc.rb index 13a2282c..351d8da7 100644 --- a/lib/scm/adapters/svn/misc.rb +++ b/lib/scm/adapters/svn/misc.rb @@ -35,10 +35,10 @@ def restrict_url_to_trunk if list.include? 'trunk/' self.url = File.join(self.url, 'trunk') - self.branch_name = File.join(self.branch_name, 'trunk') + self.branch_name = File.join(self.branch_name, 'trunk') if self.branch_name elsif list.size == 1 and list.first[-1..-1] == '/' self.url = File.join(self.url, list.first[0..-2]) - self.branch_name = File.join(self.branch_name, list.first[0..-2]) + self.branch_name = File.join(self.branch_name, list.first[0..-2]) if self.branch_name return restrict_url_to_trunk end self.url diff --git a/lib/scm/adapters/svn/validation.rb b/lib/scm/adapters/svn/validation.rb index 790d113d..152dd72d 100644 --- a/lib/scm/adapters/svn/validation.rb +++ b/lib/scm/adapters/svn/validation.rb @@ -12,7 +12,7 @@ def normalize super @url = path_to_file_url(@url) @url = force_https_if_sourceforge(@url) - @branch_name = @branch_name[0..-2] if @branch_name && @branch_name[-1..-1] == '/' + @branch_name = recalc_branch_name self end @@ -32,7 +32,7 @@ def path_to_file_url(path) def force_https_if_sourceforge(url) # SourceForge requires https for svnsync - url =~ /http(:\/\/.*svn\.sourceforge\.net.*)/ ? "https#{$1}" : url + url =~ /http(:\/\/.*svn\.(sourceforge|code\.sf)\.net.*)/ ? "https#{$1}" : url end def validate_server_connection @@ -54,7 +54,12 @@ def validate_server_connection # From the given URL, determine which part of it is the root and which part of it is the branch_name. # The current branch_name is overwritten. def recalc_branch_name - @branch_name = @url ? @url[root.length..-1] : @branch_name + begin + @branch_name = @url ? @url[root.length..-1] : @branch_name + rescue RuntimeError => exception + exception.message =~ /svn:*is not a working copy/ # we have a file system + @branch_name = '' + end @branch_name = @branch_name[0..-2] if @branch_name[-1..-1] == '/' @branch_name end diff --git a/test/unit/svn_validation_test.rb b/test/unit/svn_validation_test.rb index c41c5716..3147ca09 100644 --- a/test/unit/svn_validation_test.rb +++ b/test/unit/svn_validation_test.rb @@ -95,6 +95,9 @@ def test_guess_forge svn = SvnAdapter.new(:url => 'https://vegastrike.svn.sourceforge.net/svnroot/vegastrike/trunk') assert_equal 'sourceforge.net', svn.guess_forge + svn = SvnAdapter.new(:url => 'https://svn.code.sf.net/p/gallery/code/trunk/gallery2') + assert_equal 'code.sf.net', svn.guess_forge + svn = SvnAdapter.new(:url => 'https://appfuse.dev.java.net/svn/appfuse/trunk') assert_equal 'java.net', svn.guess_forge @@ -106,14 +109,13 @@ def test_guess_forge end def test_sourceforge_requires_https - assert_equal 'https://gallery.svn.sourceforge.net/svnroot/gallery/trunk/gallery2', - SvnAdapter.new(:url => 'http://gallery.svn.sourceforge.net/svnroot/gallery/trunk/gallery2').normalize.url + url = '://svn.code.sf.net/p/gallery/code/trunk/gallery2' + assert_equal "https#{url}", SvnAdapter.new(:url => "http#{url}").normalize.url - assert_equal 'https://gallery.svn.sourceforge.net/svnroot/gallery/trunk/gallery2', - SvnAdapter.new(:url => 'https://gallery.svn.sourceforge.net/svnroot/gallery/trunk/gallery2').normalize.url + assert_equal "https#{url}", SvnAdapter.new(:url => "https#{url}").normalize.url - assert_equal 'http://pianosa.googlecode.com/svn/trunk', - SvnAdapter.new(:url => 'http://pianosa.googlecode.com/svn/trunk').normalize.url + url = 'https://github.com/blackducksw/ohloh_scm/trunk' + assert_equal url, SvnAdapter.new(:url => url).normalize.url end def test_validate_server_connection @@ -145,6 +147,16 @@ def test_recalc_branch_name assert !svn_trunk_with_whack.branch_name assert_equal '/trunk', svn_trunk_with_whack.recalc_branch_name assert_equal '/trunk', svn_trunk_with_whack.branch_name + + svn_trunk = SvnAdapter.new(:url => svn.root + '/trunk') + assert !svn_trunk.branch_name + svn_trunk.normalize # only normalize to ensure branch_name is populated correctly + assert_equal '/trunk', svn_trunk.branch_name + + svn_trunk = SvnAdapter.new(:url => svn.root) + assert !svn_trunk.branch_name + svn_trunk.normalize + assert_equal '', svn_trunk.branch_name end end end From 2e5d88f6e92eb38e463e7dc71ff520c1c38228ec Mon Sep 17 00:00:00 2001 From: Peter Degen-Portnoy Date: Tue, 11 Mar 2014 14:25:47 -0400 Subject: [PATCH 145/219] Normalize_Branch_Name Correct condition in recalc_branch_name Remove unneeded check for @branch_name in svn/misc.rb Handle file system based SVN URLs better --- lib/scm/adapters/svn/misc.rb | 4 ++-- lib/scm/adapters/svn/validation.rb | 19 ++++++++++++++----- test/unit/svn_validation_test.rb | 15 ++++++++++++--- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/lib/scm/adapters/svn/misc.rb b/lib/scm/adapters/svn/misc.rb index 351d8da7..13a2282c 100644 --- a/lib/scm/adapters/svn/misc.rb +++ b/lib/scm/adapters/svn/misc.rb @@ -35,10 +35,10 @@ def restrict_url_to_trunk if list.include? 'trunk/' self.url = File.join(self.url, 'trunk') - self.branch_name = File.join(self.branch_name, 'trunk') if self.branch_name + self.branch_name = File.join(self.branch_name, 'trunk') elsif list.size == 1 and list.first[-1..-1] == '/' self.url = File.join(self.url, list.first[0..-2]) - self.branch_name = File.join(self.branch_name, list.first[0..-2]) if self.branch_name + self.branch_name = File.join(self.branch_name, list.first[0..-2]) return restrict_url_to_trunk end self.url diff --git a/lib/scm/adapters/svn/validation.rb b/lib/scm/adapters/svn/validation.rb index 152dd72d..49a2d3ea 100644 --- a/lib/scm/adapters/svn/validation.rb +++ b/lib/scm/adapters/svn/validation.rb @@ -12,7 +12,11 @@ def normalize super @url = path_to_file_url(@url) @url = force_https_if_sourceforge(@url) - @branch_name = recalc_branch_name + if @branch_name + clean_branch_name + else + @branch_name = recalc_branch_name + end self end @@ -57,11 +61,10 @@ def recalc_branch_name begin @branch_name = @url ? @url[root.length..-1] : @branch_name rescue RuntimeError => exception - exception.message =~ /svn:*is not a working copy/ # we have a file system - @branch_name = '' + @branch_name = '' if exception.message =~ /(svn:*is not a working copy|Unable to open an ra_local session to URL)/ # we have a file system end - @branch_name = @branch_name[0..-2] if @branch_name[-1..-1] == '/' - @branch_name + clean_branch_name + @branch_name end def guess_forge @@ -74,5 +77,11 @@ def guess_forge u end end + + private + def clean_branch_name + return unless @branch_name + @branch_name.chop! if @branch_name.end_with?('/') + end end end diff --git a/test/unit/svn_validation_test.rb b/test/unit/svn_validation_test.rb index 3147ca09..9dda3215 100644 --- a/test/unit/svn_validation_test.rb +++ b/test/unit/svn_validation_test.rb @@ -159,9 +159,18 @@ def test_recalc_branch_name assert_equal '', svn_trunk.branch_name end end - end - def test_strip_trailing_whack_from_branch_name - assert_equal '/trunk', SvnAdapter.new(:branch_name => "/trunk/").normalize.branch_name + def test_strip_trailing_whack_from_branch_name + with_svn_repository('svn') do |svn| + assert_equal '/trunk', SvnAdapter.new(:url => svn.root, :branch_name => "/trunk/").normalize.branch_name + end + end + + def test_empty_branch_name_with_file_system + Scm::ScratchDir.new do |dir| + svn = SvnAdapter.new(:url => dir).normalize + assert_equal '', svn.branch_name + end + end end end From b1b0e1e2b5c73416f569f9a4def6e8152d0abcdd Mon Sep 17 00:00:00 2001 From: Sathishkumar Natesan Date: Thu, 23 Jan 2014 22:11:33 +0530 Subject: [PATCH 146/219] OTWO-2996 Default to EPOCH time when the git parser don't find a date Currently, it defaults to Time.now.utc which is not reasonably fair. Also git commands like git log/show defaults to epoch time. --- lib/scm/parsers/git_styled_parser.rb | 4 +- test/unit/git_styled_parser_test.rb | 85 ++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 test/unit/git_styled_parser_test.rb diff --git a/lib/scm/parsers/git_styled_parser.rb b/lib/scm/parsers/git_styled_parser.rb index 3966ddd2..3f0ab39e 100644 --- a/lib/scm/parsers/git_styled_parser.rb +++ b/lib/scm/parsers/git_styled_parser.rb @@ -42,7 +42,9 @@ def self.internal_parse(io, opts) elsif line =~ /^Author: (.+)$/ e.author_name = $1 elsif line =~ /^Date: (.*)$/ - e.author_date = Time.parse($1).utc # Note strongly: MUST be RFC2822 format to parse properly + # default to EPOCH when there's no date info + e.author_date = Time.at(0).utc if $1.strip.empty? + e.author_date ||= Time.parse($1).utc # Note strongly: MUST be RFC2822 format to parse properly elsif line == "__BEGIN_COMMENT__" state = :message elsif line =~ /^AuthorEmail: (.+)$/ diff --git a/test/unit/git_styled_parser_test.rb b/test/unit/git_styled_parser_test.rb new file mode 100644 index 00000000..90b36c2c --- /dev/null +++ b/test/unit/git_styled_parser_test.rb @@ -0,0 +1,85 @@ +require File.dirname(__FILE__) + '/../test_helper' + +module Scm::Parsers + class GitStyledParserTest < Scm::Test + + def test_empty_array + assert_equal([], GitStyledParser.parse('')) + end + + def test_log_parser_no_date +sample_log = <<-SAMPLE +__BEGIN_COMMIT__ +Commit: 1df547800dcd168e589bb9b26b4039bff3a7f7e4 +Author: Jason Allen +AuthorEmail: jason@ohloh.net +Date: +__BEGIN_COMMENT__ + moving COPYING + +__END_COMMENT__ +SAMPLE + + commits = GitStyledParser.parse(sample_log) + assert_equal 1, commits.size + assert_equal Time.utc(1970,1,1,0,0,0), commits[0].author_date + end + + def test_log_parser_default +sample_log = < Date: Mon, 27 Jan 2014 16:58:48 -0500 Subject: [PATCH 147/219] OTWO-2996 Use strict time format check using Time.rfc2822 to handle bogus dates --- lib/scm/parsers/git_styled_parser.rb | 10 +++++++--- test/unit/git_styled_parser_test.rb | 20 +++++++++++++++++++- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/lib/scm/parsers/git_styled_parser.rb b/lib/scm/parsers/git_styled_parser.rb index 3f0ab39e..b13379db 100644 --- a/lib/scm/parsers/git_styled_parser.rb +++ b/lib/scm/parsers/git_styled_parser.rb @@ -42,9 +42,8 @@ def self.internal_parse(io, opts) elsif line =~ /^Author: (.+)$/ e.author_name = $1 elsif line =~ /^Date: (.*)$/ - # default to EPOCH when there's no date info - e.author_date = Time.at(0).utc if $1.strip.empty? - e.author_date ||= Time.parse($1).utc # Note strongly: MUST be RFC2822 format to parse properly + # MUST be RFC2822 format to parse properly, else defaults to epoch time + e.author_date = parse_commit_date($1) elsif line == "__BEGIN_COMMENT__" state = :message elsif line =~ /^AuthorEmail: (.+)$/ @@ -81,5 +80,10 @@ def self.internal_parse(io, opts) yield e if e end + + def self.parse_commit_date(date) + t = Time.rfc2822(date) rescue Time.at(0) + t.utc + end end end diff --git a/test/unit/git_styled_parser_test.rb b/test/unit/git_styled_parser_test.rb index 90b36c2c..c8f949cc 100644 --- a/test/unit/git_styled_parser_test.rb +++ b/test/unit/git_styled_parser_test.rb @@ -7,7 +7,7 @@ def test_empty_array assert_equal([], GitStyledParser.parse('')) end - def test_log_parser_no_date + def test_log_parser_nil_date sample_log = <<-SAMPLE __BEGIN_COMMIT__ Commit: 1df547800dcd168e589bb9b26b4039bff3a7f7e4 @@ -17,6 +17,24 @@ def test_log_parser_no_date __BEGIN_COMMENT__ moving COPYING +__END_COMMENT__ +SAMPLE + + commits = GitStyledParser.parse(sample_log) + assert_equal 1, commits.size + assert_equal Time.utc(1970,1,1,0,0,0), commits[0].author_date + end + + def test_log_parser_bogus_date +sample_log = <<-SAMPLE +__BEGIN_COMMIT__ +Commit: 1df547800dcd168e589bb9b26b4039bff3a7f7e4 +Author: Jason Allen +AuthorEmail: jason@ohloh.net +Date: Mon, Jan 01 2012 05:00:00 -0500 +__BEGIN_COMMENT__ + moving COPYING + __END_COMMENT__ SAMPLE From 1601672b4a5415efa55f11aa90d282d2cb6207ca Mon Sep 17 00:00:00 2001 From: Sathishkumar Natesan Date: Mon, 27 Jan 2014 18:17:58 -0500 Subject: [PATCH 148/219] OTWO-2996 Rename parse_commit_date to parse_date as it can be used to parse author/committer date --- lib/scm/parsers/git_styled_parser.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/scm/parsers/git_styled_parser.rb b/lib/scm/parsers/git_styled_parser.rb index b13379db..51ee194c 100644 --- a/lib/scm/parsers/git_styled_parser.rb +++ b/lib/scm/parsers/git_styled_parser.rb @@ -43,7 +43,7 @@ def self.internal_parse(io, opts) e.author_name = $1 elsif line =~ /^Date: (.*)$/ # MUST be RFC2822 format to parse properly, else defaults to epoch time - e.author_date = parse_commit_date($1) + e.author_date = parse_date($1) elsif line == "__BEGIN_COMMENT__" state = :message elsif line =~ /^AuthorEmail: (.+)$/ @@ -81,7 +81,7 @@ def self.internal_parse(io, opts) yield e if e end - def self.parse_commit_date(date) + def self.parse_date(date) t = Time.rfc2822(date) rescue Time.at(0) t.utc end From 969091f82f8cddebcbf126983352ca5093a37d27 Mon Sep 17 00:00:00 2001 From: Peter Degen-Portnoy Date: Fri, 21 Feb 2014 16:49:21 -0500 Subject: [PATCH 149/219] Change Git Validation to convert https and http protocols for git and web urls to git protocol --- lib/scm/adapters/git/validation.rb | 8 ++++-- test/unit/git_validation_test.rb | 45 ++++++++++++++++++++++-------- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/lib/scm/adapters/git/validation.rb b/lib/scm/adapters/git/validation.rb index 3f985bf9..90d99ee4 100644 --- a/lib/scm/adapters/git/validation.rb +++ b/lib/scm/adapters/git/validation.rb @@ -10,17 +10,19 @@ def self.public_url_regex def normalize super - @url = read_only_url + @url = normalize_url @branch_name = 'master' if @branch_name.to_s == '' self end # Given a Github read-write URL, return a read-only URL. # Otherwise, return the original URL. - def read_only_url + def normalize_url case @url - when /^https:\/\/\w+@github.com\/(.+)\.git$/ + when /^https?:\/\/\w+@github.com\/(.+)\.git$/ "git://github.com/#{$1}.git" + when /^https?:\/\/github.com\/(.+)/ + "git://github.com/#{$1}" when /^git@github.com:(.+)\.git$/ "git://github.com/#{$1}.git" else diff --git a/test/unit/git_validation_test.rb b/test/unit/git_validation_test.rb index a80b2e68..2bdba5bc 100644 --- a/test/unit/git_validation_test.rb +++ b/test/unit/git_validation_test.rb @@ -23,7 +23,11 @@ def test_accepted_urls "https://kernel.org/pub/scm/git/git.git", "https://kernel.org:8080/pub/scm/git/git.git", "git://kernel.org/~foo/git.git", - "http://git.onerussian.com/pub/deb/impose+.git" + "http://git.onerussian.com/pub/deb/impose+.git", + "https://Person@github.com/Person/some_repo.git", + "http://Person@github.com/Person/some_repo.git", + "https://github.com/Person/some_repo", + "http://github.com/Person/some_repo" ].each do |url| git = GitAdapter.new(:url => url) assert !git.validate_url @@ -41,32 +45,49 @@ def test_guess_forge assert_equal 'kernel.org', git.guess_forge end - def test_read_only_url - assert_equal nil, GitAdapter.new(:url => nil).read_only_url - assert_equal '', GitAdapter.new(:url => '').read_only_url - assert_equal 'foo', GitAdapter.new(:url => 'foo').read_only_url + def test_normalize_url + assert_equal nil, GitAdapter.new(:url => nil).normalize_url + assert_equal '', GitAdapter.new(:url => '').normalize_url + assert_equal 'foo', GitAdapter.new(:url => 'foo').normalize_url # A non-Github URL: no change assert_equal 'git://kernel.org/pub/scm/git/git.git', - GitAdapter.new(:url => 'git://kernel.org/pub/scm/git/git.git').read_only_url + GitAdapter.new(:url => 'git://kernel.org/pub/scm/git/git.git').normalize_url # A Github read-write URL: converted to read-only assert_equal 'git://github.com/robinluckey/ohcount.git', - GitAdapter.new(:url => 'https://robinluckey@github.com/robinluckey/ohcount.git').read_only_url + GitAdapter.new(:url => 'https://robinluckey@github.com/robinluckey/ohcount.git').normalize_url # A Github read-write URL: converted to read-only assert_equal 'git://github.com/robinluckey/ohcount.git', - GitAdapter.new(:url => 'git@github.com:robinluckey/ohcount.git').read_only_url + GitAdapter.new(:url => 'git@github.com:robinluckey/ohcount.git').normalize_url # A Github read-only URL: no change assert_equal 'git://github.com/robinluckey/ohcount.git', - GitAdapter.new(:url => 'git@github.com:robinluckey/ohcount.git').read_only_url + GitAdapter.new(:url => 'git@github.com:robinluckey/ohcount.git').normalize_url end def test_normalize_converts_to_read_only - git = GitAdapter.new(:url => 'https://robinluckey@github.com/robinluckey/ohcount.git') - git.normalize - assert_equal 'git://github.com/robinluckey/ohcount.git', git.url + normalize_url_test('https://robinluckey@github.com/robinluckey/ohcount.git', 'git://github.com/robinluckey/ohcount.git') + end + + def test_normalize_handles_https_with_user_at_github_format + normalize_url_test('http://Person@github.com/Person/something.git', 'git://github.com/Person/something.git') + end + + def test_normalize_handles_https_web_url + normalize_url_test('https://github.com/Person/something', 'git://github.com/Person/something') end + + def test_normalize_handles_http_web_url + normalize_url_test('http://github.com/Person/something', 'git://github.com/Person/something') + end + + private + def normalize_url_test(url, result_url) + git = GitAdapter.new(:url => url) + git.normalize + assert_equal result_url, git.url + end end end From 00a65c255c09d3a5717b246ec311b64138d2d40b Mon Sep 17 00:00:00 2001 From: Peter Degen-Portnoy Date: Fri, 21 Feb 2014 17:05:08 -0500 Subject: [PATCH 150/219] Update comment to reflect behavior of normalize_url method --- lib/scm/adapters/git/validation.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/scm/adapters/git/validation.rb b/lib/scm/adapters/git/validation.rb index 90d99ee4..eba20539 100644 --- a/lib/scm/adapters/git/validation.rb +++ b/lib/scm/adapters/git/validation.rb @@ -15,8 +15,10 @@ def normalize self end - # Given a Github read-write URL, return a read-only URL. - # Otherwise, return the original URL. + # Given a Github read-write URL, return a git protocol read-only URL + # Given a Github web URL, return a git protocol read-only URL + # Given a Git read-write protocol URL, return a git protocol read-only URL + # Else, return the URL def normalize_url case @url when /^https?:\/\/\w+@github.com\/(.+)\.git$/ From 1c371cada0b42c3a382938cd66c311198132556b Mon Sep 17 00:00:00 2001 From: Peter Degen-Portnoy Date: Thu, 6 Mar 2014 11:11:44 -0500 Subject: [PATCH 151/219] Normalize_Branch_Name: set the branch name when normalizing an SvnAdapter recalc_branch_name has to handle exceptions thrown when the URL is really a file system --- lib/scm/adapters/svn/misc.rb | 4 ++-- lib/scm/adapters/svn/validation.rb | 11 ++++++++--- test/unit/svn_validation_test.rb | 24 ++++++++++++++++++------ 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/lib/scm/adapters/svn/misc.rb b/lib/scm/adapters/svn/misc.rb index 13a2282c..351d8da7 100644 --- a/lib/scm/adapters/svn/misc.rb +++ b/lib/scm/adapters/svn/misc.rb @@ -35,10 +35,10 @@ def restrict_url_to_trunk if list.include? 'trunk/' self.url = File.join(self.url, 'trunk') - self.branch_name = File.join(self.branch_name, 'trunk') + self.branch_name = File.join(self.branch_name, 'trunk') if self.branch_name elsif list.size == 1 and list.first[-1..-1] == '/' self.url = File.join(self.url, list.first[0..-2]) - self.branch_name = File.join(self.branch_name, list.first[0..-2]) + self.branch_name = File.join(self.branch_name, list.first[0..-2]) if self.branch_name return restrict_url_to_trunk end self.url diff --git a/lib/scm/adapters/svn/validation.rb b/lib/scm/adapters/svn/validation.rb index 790d113d..152dd72d 100644 --- a/lib/scm/adapters/svn/validation.rb +++ b/lib/scm/adapters/svn/validation.rb @@ -12,7 +12,7 @@ def normalize super @url = path_to_file_url(@url) @url = force_https_if_sourceforge(@url) - @branch_name = @branch_name[0..-2] if @branch_name && @branch_name[-1..-1] == '/' + @branch_name = recalc_branch_name self end @@ -32,7 +32,7 @@ def path_to_file_url(path) def force_https_if_sourceforge(url) # SourceForge requires https for svnsync - url =~ /http(:\/\/.*svn\.sourceforge\.net.*)/ ? "https#{$1}" : url + url =~ /http(:\/\/.*svn\.(sourceforge|code\.sf)\.net.*)/ ? "https#{$1}" : url end def validate_server_connection @@ -54,7 +54,12 @@ def validate_server_connection # From the given URL, determine which part of it is the root and which part of it is the branch_name. # The current branch_name is overwritten. def recalc_branch_name - @branch_name = @url ? @url[root.length..-1] : @branch_name + begin + @branch_name = @url ? @url[root.length..-1] : @branch_name + rescue RuntimeError => exception + exception.message =~ /svn:*is not a working copy/ # we have a file system + @branch_name = '' + end @branch_name = @branch_name[0..-2] if @branch_name[-1..-1] == '/' @branch_name end diff --git a/test/unit/svn_validation_test.rb b/test/unit/svn_validation_test.rb index c41c5716..3147ca09 100644 --- a/test/unit/svn_validation_test.rb +++ b/test/unit/svn_validation_test.rb @@ -95,6 +95,9 @@ def test_guess_forge svn = SvnAdapter.new(:url => 'https://vegastrike.svn.sourceforge.net/svnroot/vegastrike/trunk') assert_equal 'sourceforge.net', svn.guess_forge + svn = SvnAdapter.new(:url => 'https://svn.code.sf.net/p/gallery/code/trunk/gallery2') + assert_equal 'code.sf.net', svn.guess_forge + svn = SvnAdapter.new(:url => 'https://appfuse.dev.java.net/svn/appfuse/trunk') assert_equal 'java.net', svn.guess_forge @@ -106,14 +109,13 @@ def test_guess_forge end def test_sourceforge_requires_https - assert_equal 'https://gallery.svn.sourceforge.net/svnroot/gallery/trunk/gallery2', - SvnAdapter.new(:url => 'http://gallery.svn.sourceforge.net/svnroot/gallery/trunk/gallery2').normalize.url + url = '://svn.code.sf.net/p/gallery/code/trunk/gallery2' + assert_equal "https#{url}", SvnAdapter.new(:url => "http#{url}").normalize.url - assert_equal 'https://gallery.svn.sourceforge.net/svnroot/gallery/trunk/gallery2', - SvnAdapter.new(:url => 'https://gallery.svn.sourceforge.net/svnroot/gallery/trunk/gallery2').normalize.url + assert_equal "https#{url}", SvnAdapter.new(:url => "https#{url}").normalize.url - assert_equal 'http://pianosa.googlecode.com/svn/trunk', - SvnAdapter.new(:url => 'http://pianosa.googlecode.com/svn/trunk').normalize.url + url = 'https://github.com/blackducksw/ohloh_scm/trunk' + assert_equal url, SvnAdapter.new(:url => url).normalize.url end def test_validate_server_connection @@ -145,6 +147,16 @@ def test_recalc_branch_name assert !svn_trunk_with_whack.branch_name assert_equal '/trunk', svn_trunk_with_whack.recalc_branch_name assert_equal '/trunk', svn_trunk_with_whack.branch_name + + svn_trunk = SvnAdapter.new(:url => svn.root + '/trunk') + assert !svn_trunk.branch_name + svn_trunk.normalize # only normalize to ensure branch_name is populated correctly + assert_equal '/trunk', svn_trunk.branch_name + + svn_trunk = SvnAdapter.new(:url => svn.root) + assert !svn_trunk.branch_name + svn_trunk.normalize + assert_equal '', svn_trunk.branch_name end end end From 4d46a0037d672c01de7afb4b56bb69e1cde71e30 Mon Sep 17 00:00:00 2001 From: Peter Degen-Portnoy Date: Tue, 11 Mar 2014 14:25:47 -0400 Subject: [PATCH 152/219] Normalize_Branch_Name Correct condition in recalc_branch_name Remove unneeded check for @branch_name in svn/misc.rb Handle file system based SVN URLs better --- lib/scm/adapters/svn/misc.rb | 4 ++-- lib/scm/adapters/svn/validation.rb | 19 ++++++++++++++----- test/unit/svn_validation_test.rb | 15 ++++++++++++--- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/lib/scm/adapters/svn/misc.rb b/lib/scm/adapters/svn/misc.rb index 351d8da7..13a2282c 100644 --- a/lib/scm/adapters/svn/misc.rb +++ b/lib/scm/adapters/svn/misc.rb @@ -35,10 +35,10 @@ def restrict_url_to_trunk if list.include? 'trunk/' self.url = File.join(self.url, 'trunk') - self.branch_name = File.join(self.branch_name, 'trunk') if self.branch_name + self.branch_name = File.join(self.branch_name, 'trunk') elsif list.size == 1 and list.first[-1..-1] == '/' self.url = File.join(self.url, list.first[0..-2]) - self.branch_name = File.join(self.branch_name, list.first[0..-2]) if self.branch_name + self.branch_name = File.join(self.branch_name, list.first[0..-2]) return restrict_url_to_trunk end self.url diff --git a/lib/scm/adapters/svn/validation.rb b/lib/scm/adapters/svn/validation.rb index 152dd72d..49a2d3ea 100644 --- a/lib/scm/adapters/svn/validation.rb +++ b/lib/scm/adapters/svn/validation.rb @@ -12,7 +12,11 @@ def normalize super @url = path_to_file_url(@url) @url = force_https_if_sourceforge(@url) - @branch_name = recalc_branch_name + if @branch_name + clean_branch_name + else + @branch_name = recalc_branch_name + end self end @@ -57,11 +61,10 @@ def recalc_branch_name begin @branch_name = @url ? @url[root.length..-1] : @branch_name rescue RuntimeError => exception - exception.message =~ /svn:*is not a working copy/ # we have a file system - @branch_name = '' + @branch_name = '' if exception.message =~ /(svn:*is not a working copy|Unable to open an ra_local session to URL)/ # we have a file system end - @branch_name = @branch_name[0..-2] if @branch_name[-1..-1] == '/' - @branch_name + clean_branch_name + @branch_name end def guess_forge @@ -74,5 +77,11 @@ def guess_forge u end end + + private + def clean_branch_name + return unless @branch_name + @branch_name.chop! if @branch_name.end_with?('/') + end end end diff --git a/test/unit/svn_validation_test.rb b/test/unit/svn_validation_test.rb index 3147ca09..9dda3215 100644 --- a/test/unit/svn_validation_test.rb +++ b/test/unit/svn_validation_test.rb @@ -159,9 +159,18 @@ def test_recalc_branch_name assert_equal '', svn_trunk.branch_name end end - end - def test_strip_trailing_whack_from_branch_name - assert_equal '/trunk', SvnAdapter.new(:branch_name => "/trunk/").normalize.branch_name + def test_strip_trailing_whack_from_branch_name + with_svn_repository('svn') do |svn| + assert_equal '/trunk', SvnAdapter.new(:url => svn.root, :branch_name => "/trunk/").normalize.branch_name + end + end + + def test_empty_branch_name_with_file_system + Scm::ScratchDir.new do |dir| + svn = SvnAdapter.new(:url => dir).normalize + assert_equal '', svn.branch_name + end + end end end From 6c53eec89b2a88004a45d51850c230ef209164a1 Mon Sep 17 00:00:00 2001 From: Peter Degen-Portnoy Date: Thu, 17 Jul 2014 14:01:55 -0400 Subject: [PATCH 153/219] Update library to run on Ruby 1.9 --- lib/scm.rb | 60 +++++++++++++-------------- lib/scm/adapters/abstract_adapter.rb | 8 ++-- lib/scm/adapters/bzr_adapter.rb | 14 +++---- lib/scm/adapters/bzrlib_adapter.rb | 6 +-- lib/scm/adapters/cvs_adapter.rb | 6 +-- lib/scm/adapters/git_adapter.rb | 20 ++++----- lib/scm/adapters/hg_adapter.rb | 16 +++---- lib/scm/adapters/hglib_adapter.rb | 6 +-- lib/scm/adapters/svn_adapter.rb | 16 +++---- lib/scm/adapters/svn_chain_adapter.rb | 6 +-- test/test_helper.rb | 2 +- test/unit/abstract_adapter_test.rb | 2 +- test/unit/adapter_factory_test.rb | 2 +- test/unit/array_writer_test.rb | 2 +- test/unit/bzr_cat_file_test.rb | 2 +- test/unit/bzr_commits_test.rb | 2 +- test/unit/bzr_head_test.rb | 2 +- test/unit/bzr_misc_test.rb | 2 +- test/unit/bzr_parser_test.rb | 2 +- test/unit/bzr_pull_test.rb | 2 +- test/unit/bzr_push_test.rb | 2 +- test/unit/bzr_validation_test.rb | 2 +- test/unit/bzr_xml_parser_test.rb | 2 +- test/unit/bzrlib_cat_file_test.rb | 2 +- test/unit/bzrlib_head_test.rb | 2 +- test/unit/cvs_branch_number_test.rb | 2 +- test/unit/cvs_commits_test.rb | 2 +- test/unit/cvs_convert_test.rb | 2 +- test/unit/cvs_misc_test.rb | 2 +- test/unit/cvs_parser_test.rb | 2 +- test/unit/cvs_validation_test.rb | 2 +- test/unit/git_cat_file_test.rb | 2 +- test/unit/git_commit_all_test.rb | 2 +- test/unit/git_commits_test.rb | 2 +- test/unit/git_head_test.rb | 2 +- test/unit/git_log_parser_test.rb | 2 +- test/unit/git_misc_test.rb | 2 +- test/unit/git_parser_test.rb | 2 +- test/unit/git_patch_test.rb | 2 +- test/unit/git_pull_test.rb | 2 +- test/unit/git_push_test.rb | 2 +- test/unit/git_rev_list_test.rb | 2 +- test/unit/git_styled_parser_test.rb | 2 +- test/unit/git_token_test.rb | 2 +- test/unit/git_validation_test.rb | 2 +- test/unit/hg_cat_file_test.rb | 2 +- test/unit/hg_commits_test.rb | 2 +- test/unit/hg_head_test.rb | 2 +- test/unit/hg_misc_test.rb | 2 +- test/unit/hg_parser_test.rb | 2 +- test/unit/hg_patch_test.rb | 2 +- test/unit/hg_pull_test.rb | 2 +- test/unit/hg_push_test.rb | 2 +- test/unit/hg_rev_list_test.rb | 2 +- test/unit/hg_validation_test.rb | 2 +- test/unit/hglib_cat_file_test.rb | 2 +- test/unit/hglib_head_test.rb | 2 +- test/unit/svn_cat_file_test.rb | 2 +- test/unit/svn_chain_cat_file_test.rb | 2 +- test/unit/svn_chain_commits_test.rb | 2 +- test/unit/svn_chain_test.rb | 2 +- test/unit/svn_commits_test.rb | 2 +- test/unit/svn_convert_test.rb | 2 +- test/unit/svn_head_test.rb | 2 +- test/unit/svn_misc_test.rb | 2 +- test/unit/svn_parser_test.rb | 2 +- test/unit/svn_patch_test.rb | 2 +- test/unit/svn_pull_test.rb | 2 +- test/unit/svn_push_test.rb | 2 +- test/unit/svn_validation_test.rb | 2 +- test/unit/svn_xml_parser_test.rb | 2 +- 71 files changed, 140 insertions(+), 140 deletions(-) diff --git a/lib/scm.rb b/lib/scm.rb index 60b014c8..c5365a02 100644 --- a/lib/scm.rb +++ b/lib/scm.rb @@ -1,38 +1,38 @@ module Scm end -require 'rbconfig' +#require 'rbconfig' -$: << File.join(File.dirname(__FILE__),"..") +#$: << File.join(File.dirname(__FILE__),"..") -require 'lib/scm/shellout' -require 'lib/scm/scratch_dir' -require 'lib/scm/commit' -require 'lib/scm/diff' +require_relative 'scm/shellout' +require_relative 'scm/scratch_dir' +require_relative 'scm/commit' +require_relative 'scm/diff' -require 'lib/scm/adapters/abstract_adapter' -require 'lib/scm/adapters/cvs_adapter' -require 'lib/scm/adapters/svn_adapter' -require 'lib/scm/adapters/svn_chain_adapter' -require 'lib/scm/adapters/git_adapter' -require 'lib/scm/adapters/hg_adapter' -require 'lib/scm/adapters/hglib_adapter' -require 'lib/scm/adapters/bzr_adapter' -require 'lib/scm/adapters/bzrlib_adapter' -require 'lib/scm/adapters/factory' +require_relative 'scm/adapters/abstract_adapter' +require_relative 'scm/adapters/cvs_adapter' +require_relative 'scm/adapters/svn_adapter' +require_relative 'scm/adapters/svn_chain_adapter' +require_relative 'scm/adapters/git_adapter' +require_relative 'scm/adapters/hg_adapter' +require_relative 'scm/adapters/hglib_adapter' +require_relative 'scm/adapters/bzr_adapter' +require_relative 'scm/adapters/bzrlib_adapter' +require_relative 'scm/adapters/factory' -require 'lib/scm/parsers/parser' -require 'lib/scm/parsers/branch_number' -require 'lib/scm/parsers/cvs_parser' -require 'lib/scm/parsers/svn_parser' -require 'lib/scm/parsers/svn_xml_parser' -require 'lib/scm/parsers/git_parser' -require 'lib/scm/parsers/git_styled_parser' -require 'lib/scm/parsers/hg_parser' -require 'lib/scm/parsers/hg_styled_parser' -require 'lib/scm/parsers/bzr_xml_parser' -require 'lib/scm/parsers/bzr_parser' +require_relative 'scm/parsers/parser' +require_relative 'scm/parsers/branch_number' +require_relative 'scm/parsers/cvs_parser' +require_relative 'scm/parsers/svn_parser' +require_relative 'scm/parsers/svn_xml_parser' +require_relative 'scm/parsers/git_parser' +require_relative 'scm/parsers/git_styled_parser' +require_relative 'scm/parsers/hg_parser' +require_relative 'scm/parsers/hg_styled_parser' +require_relative 'scm/parsers/bzr_xml_parser' +require_relative 'scm/parsers/bzr_parser' -require 'lib/scm/parsers/array_writer' -require 'lib/scm/parsers/xml_writer' -require 'lib/scm/parsers/human_writer' +require_relative 'scm/parsers/array_writer' +require_relative 'scm/parsers/xml_writer' +require_relative 'scm/parsers/human_writer' diff --git a/lib/scm/adapters/abstract_adapter.rb b/lib/scm/adapters/abstract_adapter.rb index 4fe9f171..361b5b4e 100644 --- a/lib/scm/adapters/abstract_adapter.rb +++ b/lib/scm/adapters/abstract_adapter.rb @@ -16,7 +16,7 @@ class << self end end -require 'lib/scm/adapters/abstract/system' -require 'lib/scm/adapters/abstract/validation' -require 'lib/scm/adapters/abstract/sha1' -require 'lib/scm/adapters/abstract/misc' +require_relative 'abstract/system' +require_relative 'abstract/validation' +require_relative 'abstract/sha1' +require_relative 'abstract/misc' diff --git a/lib/scm/adapters/bzr_adapter.rb b/lib/scm/adapters/bzr_adapter.rb index def60a3f..ef0e81f0 100644 --- a/lib/scm/adapters/bzr_adapter.rb +++ b/lib/scm/adapters/bzr_adapter.rb @@ -6,10 +6,10 @@ def english_name end end -require 'lib/scm/adapters/bzr/validation' -require 'lib/scm/adapters/bzr/commits' -require 'lib/scm/adapters/bzr/head' -require 'lib/scm/adapters/bzr/cat_file' -require 'lib/scm/adapters/bzr/misc' -require 'lib/scm/adapters/bzr/pull' -require 'lib/scm/adapters/bzr/push' +require_relative 'bzr/validation' +require_relative 'bzr/commits' +require_relative 'bzr/head' +require_relative 'bzr/cat_file' +require_relative 'bzr/misc' +require_relative 'bzr/pull' +require_relative 'bzr/push' diff --git a/lib/scm/adapters/bzrlib_adapter.rb b/lib/scm/adapters/bzrlib_adapter.rb index 5cfdb342..c836026a 100644 --- a/lib/scm/adapters/bzrlib_adapter.rb +++ b/lib/scm/adapters/bzrlib_adapter.rb @@ -1,6 +1,6 @@ require 'rubygems' -require 'lib/scm/adapters/bzrlib/bzrlib_pipe_client' +require_relative 'bzrlib/bzrlib_pipe_client' module Scm::Adapters class BzrlibAdapter < BzrAdapter @@ -21,5 +21,5 @@ def cleanup end end -require 'lib/scm/adapters/bzrlib/head' -require 'lib/scm/adapters/bzrlib/cat_file' +require_relative 'bzrlib/head' +require_relative 'bzrlib/cat_file' diff --git a/lib/scm/adapters/cvs_adapter.rb b/lib/scm/adapters/cvs_adapter.rb index ce78e70d..3fd76ced 100644 --- a/lib/scm/adapters/cvs_adapter.rb +++ b/lib/scm/adapters/cvs_adapter.rb @@ -13,6 +13,6 @@ def initialize(params={}) end end -require 'lib/scm/adapters/cvs/validation' -require 'lib/scm/adapters/cvs/commits' -require 'lib/scm/adapters/cvs/misc' +require_relative 'cvs/validation' +require_relative 'cvs/commits' +require_relative 'cvs/misc' diff --git a/lib/scm/adapters/git_adapter.rb b/lib/scm/adapters/git_adapter.rb index f942a576..61ae04a3 100644 --- a/lib/scm/adapters/git_adapter.rb +++ b/lib/scm/adapters/git_adapter.rb @@ -6,13 +6,13 @@ def english_name end end -require 'lib/scm/adapters/git/validation' -require 'lib/scm/adapters/git/cat_file' -require 'lib/scm/adapters/git/commits' -require 'lib/scm/adapters/git/commit_all' -require 'lib/scm/adapters/git/token' -require 'lib/scm/adapters/git/push' -require 'lib/scm/adapters/git/pull' -require 'lib/scm/adapters/git/head' -require 'lib/scm/adapters/git/misc' -require 'lib/scm/adapters/git/patch' +require_relative 'git/validation' +require_relative 'git/cat_file' +require_relative 'git/commits' +require_relative 'git/commit_all' +require_relative 'git/token' +require_relative 'git/push' +require_relative 'git/pull' +require_relative 'git/head' +require_relative 'git/misc' +require_relative 'git/patch' diff --git a/lib/scm/adapters/hg_adapter.rb b/lib/scm/adapters/hg_adapter.rb index 2853305b..0629aa46 100644 --- a/lib/scm/adapters/hg_adapter.rb +++ b/lib/scm/adapters/hg_adapter.rb @@ -6,11 +6,11 @@ def english_name end end -require 'lib/scm/adapters/hg/validation' -require 'lib/scm/adapters/hg/cat_file' -require 'lib/scm/adapters/hg/commits' -require 'lib/scm/adapters/hg/misc' -require 'lib/scm/adapters/hg/pull' -require 'lib/scm/adapters/hg/push' -require 'lib/scm/adapters/hg/head' -require 'lib/scm/adapters/hg/patch' +require_relative 'hg/validation' +require_relative 'hg/cat_file' +require_relative 'hg/commits' +require_relative 'hg/misc' +require_relative 'hg/pull' +require_relative 'hg/push' +require_relative 'hg/head' +require_relative 'hg/patch' diff --git a/lib/scm/adapters/hglib_adapter.rb b/lib/scm/adapters/hglib_adapter.rb index 0a153628..cb5d8b0c 100644 --- a/lib/scm/adapters/hglib_adapter.rb +++ b/lib/scm/adapters/hglib_adapter.rb @@ -1,5 +1,5 @@ require 'rubygems' -require 'lib/scm/adapters/hglib/client' +require_relative 'hglib/client' module Scm::Adapters class HglibAdapter < HgAdapter @@ -21,5 +21,5 @@ def cleanup end end -require 'lib/scm/adapters/hglib/cat_file' -require 'lib/scm/adapters/hglib/head' +require_relative 'hglib/cat_file' +require_relative 'hglib/head' diff --git a/lib/scm/adapters/svn_adapter.rb b/lib/scm/adapters/svn_adapter.rb index e8f28d5d..92a9e908 100644 --- a/lib/scm/adapters/svn_adapter.rb +++ b/lib/scm/adapters/svn_adapter.rb @@ -6,12 +6,12 @@ def english_name end end -require 'lib/scm/adapters/svn/validation' -require 'lib/scm/adapters/svn/cat_file' -require 'lib/scm/adapters/svn/commits' -require 'lib/scm/adapters/svn/push' -require 'lib/scm/adapters/svn/pull' -require 'lib/scm/adapters/svn/head' -require 'lib/scm/adapters/svn/misc' -require 'lib/scm/adapters/svn/patch' +require_relative 'svn/validation' +require_relative 'svn/cat_file' +require_relative 'svn/commits' +require_relative 'svn/push' +require_relative 'svn/pull' +require_relative 'svn/head' +require_relative 'svn/misc' +require_relative 'svn/patch' diff --git a/lib/scm/adapters/svn_chain_adapter.rb b/lib/scm/adapters/svn_chain_adapter.rb index 4d6cf6c2..0f694d7a 100644 --- a/lib/scm/adapters/svn_chain_adapter.rb +++ b/lib/scm/adapters/svn_chain_adapter.rb @@ -39,6 +39,6 @@ class SvnChainAdapter < SvnAdapter end end -require 'lib/scm/adapters/svn_chain/chain' -require 'lib/scm/adapters/svn_chain/commits' -require 'lib/scm/adapters/svn_chain/cat_file' +require_relative 'svn_chain/chain' +require_relative 'svn_chain/commits' +require_relative 'svn_chain/cat_file' diff --git a/test/test_helper.rb b/test/test_helper.rb index 797d2f69..7aa1803b 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -5,7 +5,7 @@ unless defined?(TEST_DIR) TEST_DIR = File.dirname(__FILE__) end -require TEST_DIR + '/../lib/scm' +require_relative '../lib/scm' Scm::Adapters::AbstractAdapter.logger = Logger.new(File.open('log/test.log','a')) diff --git a/test/unit/abstract_adapter_test.rb b/test/unit/abstract_adapter_test.rb index 57023f54..d0f10ba7 100644 --- a/test/unit/abstract_adapter_test.rb +++ b/test/unit/abstract_adapter_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class AbstractAdapterTest < Scm::Test diff --git a/test/unit/adapter_factory_test.rb b/test/unit/adapter_factory_test.rb index 71e28622..d9934664 100644 --- a/test/unit/adapter_factory_test.rb +++ b/test/unit/adapter_factory_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class FactoryTest < Scm::Test diff --git a/test/unit/array_writer_test.rb b/test/unit/array_writer_test.rb index f8b1686b..97c3c673 100644 --- a/test/unit/array_writer_test.rb +++ b/test/unit/array_writer_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Parsers class ArrayWriterTest < Scm::Test diff --git a/test/unit/bzr_cat_file_test.rb b/test/unit/bzr_cat_file_test.rb index 50377c66..73e1b084 100644 --- a/test/unit/bzr_cat_file_test.rb +++ b/test/unit/bzr_cat_file_test.rb @@ -1,5 +1,5 @@ #encoding: utf-8 -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class BzrCatFileTest < Scm::Test diff --git a/test/unit/bzr_commits_test.rb b/test/unit/bzr_commits_test.rb index b8c0d5b0..490286f7 100644 --- a/test/unit/bzr_commits_test.rb +++ b/test/unit/bzr_commits_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class BzrCommitsTest < Scm::Test diff --git a/test/unit/bzr_head_test.rb b/test/unit/bzr_head_test.rb index 0becedd2..525d47ac 100644 --- a/test/unit/bzr_head_test.rb +++ b/test/unit/bzr_head_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class BzrHeadTest < Scm::Test diff --git a/test/unit/bzr_misc_test.rb b/test/unit/bzr_misc_test.rb index 5ca17d6e..17717cfb 100644 --- a/test/unit/bzr_misc_test.rb +++ b/test/unit/bzr_misc_test.rb @@ -1,5 +1,5 @@ #encoding: utf-8 -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class BzrMiscTest < Scm::Test diff --git a/test/unit/bzr_parser_test.rb b/test/unit/bzr_parser_test.rb index 5ed2716c..e208e999 100644 --- a/test/unit/bzr_parser_test.rb +++ b/test/unit/bzr_parser_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Parsers class BzrParserTest < Scm::Test diff --git a/test/unit/bzr_pull_test.rb b/test/unit/bzr_pull_test.rb index 77db85bc..690bc72b 100644 --- a/test/unit/bzr_pull_test.rb +++ b/test/unit/bzr_pull_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class BzrPullTest < Scm::Test diff --git a/test/unit/bzr_push_test.rb b/test/unit/bzr_push_test.rb index 05a35983..3d221fe5 100644 --- a/test/unit/bzr_push_test.rb +++ b/test/unit/bzr_push_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class BzrPushTest < Scm::Test diff --git a/test/unit/bzr_validation_test.rb b/test/unit/bzr_validation_test.rb index 8702542f..23e50376 100644 --- a/test/unit/bzr_validation_test.rb +++ b/test/unit/bzr_validation_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class BzrValidationTest < Scm::Test diff --git a/test/unit/bzr_xml_parser_test.rb b/test/unit/bzr_xml_parser_test.rb index 847be7b6..b78af68f 100644 --- a/test/unit/bzr_xml_parser_test.rb +++ b/test/unit/bzr_xml_parser_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Parsers class BzrXmlParserTest < Scm::Test diff --git a/test/unit/bzrlib_cat_file_test.rb b/test/unit/bzrlib_cat_file_test.rb index 6c43203f..ad1b1f9e 100644 --- a/test/unit/bzrlib_cat_file_test.rb +++ b/test/unit/bzrlib_cat_file_test.rb @@ -1,5 +1,5 @@ #encoding: utf-8 -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class BzrlibCatFileTest < Scm::Test diff --git a/test/unit/bzrlib_head_test.rb b/test/unit/bzrlib_head_test.rb index 1bc1fe85..f75946f9 100644 --- a/test/unit/bzrlib_head_test.rb +++ b/test/unit/bzrlib_head_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class BzrBzrlibHeadTest < Scm::Test diff --git a/test/unit/cvs_branch_number_test.rb b/test/unit/cvs_branch_number_test.rb index 272cc8da..8949ad2f 100644 --- a/test/unit/cvs_branch_number_test.rb +++ b/test/unit/cvs_branch_number_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Parsers class CvsBranchNumberTest < Scm::Test diff --git a/test/unit/cvs_commits_test.rb b/test/unit/cvs_commits_test.rb index 944b5a80..540bb24e 100644 --- a/test/unit/cvs_commits_test.rb +++ b/test/unit/cvs_commits_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class CvsCommitsTest < Scm::Test diff --git a/test/unit/cvs_convert_test.rb b/test/unit/cvs_convert_test.rb index 644ac025..860cd013 100644 --- a/test/unit/cvs_convert_test.rb +++ b/test/unit/cvs_convert_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class CvsConvertTest < Scm::Test diff --git a/test/unit/cvs_misc_test.rb b/test/unit/cvs_misc_test.rb index e1b0768e..67917591 100644 --- a/test/unit/cvs_misc_test.rb +++ b/test/unit/cvs_misc_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class CvsMiscTest < Scm::Test diff --git a/test/unit/cvs_parser_test.rb b/test/unit/cvs_parser_test.rb index ac3ae676..c3a37053 100644 --- a/test/unit/cvs_parser_test.rb +++ b/test/unit/cvs_parser_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Parsers class CvsParserTest < Scm::Test diff --git a/test/unit/cvs_validation_test.rb b/test/unit/cvs_validation_test.rb index 7047144b..e393b41b 100644 --- a/test/unit/cvs_validation_test.rb +++ b/test/unit/cvs_validation_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class CvsValidationTest < Scm::Test diff --git a/test/unit/git_cat_file_test.rb b/test/unit/git_cat_file_test.rb index 4e2b0a2d..10cbd4a4 100644 --- a/test/unit/git_cat_file_test.rb +++ b/test/unit/git_cat_file_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class GitCatFileTest < Scm::Test diff --git a/test/unit/git_commit_all_test.rb b/test/unit/git_commit_all_test.rb index 0fdb111b..5b9b0ead 100644 --- a/test/unit/git_commit_all_test.rb +++ b/test/unit/git_commit_all_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class GitCommitAllTest < Scm::Test diff --git a/test/unit/git_commits_test.rb b/test/unit/git_commits_test.rb index 1a39a872..b4b9bbc5 100644 --- a/test/unit/git_commits_test.rb +++ b/test/unit/git_commits_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class GitCommitsTest < Scm::Test diff --git a/test/unit/git_head_test.rb b/test/unit/git_head_test.rb index ca5bec94..438687c2 100644 --- a/test/unit/git_head_test.rb +++ b/test/unit/git_head_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class GitHeadTest < Scm::Test diff --git a/test/unit/git_log_parser_test.rb b/test/unit/git_log_parser_test.rb index ddfe067b..df2252c9 100644 --- a/test/unit/git_log_parser_test.rb +++ b/test/unit/git_log_parser_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' require 'date' module Scm::Parsers diff --git a/test/unit/git_misc_test.rb b/test/unit/git_misc_test.rb index 55f77db4..b2996616 100644 --- a/test/unit/git_misc_test.rb +++ b/test/unit/git_misc_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class GitMiscTest < Scm::Test diff --git a/test/unit/git_parser_test.rb b/test/unit/git_parser_test.rb index e1293d39..962aae7d 100644 --- a/test/unit/git_parser_test.rb +++ b/test/unit/git_parser_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Parsers class GitParserTest < Scm::Test diff --git a/test/unit/git_patch_test.rb b/test/unit/git_patch_test.rb index 0ec6629a..ddcb5e46 100644 --- a/test/unit/git_patch_test.rb +++ b/test/unit/git_patch_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class GitPatchTest < Scm::Test diff --git a/test/unit/git_pull_test.rb b/test/unit/git_pull_test.rb index e39e210d..0534b605 100644 --- a/test/unit/git_pull_test.rb +++ b/test/unit/git_pull_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class GitPullTest < Scm::Test diff --git a/test/unit/git_push_test.rb b/test/unit/git_push_test.rb index 209830c8..52e6e8ae 100644 --- a/test/unit/git_push_test.rb +++ b/test/unit/git_push_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class GitPushTest < Scm::Test diff --git a/test/unit/git_rev_list_test.rb b/test/unit/git_rev_list_test.rb index 184720fd..f9244f0e 100644 --- a/test/unit/git_rev_list_test.rb +++ b/test/unit/git_rev_list_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters # Repository git_walk has the following structure: diff --git a/test/unit/git_styled_parser_test.rb b/test/unit/git_styled_parser_test.rb index c8f949cc..12e91b70 100644 --- a/test/unit/git_styled_parser_test.rb +++ b/test/unit/git_styled_parser_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Parsers class GitStyledParserTest < Scm::Test diff --git a/test/unit/git_token_test.rb b/test/unit/git_token_test.rb index b2370503..88be81d4 100644 --- a/test/unit/git_token_test.rb +++ b/test/unit/git_token_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class GitTokenTest < Scm::Test diff --git a/test/unit/git_validation_test.rb b/test/unit/git_validation_test.rb index 2bdba5bc..bf8b426f 100644 --- a/test/unit/git_validation_test.rb +++ b/test/unit/git_validation_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class GitValidationTest < Scm::Test diff --git a/test/unit/hg_cat_file_test.rb b/test/unit/hg_cat_file_test.rb index 7c60210d..013ca9de 100644 --- a/test/unit/hg_cat_file_test.rb +++ b/test/unit/hg_cat_file_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class HgCatFileTest < Scm::Test diff --git a/test/unit/hg_commits_test.rb b/test/unit/hg_commits_test.rb index 65f87b46..2771b498 100644 --- a/test/unit/hg_commits_test.rb +++ b/test/unit/hg_commits_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class HgCommitsTest < Scm::Test diff --git a/test/unit/hg_head_test.rb b/test/unit/hg_head_test.rb index 4fa5521b..f8a13586 100644 --- a/test/unit/hg_head_test.rb +++ b/test/unit/hg_head_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class HgHeadTest < Scm::Test diff --git a/test/unit/hg_misc_test.rb b/test/unit/hg_misc_test.rb index ce436a5e..fb371c56 100644 --- a/test/unit/hg_misc_test.rb +++ b/test/unit/hg_misc_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class HgMiscTest < Scm::Test diff --git a/test/unit/hg_parser_test.rb b/test/unit/hg_parser_test.rb index 32f5ac55..23408d7a 100644 --- a/test/unit/hg_parser_test.rb +++ b/test/unit/hg_parser_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Parsers class HgParserTest < Scm::Test diff --git a/test/unit/hg_patch_test.rb b/test/unit/hg_patch_test.rb index af7df910..655e9a90 100644 --- a/test/unit/hg_patch_test.rb +++ b/test/unit/hg_patch_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class HgPatchTest < Scm::Test diff --git a/test/unit/hg_pull_test.rb b/test/unit/hg_pull_test.rb index aabba011..ee36b905 100644 --- a/test/unit/hg_pull_test.rb +++ b/test/unit/hg_pull_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class HgPullTest < Scm::Test diff --git a/test/unit/hg_push_test.rb b/test/unit/hg_push_test.rb index e73b5b34..e987de3e 100644 --- a/test/unit/hg_push_test.rb +++ b/test/unit/hg_push_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class HgPushTest < Scm::Test diff --git a/test/unit/hg_rev_list_test.rb b/test/unit/hg_rev_list_test.rb index a0250df1..d8c2ff6c 100644 --- a/test/unit/hg_rev_list_test.rb +++ b/test/unit/hg_rev_list_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters # Repository hg_walk has the following structure: diff --git a/test/unit/hg_validation_test.rb b/test/unit/hg_validation_test.rb index f0385afc..4e6f77f0 100644 --- a/test/unit/hg_validation_test.rb +++ b/test/unit/hg_validation_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class HgValidationTest < Scm::Test diff --git a/test/unit/hglib_cat_file_test.rb b/test/unit/hglib_cat_file_test.rb index b110d0a9..c65611d8 100644 --- a/test/unit/hglib_cat_file_test.rb +++ b/test/unit/hglib_cat_file_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class HglibCatFileTest < Scm::Test diff --git a/test/unit/hglib_head_test.rb b/test/unit/hglib_head_test.rb index f10ed0ed..0491553f 100644 --- a/test/unit/hglib_head_test.rb +++ b/test/unit/hglib_head_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class HgHeadTest < Scm::Test diff --git a/test/unit/svn_cat_file_test.rb b/test/unit/svn_cat_file_test.rb index f7e47ea0..7fd93be1 100644 --- a/test/unit/svn_cat_file_test.rb +++ b/test/unit/svn_cat_file_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class SvnCatFileTest < Scm::Test diff --git a/test/unit/svn_chain_cat_file_test.rb b/test/unit/svn_chain_cat_file_test.rb index 579397f6..33759c3c 100644 --- a/test/unit/svn_chain_cat_file_test.rb +++ b/test/unit/svn_chain_cat_file_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class SvnChainCatFileTest < Scm::Test diff --git a/test/unit/svn_chain_commits_test.rb b/test/unit/svn_chain_commits_test.rb index 5ceaaa6c..6e4f890f 100644 --- a/test/unit/svn_chain_commits_test.rb +++ b/test/unit/svn_chain_commits_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Parsers class SvnChainTest < Scm::Test diff --git a/test/unit/svn_chain_test.rb b/test/unit/svn_chain_test.rb index 22a74da3..44cdb7c5 100644 --- a/test/unit/svn_chain_test.rb +++ b/test/unit/svn_chain_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Parsers class SvnChainTest < Scm::Test diff --git a/test/unit/svn_commits_test.rb b/test/unit/svn_commits_test.rb index 582dc336..b0eb7301 100644 --- a/test/unit/svn_commits_test.rb +++ b/test/unit/svn_commits_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class SvnCommitsTest < Scm::Test diff --git a/test/unit/svn_convert_test.rb b/test/unit/svn_convert_test.rb index 3c5533c8..334991ce 100644 --- a/test/unit/svn_convert_test.rb +++ b/test/unit/svn_convert_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class SvnConvertTest < Scm::Test diff --git a/test/unit/svn_head_test.rb b/test/unit/svn_head_test.rb index 0edf0cc9..9e95ffd9 100644 --- a/test/unit/svn_head_test.rb +++ b/test/unit/svn_head_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class SvnHeadTest < Scm::Test diff --git a/test/unit/svn_misc_test.rb b/test/unit/svn_misc_test.rb index e5404d10..13c5589d 100644 --- a/test/unit/svn_misc_test.rb +++ b/test/unit/svn_misc_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class SvnMiscTest < Scm::Test diff --git a/test/unit/svn_parser_test.rb b/test/unit/svn_parser_test.rb index 09790fd9..e91a7ff2 100644 --- a/test/unit/svn_parser_test.rb +++ b/test/unit/svn_parser_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Parsers class SvnParserTest < Scm::Test diff --git a/test/unit/svn_patch_test.rb b/test/unit/svn_patch_test.rb index c7118a46..21ffbd92 100644 --- a/test/unit/svn_patch_test.rb +++ b/test/unit/svn_patch_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class SvnPatchTest < Scm::Test diff --git a/test/unit/svn_pull_test.rb b/test/unit/svn_pull_test.rb index 61de105e..8040fd03 100644 --- a/test/unit/svn_pull_test.rb +++ b/test/unit/svn_pull_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' require 'socket' module Scm::Adapters diff --git a/test/unit/svn_push_test.rb b/test/unit/svn_push_test.rb index e945e22b..f431f4a2 100644 --- a/test/unit/svn_push_test.rb +++ b/test/unit/svn_push_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' require 'socket' module Scm::Adapters diff --git a/test/unit/svn_validation_test.rb b/test/unit/svn_validation_test.rb index 9dda3215..50602fe8 100644 --- a/test/unit/svn_validation_test.rb +++ b/test/unit/svn_validation_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Adapters class SvnValidationTest < Scm::Test diff --git a/test/unit/svn_xml_parser_test.rb b/test/unit/svn_xml_parser_test.rb index 1eeb337d..39623cbe 100644 --- a/test/unit/svn_xml_parser_test.rb +++ b/test/unit/svn_xml_parser_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../test_helper' +require_relative '../test_helper' module Scm::Parsers class SvnXmlParserTest < Scm::Test From 85e71bf555d601d627cde729e05bbf645510f0fd Mon Sep 17 00:00:00 2001 From: Peter Degen-Portnoy Date: Thu, 17 Jul 2014 14:39:28 -0400 Subject: [PATCH 154/219] Add encoding specifier the BZR test files --- test/unit/bzr_cat_file_test.rb | 2 +- test/unit/bzr_misc_test.rb | 2 +- test/unit/bzrlib_cat_file_test.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unit/bzr_cat_file_test.rb b/test/unit/bzr_cat_file_test.rb index 73e1b084..83d5682d 100644 --- a/test/unit/bzr_cat_file_test.rb +++ b/test/unit/bzr_cat_file_test.rb @@ -1,4 +1,4 @@ -#encoding: utf-8 +# encoding: utf-8 require_relative '../test_helper' module Scm::Adapters diff --git a/test/unit/bzr_misc_test.rb b/test/unit/bzr_misc_test.rb index 17717cfb..d475b7fd 100644 --- a/test/unit/bzr_misc_test.rb +++ b/test/unit/bzr_misc_test.rb @@ -1,4 +1,4 @@ -#encoding: utf-8 +# encoding: utf-8 require_relative '../test_helper' module Scm::Adapters diff --git a/test/unit/bzrlib_cat_file_test.rb b/test/unit/bzrlib_cat_file_test.rb index ad1b1f9e..400e6b7f 100644 --- a/test/unit/bzrlib_cat_file_test.rb +++ b/test/unit/bzrlib_cat_file_test.rb @@ -1,4 +1,4 @@ -#encoding: utf-8 +# encoding: utf-8 require_relative '../test_helper' module Scm::Adapters From 2c2ac1463c13fcfedc36808eafd7580ddca9d420 Mon Sep 17 00:00:00 2001 From: Peter Degen-Portnoy Date: Thu, 14 Aug 2014 20:57:41 +0000 Subject: [PATCH 155/219] Fix test errors by updating SVN regex These changes update the Ohloh SCM so that it works with Ubuntu 14 and the current versions of the SCM libraries. --- lib/scm/adapters/abstract/system.rb | 2 +- lib/scm/adapters/svn/cat_file.rb | 2 +- lib/scm/adapters/svn/misc.rb | 6 +++--- lib/scm/shellout.rb | 26 ++++++++++++++------------ test/unit/svn_pull_test.rb | 5 +++-- 5 files changed, 22 insertions(+), 19 deletions(-) diff --git a/lib/scm/adapters/abstract/system.rb b/lib/scm/adapters/abstract/system.rb index 766e993a..aa223d0b 100644 --- a/lib/scm/adapters/abstract/system.rb +++ b/lib/scm/adapters/abstract/system.rb @@ -17,7 +17,7 @@ def logger # Raises an exception if the shell returns non-zero exit code. def self.run(cmd) logger.debug { cmd } - status, out, err = Shellout.new.run(cmd) + status, out, err = Shellout.execute(cmd) raise RuntimeError.new("#{cmd} failed: #{out}\n#{err}") if status.exitstatus != 0 out end diff --git a/lib/scm/adapters/svn/cat_file.rb b/lib/scm/adapters/svn/cat_file.rb index 4b2432b6..b1712060 100644 --- a/lib/scm/adapters/svn/cat_file.rb +++ b/lib/scm/adapters/svn/cat_file.rb @@ -12,7 +12,7 @@ def cat(path, revision) begin run "svn cat --trust-server-cert --non-interactive -r #{revision} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name.to_s, path.to_s))}@#{revision}'" rescue - raise unless $!.message =~ /svn: (File not found|.* is not a directory in filesystem)/ + raise unless $!.message =~ /svn:.*Could not cat all targets because some targets don't exist/ end end end diff --git a/lib/scm/adapters/svn/misc.rb b/lib/scm/adapters/svn/misc.rb index 13a2282c..a9398257 100644 --- a/lib/scm/adapters/svn/misc.rb +++ b/lib/scm/adapters/svn/misc.rb @@ -98,14 +98,14 @@ def ls(path=nil, revision=final_token || 'HEAD') end def node_kind(path=nil, revision=final_token || 'HEAD') - $1 if self.info(path, revision) =~ /^Node Kind: (.+)$/ + $1 if self.info(path, revision) =~ /Node Kind: (\w+)\W/ end def is_directory?(path=nil, revision=final_token || 'HEAD') begin return node_kind(path, revision) == 'directory' - rescue - if $!.message =~ /svn: .* is not a directory in filesystem/ || $!.message =~ /.*Not a valid URL.*/ + rescue Exception + if $!.message =~ /svn: E200009: Could not display info for all targets because some targets don't exist/ return false else raise diff --git a/lib/scm/shellout.rb b/lib/scm/shellout.rb index a7177413..9562beec 100644 --- a/lib/scm/shellout.rb +++ b/lib/scm/shellout.rb @@ -1,6 +1,6 @@ require 'rubygems' require 'stringio' -require 'open4' +require 'open3' class Shellout @@ -9,17 +9,19 @@ def self.relay src, dst end def self.execute(cmd) - outbuf = StringIO.new - errbuf = StringIO.new - status = Open4::popen4("sh") do | pid, stdin, stdout, stderr | - stdin.puts cmd - stdin.close - to = Thread.new { relay stdout, outbuf } - te = Thread.new { relay stderr, errbuf } - to.join - te.join - end - return status, outbuf.string, errbuf.string + out = '' + err = '' + exit_status = nil + Open3.popen3(cmd) { |stdin, stdout, stderr, wait_thread| + while line = stdout.gets + out << line + end + while line = stderr.gets + err << line + end + exit_status = wait_thread.value + } + return exit_status, out, err end def run(cmd) diff --git a/test/unit/svn_pull_test.rb b/test/unit/svn_pull_test.rb index 8040fd03..4ca959ab 100644 --- a/test/unit/svn_pull_test.rb +++ b/test/unit/svn_pull_test.rb @@ -14,8 +14,9 @@ def test_svnadmin_create assert svn.exist? # Ensure that revision properties are settable - svn.propset('foo','bar') - assert_equal 'bar', svn.propget('foo') + # Note that only valid properties can be set + svn.propset('log','bar') + assert_equal 'bar', svn.propget('log') end end From cad58ef3c2d5cd37eb2bf3b103157dab1a908b63 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Sun, 31 Aug 2014 19:16:28 +0530 Subject: [PATCH 156/219] OTWO-3206: Use cvs test repositories as a tarball This is to support filenames with invalid utf8 encoding in test repositories. If the repository is not tarballed, the filenames would be read by the rake task and throw an exception. --- test/repositories/cvs.tgz | Bin 0 -> 10054 bytes test/repositories/cvs/CVSROOT/.#checkoutlist | 13 -- test/repositories/cvs/CVSROOT/.#commit_email | 10 -- test/repositories/cvs/CVSROOT/.#commitinfo | 15 --- test/repositories/cvs/CVSROOT/.#config | 26 ---- test/repositories/cvs/CVSROOT/.#cvsrc | 0 test/repositories/cvs/CVSROOT/.#cvswrappers | 18 --- test/repositories/cvs/CVSROOT/.#historyinfo | 15 --- test/repositories/cvs/CVSROOT/.#keywords | 30 ----- test/repositories/cvs/CVSROOT/.#loginfo | 22 ---- test/repositories/cvs/CVSROOT/.#modules | 26 ---- test/repositories/cvs/CVSROOT/.#modules2 | 22 ---- test/repositories/cvs/CVSROOT/.#notify | 22 ---- test/repositories/cvs/CVSROOT/.#notify_email | 10 -- test/repositories/cvs/CVSROOT/.#postcommand | 14 --- test/repositories/cvs/CVSROOT/.#postmodule | 14 --- test/repositories/cvs/CVSROOT/.#precommand | 18 --- test/repositories/cvs/CVSROOT/.#premodule | 15 --- test/repositories/cvs/CVSROOT/.#rcsinfo | 10 -- test/repositories/cvs/CVSROOT/.#shadow | 7 -- test/repositories/cvs/CVSROOT/.#tag_email | 10 -- test/repositories/cvs/CVSROOT/.#taginfo | 21 ---- test/repositories/cvs/CVSROOT/.#triggers | 5 - test/repositories/cvs/CVSROOT/.#verifymsg | 17 --- .../repositories/cvs/CVSROOT/CVS/fileattr.xml | 15 --- test/repositories/cvs/CVSROOT/checkoutlist | 13 -- test/repositories/cvs/CVSROOT/checkoutlist,v | 39 ------ test/repositories/cvs/CVSROOT/commit_email | 10 -- test/repositories/cvs/CVSROOT/commit_email,v | 36 ------ test/repositories/cvs/CVSROOT/commitinfo | 15 --- test/repositories/cvs/CVSROOT/commitinfo,v | 41 ------- test/repositories/cvs/CVSROOT/config | 26 ---- test/repositories/cvs/CVSROOT/config,v | 51 -------- test/repositories/cvs/CVSROOT/cvsrc | 0 test/repositories/cvs/CVSROOT/cvsrc,v | 26 ---- test/repositories/cvs/CVSROOT/cvswrappers | 18 --- test/repositories/cvs/CVSROOT/cvswrappers,v | 44 ------- test/repositories/cvs/CVSROOT/historyinfo | 15 --- test/repositories/cvs/CVSROOT/historyinfo,v | 41 ------- test/repositories/cvs/CVSROOT/keywords | 30 ----- test/repositories/cvs/CVSROOT/keywords,v | 56 --------- test/repositories/cvs/CVSROOT/loginfo | 22 ---- test/repositories/cvs/CVSROOT/loginfo,v | 48 -------- test/repositories/cvs/CVSROOT/modules | 26 ---- test/repositories/cvs/CVSROOT/modules,v | 52 -------- test/repositories/cvs/CVSROOT/modules2 | 22 ---- test/repositories/cvs/CVSROOT/modules2,v | 48 -------- test/repositories/cvs/CVSROOT/notify | 22 ---- test/repositories/cvs/CVSROOT/notify,v | 48 -------- test/repositories/cvs/CVSROOT/notify_email | 10 -- test/repositories/cvs/CVSROOT/notify_email,v | 36 ------ test/repositories/cvs/CVSROOT/postcommand | 14 --- test/repositories/cvs/CVSROOT/postcommand,v | 40 ------- test/repositories/cvs/CVSROOT/postmodule | 14 --- test/repositories/cvs/CVSROOT/postmodule,v | 40 ------- test/repositories/cvs/CVSROOT/precommand | 18 --- test/repositories/cvs/CVSROOT/precommand,v | 44 ------- test/repositories/cvs/CVSROOT/premodule | 15 --- test/repositories/cvs/CVSROOT/premodule,v | 41 ------- test/repositories/cvs/CVSROOT/rcsinfo | 10 -- test/repositories/cvs/CVSROOT/rcsinfo,v | 36 ------ test/repositories/cvs/CVSROOT/shadow | 7 -- test/repositories/cvs/CVSROOT/shadow,v | 33 ----- test/repositories/cvs/CVSROOT/tag_email | 10 -- test/repositories/cvs/CVSROOT/tag_email,v | 36 ------ test/repositories/cvs/CVSROOT/taginfo | 21 ---- test/repositories/cvs/CVSROOT/taginfo,v | 47 -------- test/repositories/cvs/CVSROOT/triggers | 5 - test/repositories/cvs/CVSROOT/triggers,v | 31 ----- test/repositories/cvs/CVSROOT/val-tags | 2 - test/repositories/cvs/CVSROOT/verifymsg | 17 --- test/repositories/cvs/CVSROOT/verifymsg,v | 43 ------- test/repositories/cvs/simple/CVS/fileattr.xml | 6 - .../repositories/cvs/simple/another_file.rb,v | 113 ------------------ test/repositories/cvs/simple/foo.rb,v | 50 -------- .../cvs/simple/late_addition.rb,v | 93 -------------- test/repositories/cvs/simple/new_file.rb,v | 112 ----------------- 77 files changed, 2068 deletions(-) create mode 100644 test/repositories/cvs.tgz delete mode 100644 test/repositories/cvs/CVSROOT/.#checkoutlist delete mode 100644 test/repositories/cvs/CVSROOT/.#commit_email delete mode 100644 test/repositories/cvs/CVSROOT/.#commitinfo delete mode 100644 test/repositories/cvs/CVSROOT/.#config delete mode 100644 test/repositories/cvs/CVSROOT/.#cvsrc delete mode 100644 test/repositories/cvs/CVSROOT/.#cvswrappers delete mode 100644 test/repositories/cvs/CVSROOT/.#historyinfo delete mode 100644 test/repositories/cvs/CVSROOT/.#keywords delete mode 100644 test/repositories/cvs/CVSROOT/.#loginfo delete mode 100644 test/repositories/cvs/CVSROOT/.#modules delete mode 100644 test/repositories/cvs/CVSROOT/.#modules2 delete mode 100644 test/repositories/cvs/CVSROOT/.#notify delete mode 100644 test/repositories/cvs/CVSROOT/.#notify_email delete mode 100644 test/repositories/cvs/CVSROOT/.#postcommand delete mode 100644 test/repositories/cvs/CVSROOT/.#postmodule delete mode 100644 test/repositories/cvs/CVSROOT/.#precommand delete mode 100644 test/repositories/cvs/CVSROOT/.#premodule delete mode 100644 test/repositories/cvs/CVSROOT/.#rcsinfo delete mode 100644 test/repositories/cvs/CVSROOT/.#shadow delete mode 100644 test/repositories/cvs/CVSROOT/.#tag_email delete mode 100644 test/repositories/cvs/CVSROOT/.#taginfo delete mode 100644 test/repositories/cvs/CVSROOT/.#triggers delete mode 100644 test/repositories/cvs/CVSROOT/.#verifymsg delete mode 100644 test/repositories/cvs/CVSROOT/CVS/fileattr.xml delete mode 100644 test/repositories/cvs/CVSROOT/checkoutlist delete mode 100644 test/repositories/cvs/CVSROOT/checkoutlist,v delete mode 100644 test/repositories/cvs/CVSROOT/commit_email delete mode 100644 test/repositories/cvs/CVSROOT/commit_email,v delete mode 100644 test/repositories/cvs/CVSROOT/commitinfo delete mode 100644 test/repositories/cvs/CVSROOT/commitinfo,v delete mode 100644 test/repositories/cvs/CVSROOT/config delete mode 100644 test/repositories/cvs/CVSROOT/config,v delete mode 100644 test/repositories/cvs/CVSROOT/cvsrc delete mode 100644 test/repositories/cvs/CVSROOT/cvsrc,v delete mode 100644 test/repositories/cvs/CVSROOT/cvswrappers delete mode 100644 test/repositories/cvs/CVSROOT/cvswrappers,v delete mode 100644 test/repositories/cvs/CVSROOT/historyinfo delete mode 100644 test/repositories/cvs/CVSROOT/historyinfo,v delete mode 100644 test/repositories/cvs/CVSROOT/keywords delete mode 100644 test/repositories/cvs/CVSROOT/keywords,v delete mode 100644 test/repositories/cvs/CVSROOT/loginfo delete mode 100644 test/repositories/cvs/CVSROOT/loginfo,v delete mode 100644 test/repositories/cvs/CVSROOT/modules delete mode 100644 test/repositories/cvs/CVSROOT/modules,v delete mode 100644 test/repositories/cvs/CVSROOT/modules2 delete mode 100644 test/repositories/cvs/CVSROOT/modules2,v delete mode 100644 test/repositories/cvs/CVSROOT/notify delete mode 100644 test/repositories/cvs/CVSROOT/notify,v delete mode 100644 test/repositories/cvs/CVSROOT/notify_email delete mode 100644 test/repositories/cvs/CVSROOT/notify_email,v delete mode 100644 test/repositories/cvs/CVSROOT/postcommand delete mode 100644 test/repositories/cvs/CVSROOT/postcommand,v delete mode 100644 test/repositories/cvs/CVSROOT/postmodule delete mode 100644 test/repositories/cvs/CVSROOT/postmodule,v delete mode 100644 test/repositories/cvs/CVSROOT/precommand delete mode 100644 test/repositories/cvs/CVSROOT/precommand,v delete mode 100644 test/repositories/cvs/CVSROOT/premodule delete mode 100644 test/repositories/cvs/CVSROOT/premodule,v delete mode 100644 test/repositories/cvs/CVSROOT/rcsinfo delete mode 100644 test/repositories/cvs/CVSROOT/rcsinfo,v delete mode 100644 test/repositories/cvs/CVSROOT/shadow delete mode 100644 test/repositories/cvs/CVSROOT/shadow,v delete mode 100644 test/repositories/cvs/CVSROOT/tag_email delete mode 100644 test/repositories/cvs/CVSROOT/tag_email,v delete mode 100644 test/repositories/cvs/CVSROOT/taginfo delete mode 100644 test/repositories/cvs/CVSROOT/taginfo,v delete mode 100644 test/repositories/cvs/CVSROOT/triggers delete mode 100644 test/repositories/cvs/CVSROOT/triggers,v delete mode 100644 test/repositories/cvs/CVSROOT/val-tags delete mode 100644 test/repositories/cvs/CVSROOT/verifymsg delete mode 100644 test/repositories/cvs/CVSROOT/verifymsg,v delete mode 100644 test/repositories/cvs/simple/CVS/fileattr.xml delete mode 100644 test/repositories/cvs/simple/another_file.rb,v delete mode 100644 test/repositories/cvs/simple/foo.rb,v delete mode 100644 test/repositories/cvs/simple/late_addition.rb,v delete mode 100644 test/repositories/cvs/simple/new_file.rb,v diff --git a/test/repositories/cvs.tgz b/test/repositories/cvs.tgz new file mode 100644 index 0000000000000000000000000000000000000000..d047cc5894ddea0f2e7b79c4ea7a93be0a3b58f7 GIT binary patch literal 10054 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 Mhc!=u*3m%!2RY6LUH||9 literal 0 HcmV?d00001 diff --git a/test/repositories/cvs/CVSROOT/.#checkoutlist b/test/repositories/cvs/CVSROOT/.#checkoutlist deleted file mode 100644 index b04b3501..00000000 --- a/test/repositories/cvs/CVSROOT/.#checkoutlist +++ /dev/null @@ -1,13 +0,0 @@ -# The "checkoutlist" file is used to support additional version controlled -# administrative files in $CVSROOT/CVSROOT, such as template files. -# -# The first entry on a line is a filename which will be checked out from -# the corresponding RCS file in the $CVSROOT/CVSROOT directory. -# The remainder of the line is an error message to use if the file cannot -# be checked out. -# -# File format: -# -# [] -# -# comment lines begin with '#' diff --git a/test/repositories/cvs/CVSROOT/.#commit_email b/test/repositories/cvs/CVSROOT/.#commit_email deleted file mode 100644 index 63863618..00000000 --- a/test/repositories/cvs/CVSROOT/.#commit_email +++ /dev/null @@ -1,10 +0,0 @@ -# The "commit_email" file is used to control templates for emails sent -# during commit and import. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being made to, relative to the -# $CVSROOT. For the first match that is found, then the remainder of the -# line is the name of the file that contains the template. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. diff --git a/test/repositories/cvs/CVSROOT/.#commitinfo b/test/repositories/cvs/CVSROOT/.#commitinfo deleted file mode 100644 index 63ea65ad..00000000 --- a/test/repositories/cvs/CVSROOT/.#commitinfo +++ /dev/null @@ -1,15 +0,0 @@ -# The "commitinfo" file is used to control pre-commit checks. -# The filter on the right is invoked with the repository name. A list -# of files to check is passed to the standard input of the script. A non-zero -# exit of the filter program will cause the commit to be aborted. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/test/repositories/cvs/CVSROOT/.#config b/test/repositories/cvs/CVSROOT/.#config deleted file mode 100644 index af2a28c4..00000000 --- a/test/repositories/cvs/CVSROOT/.#config +++ /dev/null @@ -1,26 +0,0 @@ -# Set this to 'no' if pserver shouldn't check system users/passwords -#SystemAuth=yes - -# Set the Acl parsing type (none,compat,normal). -#AclMode=compat - -# Alternate location of CVS LockServer. Set to 'none' to disable.. -#LockServer=localhost:2402 - -# Set 'TopLevelAdmin' to 'yes' to create a CVS directory at the top -# level of the new working directory when using the 'cvs checkout' -# command. -#TopLevelAdmin=no - -# Set 'LogHistory' to 'all' or 'TOFEWGCMAR' to log all transactions to the -# history file, or a subset as needed (ie 'TMAR' logs all write operations) -#LogHistory=TOFEWGCMAR - -# Set 'RereadLogAfterVerify' to control rereading of the log file after a verifymsg -# 'always' or 'yes' to always reread the log regardless -# 'never' or 'no' (default) to never reread the log -#RereadLogAfterVerify=no - -# Set 'Watcher' to set a user who gets all notify events within the repository whether -# or not the ifle is watched. -#Watcher=watch_user \ No newline at end of file diff --git a/test/repositories/cvs/CVSROOT/.#cvsrc b/test/repositories/cvs/CVSROOT/.#cvsrc deleted file mode 100644 index e69de29b..00000000 diff --git a/test/repositories/cvs/CVSROOT/.#cvswrappers b/test/repositories/cvs/CVSROOT/.#cvswrappers deleted file mode 100644 index 11fa3b39..00000000 --- a/test/repositories/cvs/CVSROOT/.#cvswrappers +++ /dev/null @@ -1,18 +0,0 @@ -# This file affects handling of files based on their names. -# -# The -m option specifies whether CVS attempts to merge files. -# -# The -k option specifies keyword expansion (e.g. -kb for binary). -# -# The -t option overrides the default mime type. -# -# Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers) -# -# wildcard [option value][option value]... -# -# where option is one of -# -k expansion mode value: b, o, kkv, etc. -# -# and value is a single-quote delimited value. -# For example: -#*.gif -kb diff --git a/test/repositories/cvs/CVSROOT/.#historyinfo b/test/repositories/cvs/CVSROOT/.#historyinfo deleted file mode 100644 index 889ff1be..00000000 --- a/test/repositories/cvs/CVSROOT/.#historyinfo +++ /dev/null @@ -1,15 +0,0 @@ -# The "historyinfo" file is used to log the history file output. -# The filter on the right is invoked with the repository name. Its -# standard input contains the history line that has just been written -# to the history file (if it exists) -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/test/repositories/cvs/CVSROOT/.#keywords b/test/repositories/cvs/CVSROOT/.#keywords deleted file mode 100644 index a94adf4d..00000000 --- a/test/repositories/cvs/CVSROOT/.#keywords +++ /dev/null @@ -1,30 +0,0 @@ -# The "keywords" file is used to modify the standard set of RCS keywords -# or define entirely new ones. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being made to, relative to the -# $CVSROOT. Subsequent lines contain keyword definitions, indented by a space -# to separate them from module definitions -.# -# If the repository name does not match any of the definitions in this -# file, the "ALL" section is used, if it is specified. -# -# Any keyword with an empty definition is ignored. This can be used to selectively -# disable individual RCS keywords. -# -# The default defintions are: -# -#ALL -# Author %a -# Date %d -# Header %r/%p/%f %v %d %a %s %l -# CVSHeader %p/%f %v %d %a %s %l -# Id %f %v %d %a %s %l -# Locker %l -# Log %f -# Name %N -# RCSfile %f -# Revision %v -# Source %r/%p/%f -# State %s -# CommitId %C diff --git a/test/repositories/cvs/CVSROOT/.#loginfo b/test/repositories/cvs/CVSROOT/.#loginfo deleted file mode 100644 index f3c43297..00000000 --- a/test/repositories/cvs/CVSROOT/.#loginfo +++ /dev/null @@ -1,22 +0,0 @@ -# The "loginfo" file controls where "cvs commit" log information -# is sent. The first entry on a line is a regular expression which must match -# the directory that the change is being made to, relative to the -# $CVSROOT. If a match is found, then the remainder of the line is a filter -# program that should expect log information on its standard input. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name ALL appears as a regular expression it is always used -# in addition to the first matching regex or DEFAULT. -# -# You may specify a format string as part of the -# filter. The string is composed of a '%' followed -# by a single format character, or followed by a set of format -# characters surrounded by '{' and '}' as separators. The format -# characters are: -# -# s = file name -# V = old version number (pre-checkin) -# v = new version number (post-checkin) -# diff --git a/test/repositories/cvs/CVSROOT/.#modules b/test/repositories/cvs/CVSROOT/.#modules deleted file mode 100644 index cb9e9efc..00000000 --- a/test/repositories/cvs/CVSROOT/.#modules +++ /dev/null @@ -1,26 +0,0 @@ -# Three different line formats are valid: -# key -a aliases... -# key [options] directory -# key [options] directory files... -# -# Where "options" are composed of: -# -i prog Run "prog" on "cvs commit" from top-level of module. -# -o prog Run "prog" on "cvs checkout" of module. -# -e prog Run "prog" on "cvs export" of module. -# -t prog Run "prog" on "cvs rtag" of module. -# -u prog Run "prog" on "cvs update" of module. -# -d dir Place module in directory "dir" instead of module name. -# -l Top-level directory only -- do not recurse. -# -# NOTE: If you change any of the "Run" options above, you'll have to -# release and re-checkout any working directories of these modules. -# -# And "directory" is a path to a directory relative to $CVSROOT. -# -# The "-a" option specifies an alias. An alias is interpreted as if -# everything on the right of the "-a" had been typed on the command line. -# -# You can encode a module within a module by using the special '&' -# character to interpose another module into the current module. This -# can be useful for creating a module that consists of many directories -# spread out over the entire source repository. diff --git a/test/repositories/cvs/CVSROOT/.#modules2 b/test/repositories/cvs/CVSROOT/.#modules2 deleted file mode 100644 index 6cdc5bae..00000000 --- a/test/repositories/cvs/CVSROOT/.#modules2 +++ /dev/null @@ -1,22 +0,0 @@ -# *** modules2 currently has 'experimental' status. Testing is encouraged but. -# for greatest stability use the modules file. *** -# -# This file describes the layout of virtual directory structures -# within the repository. -# -# The layout is similar to a Windows .ini file. For example: -# -# [foo] -# dir1/dir2/dir3 = realdir1/realdir2 -# dir1/dir3 = !realdir1/realdir3 (^*js$|^*cpp$) -# -# [bar] -# / = realdir4 -# dir_to_delete = -# foo = foo -# -# The special character '!' stops recursion to directories below the one specified (-l option). -# The special character '+' stops parsing of that line, so that you can avoid infinte loops. -# -# Items in (...) are an extended regular expression applied to the filenames. All files which do not. -# match are ignored. diff --git a/test/repositories/cvs/CVSROOT/.#notify b/test/repositories/cvs/CVSROOT/.#notify deleted file mode 100644 index cdb3320c..00000000 --- a/test/repositories/cvs/CVSROOT/.#notify +++ /dev/null @@ -1,22 +0,0 @@ -# The "notify" file controls where notifications from watches set by -# "cvs watch add" or "cvs edit" are sent. The first entry on a line is -# a regular expression which is tested against the directory that the -# change is being made to, relative to the $CVSROOT. If it matches, -# then the remainder of the line is a filter program that should contain -# one occurrence of %s for the user to notify, and information on its -# standard input. -# -# "ALL" or "DEFAULT" can be used in place of the regular expression. -# -# You may specify a format string as part of the -# filter. The format characters are: -# -# s = user being notified -# b = Bug identifier -# m = Message supplied on command line -# d = Date of action -# u = User performing the unedit -# t = tag or branch being edited -# -# For example: -#ALL mail %s -s "CVS notification for bug %b" diff --git a/test/repositories/cvs/CVSROOT/.#notify_email b/test/repositories/cvs/CVSROOT/.#notify_email deleted file mode 100644 index c673ab4c..00000000 --- a/test/repositories/cvs/CVSROOT/.#notify_email +++ /dev/null @@ -1,10 +0,0 @@ -# The "notify_email" file is used to control templates for emails sent -# when notifying users. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being made to, relative to the -# $CVSROOT. For the first match that is found, then the remainder of the -# line is the name of the file that contains the template. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. diff --git a/test/repositories/cvs/CVSROOT/.#postcommand b/test/repositories/cvs/CVSROOT/.#postcommand deleted file mode 100644 index ab3ef145..00000000 --- a/test/repositories/cvs/CVSROOT/.#postcommand +++ /dev/null @@ -1,14 +0,0 @@ -# The "postcommand" file is run after a cvs command has finished. -# The filter on the right is invoked with the repository name and -# the name of the command that has been executed. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/test/repositories/cvs/CVSROOT/.#postmodule b/test/repositories/cvs/CVSROOT/.#postmodule deleted file mode 100644 index b6d258be..00000000 --- a/test/repositories/cvs/CVSROOT/.#postmodule +++ /dev/null @@ -1,14 +0,0 @@ -# The "postmodule" file is run after a cvs module is processed. -# The filter on the right is invoked with the repository name, -# the name of the command that has been executed, and the module name. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/test/repositories/cvs/CVSROOT/.#precommand b/test/repositories/cvs/CVSROOT/.#precommand deleted file mode 100644 index 05c8b890..00000000 --- a/test/repositories/cvs/CVSROOT/.#precommand +++ /dev/null @@ -1,18 +0,0 @@ -# The "precommand" file is run before a cvs command is executed. -# The filter on the right is invoked with the repository name and -# the name of the command that has been executed. A non-zero return -# value with abort the command with an error. -# -# The standard input of the filter receives each command argument, -# separated by linefeeds. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/test/repositories/cvs/CVSROOT/.#premodule b/test/repositories/cvs/CVSROOT/.#premodule deleted file mode 100644 index 4837892d..00000000 --- a/test/repositories/cvs/CVSROOT/.#premodule +++ /dev/null @@ -1,15 +0,0 @@ -# The "premodule" file is run before cvs module is processed. -# The filter on the right is invoked with the repository name, -# the name of the command that has been executed, and the module name. -# A non-zero return value with abort the command with an error. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/test/repositories/cvs/CVSROOT/.#rcsinfo b/test/repositories/cvs/CVSROOT/.#rcsinfo deleted file mode 100644 index 27c002f7..00000000 --- a/test/repositories/cvs/CVSROOT/.#rcsinfo +++ /dev/null @@ -1,10 +0,0 @@ -# The "rcsinfo" file is used to control templates with which the editor -# is invoked on commit and import. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being made to, relative to the -# $CVSROOT. For the first match that is found, then the remainder of the -# line is the name of the file that contains the template. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. diff --git a/test/repositories/cvs/CVSROOT/.#shadow b/test/repositories/cvs/CVSROOT/.#shadow deleted file mode 100644 index 7ccd24e2..00000000 --- a/test/repositories/cvs/CVSROOT/.#shadow +++ /dev/null @@ -1,7 +0,0 @@ -# The "shadow" file is used to control automatic checkouts. -# -# Each line has 3 parts: -# -# -# In common with other commit support files, use forward slashes -# and escape any spaces in filenames. diff --git a/test/repositories/cvs/CVSROOT/.#tag_email b/test/repositories/cvs/CVSROOT/.#tag_email deleted file mode 100644 index 48d545fe..00000000 --- a/test/repositories/cvs/CVSROOT/.#tag_email +++ /dev/null @@ -1,10 +0,0 @@ -# The "tag_email" file is used to control templates for emails sent -# during tagging operations. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being made to, relative to the -# $CVSROOT. For the first match that is found, then the remainder of the -# line is the name of the file that contains the template. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. diff --git a/test/repositories/cvs/CVSROOT/.#taginfo b/test/repositories/cvs/CVSROOT/.#taginfo deleted file mode 100644 index 3beb822e..00000000 --- a/test/repositories/cvs/CVSROOT/.#taginfo +++ /dev/null @@ -1,21 +0,0 @@ -# The "taginfo" file is used to control pre-tag checks. -# The filter on the right is invoked with the following arguments: -# -# $1 -- tagname -# $2 -- operation "add" for tag, "mov" for tag -F, and "del" for tag -d -# $3 -- repository -# -# The filter is passed a series of filename/version pairs on its standard input -# -# A non-zero exit of the filter program will cause the tag to be aborted. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/test/repositories/cvs/CVSROOT/.#triggers b/test/repositories/cvs/CVSROOT/.#triggers deleted file mode 100644 index 48a9fc33..00000000 --- a/test/repositories/cvs/CVSROOT/.#triggers +++ /dev/null @@ -1,5 +0,0 @@ -# The "triggers" file lists libraries which handle the events for each -# module. -# -# In addition to the lines here, the default_trigger library is loaded, if available. -# diff --git a/test/repositories/cvs/CVSROOT/.#verifymsg b/test/repositories/cvs/CVSROOT/.#verifymsg deleted file mode 100644 index 28b1d6ea..00000000 --- a/test/repositories/cvs/CVSROOT/.#verifymsg +++ /dev/null @@ -1,17 +0,0 @@ -# The "verifymsg" file is used to allow verification of logging -# information. It works best when a template (as specified in the -# rcsinfo file) is provided for the logging procedure. Given a -# template with locations for, a bug-id number, a list of people who -# reviewed the code before it can be checked in, and an external -# process to catalog the differences that were code reviewed, the -# following test can be applied to the code: -# -# Making sure that the entered bug-id number is correct. -# Validating that the code that was reviewed is indeed the code being -# checked in (using the bug-id number or a seperate review -# number to identify this particular code set.). -# -# If any of the above test failed, then the commit would be aborted. -# -# Actions such as mailing a copy of the report to each reviewer are -# better handled by an entry in the loginfo file. diff --git a/test/repositories/cvs/CVSROOT/CVS/fileattr.xml b/test/repositories/cvs/CVSROOT/CVS/fileattr.xml deleted file mode 100644 index 83ce5ca0..00000000 --- a/test/repositories/cvs/CVSROOT/CVS/fileattr.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - robin - - - - - - - - - - - diff --git a/test/repositories/cvs/CVSROOT/checkoutlist b/test/repositories/cvs/CVSROOT/checkoutlist deleted file mode 100644 index b04b3501..00000000 --- a/test/repositories/cvs/CVSROOT/checkoutlist +++ /dev/null @@ -1,13 +0,0 @@ -# The "checkoutlist" file is used to support additional version controlled -# administrative files in $CVSROOT/CVSROOT, such as template files. -# -# The first entry on a line is a filename which will be checked out from -# the corresponding RCS file in the $CVSROOT/CVSROOT directory. -# The remainder of the line is an error message to use if the file cannot -# be checked out. -# -# File format: -# -# [] -# -# comment lines begin with '#' diff --git a/test/repositories/cvs/CVSROOT/checkoutlist,v b/test/repositories/cvs/CVSROOT/checkoutlist,v deleted file mode 100644 index 13ddb4ff..00000000 --- a/test/repositories/cvs/CVSROOT/checkoutlist,v +++ /dev/null @@ -1,39 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# The "checkoutlist" file is used to support additional version controlled -# administrative files in $CVSROOT/CVSROOT, such as template files. -# -# The first entry on a line is a filename which will be checked out from -# the corresponding RCS file in the $CVSROOT/CVSROOT directory. -# The remainder of the line is an error message to use if the file cannot -# be checked out. -# -# File format: -# -# [] -# -# comment lines begin with '#' -@ - diff --git a/test/repositories/cvs/CVSROOT/commit_email b/test/repositories/cvs/CVSROOT/commit_email deleted file mode 100644 index 63863618..00000000 --- a/test/repositories/cvs/CVSROOT/commit_email +++ /dev/null @@ -1,10 +0,0 @@ -# The "commit_email" file is used to control templates for emails sent -# during commit and import. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being made to, relative to the -# $CVSROOT. For the first match that is found, then the remainder of the -# line is the name of the file that contains the template. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. diff --git a/test/repositories/cvs/CVSROOT/commit_email,v b/test/repositories/cvs/CVSROOT/commit_email,v deleted file mode 100644 index 79135d9e..00000000 --- a/test/repositories/cvs/CVSROOT/commit_email,v +++ /dev/null @@ -1,36 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# The "commit_email" file is used to control templates for emails sent -# during commit and import. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being made to, relative to the -# $CVSROOT. For the first match that is found, then the remainder of the -# line is the name of the file that contains the template. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -@ - diff --git a/test/repositories/cvs/CVSROOT/commitinfo b/test/repositories/cvs/CVSROOT/commitinfo deleted file mode 100644 index 63ea65ad..00000000 --- a/test/repositories/cvs/CVSROOT/commitinfo +++ /dev/null @@ -1,15 +0,0 @@ -# The "commitinfo" file is used to control pre-commit checks. -# The filter on the right is invoked with the repository name. A list -# of files to check is passed to the standard input of the script. A non-zero -# exit of the filter program will cause the commit to be aborted. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/test/repositories/cvs/CVSROOT/commitinfo,v b/test/repositories/cvs/CVSROOT/commitinfo,v deleted file mode 100644 index 62bf695b..00000000 --- a/test/repositories/cvs/CVSROOT/commitinfo,v +++ /dev/null @@ -1,41 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# The "commitinfo" file is used to control pre-commit checks. -# The filter on the right is invoked with the repository name. A list -# of files to check is passed to the standard input of the script. A non-zero -# exit of the filter program will cause the commit to be aborted. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". -@ - diff --git a/test/repositories/cvs/CVSROOT/config b/test/repositories/cvs/CVSROOT/config deleted file mode 100644 index af2a28c4..00000000 --- a/test/repositories/cvs/CVSROOT/config +++ /dev/null @@ -1,26 +0,0 @@ -# Set this to 'no' if pserver shouldn't check system users/passwords -#SystemAuth=yes - -# Set the Acl parsing type (none,compat,normal). -#AclMode=compat - -# Alternate location of CVS LockServer. Set to 'none' to disable.. -#LockServer=localhost:2402 - -# Set 'TopLevelAdmin' to 'yes' to create a CVS directory at the top -# level of the new working directory when using the 'cvs checkout' -# command. -#TopLevelAdmin=no - -# Set 'LogHistory' to 'all' or 'TOFEWGCMAR' to log all transactions to the -# history file, or a subset as needed (ie 'TMAR' logs all write operations) -#LogHistory=TOFEWGCMAR - -# Set 'RereadLogAfterVerify' to control rereading of the log file after a verifymsg -# 'always' or 'yes' to always reread the log regardless -# 'never' or 'no' (default) to never reread the log -#RereadLogAfterVerify=no - -# Set 'Watcher' to set a user who gets all notify events within the repository whether -# or not the ifle is watched. -#Watcher=watch_user \ No newline at end of file diff --git a/test/repositories/cvs/CVSROOT/config,v b/test/repositories/cvs/CVSROOT/config,v deleted file mode 100644 index 80bcd01f..00000000 --- a/test/repositories/cvs/CVSROOT/config,v +++ /dev/null @@ -1,51 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# Set this to 'no' if pserver shouldn't check system users/passwords -#SystemAuth=yes - -# Set the Acl parsing type (none,compat,normal). -#AclMode=compat - -# Alternate location of CVS LockServer. Set to 'none' to disable.. -#LockServer=localhost:2402 - -# Set 'TopLevelAdmin' to 'yes' to create a CVS directory at the top -# level of the new working directory when using the 'cvs checkout' -# command. -#TopLevelAdmin=no - -# Set 'LogHistory' to 'all' or 'TOFEWGCMAR' to log all transactions to the -# history file, or a subset as needed (ie 'TMAR' logs all write operations) -#LogHistory=TOFEWGCMAR - -# Set 'RereadLogAfterVerify' to control rereading of the log file after a verifymsg -# 'always' or 'yes' to always reread the log regardless -# 'never' or 'no' (default) to never reread the log -#RereadLogAfterVerify=no - -# Set 'Watcher' to set a user who gets all notify events within the repository whether -# or not the ifle is watched. -#Watcher=watch_user@ - diff --git a/test/repositories/cvs/CVSROOT/cvsrc b/test/repositories/cvs/CVSROOT/cvsrc deleted file mode 100644 index e69de29b..00000000 diff --git a/test/repositories/cvs/CVSROOT/cvsrc,v b/test/repositories/cvs/CVSROOT/cvsrc,v deleted file mode 100644 index 6e50ecf6..00000000 --- a/test/repositories/cvs/CVSROOT/cvsrc,v +++ /dev/null @@ -1,26 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@@ - diff --git a/test/repositories/cvs/CVSROOT/cvswrappers b/test/repositories/cvs/CVSROOT/cvswrappers deleted file mode 100644 index 11fa3b39..00000000 --- a/test/repositories/cvs/CVSROOT/cvswrappers +++ /dev/null @@ -1,18 +0,0 @@ -# This file affects handling of files based on their names. -# -# The -m option specifies whether CVS attempts to merge files. -# -# The -k option specifies keyword expansion (e.g. -kb for binary). -# -# The -t option overrides the default mime type. -# -# Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers) -# -# wildcard [option value][option value]... -# -# where option is one of -# -k expansion mode value: b, o, kkv, etc. -# -# and value is a single-quote delimited value. -# For example: -#*.gif -kb diff --git a/test/repositories/cvs/CVSROOT/cvswrappers,v b/test/repositories/cvs/CVSROOT/cvswrappers,v deleted file mode 100644 index badb2259..00000000 --- a/test/repositories/cvs/CVSROOT/cvswrappers,v +++ /dev/null @@ -1,44 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# This file affects handling of files based on their names. -# -# The -m option specifies whether CVS attempts to merge files. -# -# The -k option specifies keyword expansion (e.g. -kb for binary). -# -# The -t option overrides the default mime type. -# -# Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers) -# -# wildcard [option value][option value]... -# -# where option is one of -# -k expansion mode value: b, o, kkv, etc. -# -# and value is a single-quote delimited value. -# For example: -#*.gif -kb -@ - diff --git a/test/repositories/cvs/CVSROOT/historyinfo b/test/repositories/cvs/CVSROOT/historyinfo deleted file mode 100644 index 889ff1be..00000000 --- a/test/repositories/cvs/CVSROOT/historyinfo +++ /dev/null @@ -1,15 +0,0 @@ -# The "historyinfo" file is used to log the history file output. -# The filter on the right is invoked with the repository name. Its -# standard input contains the history line that has just been written -# to the history file (if it exists) -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/test/repositories/cvs/CVSROOT/historyinfo,v b/test/repositories/cvs/CVSROOT/historyinfo,v deleted file mode 100644 index 645bd87f..00000000 --- a/test/repositories/cvs/CVSROOT/historyinfo,v +++ /dev/null @@ -1,41 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# The "historyinfo" file is used to log the history file output. -# The filter on the right is invoked with the repository name. Its -# standard input contains the history line that has just been written -# to the history file (if it exists) -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". -@ - diff --git a/test/repositories/cvs/CVSROOT/keywords b/test/repositories/cvs/CVSROOT/keywords deleted file mode 100644 index a94adf4d..00000000 --- a/test/repositories/cvs/CVSROOT/keywords +++ /dev/null @@ -1,30 +0,0 @@ -# The "keywords" file is used to modify the standard set of RCS keywords -# or define entirely new ones. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being made to, relative to the -# $CVSROOT. Subsequent lines contain keyword definitions, indented by a space -# to separate them from module definitions -.# -# If the repository name does not match any of the definitions in this -# file, the "ALL" section is used, if it is specified. -# -# Any keyword with an empty definition is ignored. This can be used to selectively -# disable individual RCS keywords. -# -# The default defintions are: -# -#ALL -# Author %a -# Date %d -# Header %r/%p/%f %v %d %a %s %l -# CVSHeader %p/%f %v %d %a %s %l -# Id %f %v %d %a %s %l -# Locker %l -# Log %f -# Name %N -# RCSfile %f -# Revision %v -# Source %r/%p/%f -# State %s -# CommitId %C diff --git a/test/repositories/cvs/CVSROOT/keywords,v b/test/repositories/cvs/CVSROOT/keywords,v deleted file mode 100644 index 83f97ed2..00000000 --- a/test/repositories/cvs/CVSROOT/keywords,v +++ /dev/null @@ -1,56 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# The "keywords" file is used to modify the standard set of RCS keywords -# or define entirely new ones. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being made to, relative to the -# $CVSROOT. Subsequent lines contain keyword definitions, indented by a space -# to separate them from module definitions -.# -# If the repository name does not match any of the definitions in this -# file, the "ALL" section is used, if it is specified. -# -# Any keyword with an empty definition is ignored. This can be used to selectively -# disable individual RCS keywords. -# -# The default defintions are: -# -#ALL -# Author %a -# Date %d -# Header %r/%p/%f %v %d %a %s %l -# CVSHeader %p/%f %v %d %a %s %l -# Id %f %v %d %a %s %l -# Locker %l -# Log %f -# Name %N -# RCSfile %f -# Revision %v -# Source %r/%p/%f -# State %s -# CommitId %C -@ - diff --git a/test/repositories/cvs/CVSROOT/loginfo b/test/repositories/cvs/CVSROOT/loginfo deleted file mode 100644 index f3c43297..00000000 --- a/test/repositories/cvs/CVSROOT/loginfo +++ /dev/null @@ -1,22 +0,0 @@ -# The "loginfo" file controls where "cvs commit" log information -# is sent. The first entry on a line is a regular expression which must match -# the directory that the change is being made to, relative to the -# $CVSROOT. If a match is found, then the remainder of the line is a filter -# program that should expect log information on its standard input. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name ALL appears as a regular expression it is always used -# in addition to the first matching regex or DEFAULT. -# -# You may specify a format string as part of the -# filter. The string is composed of a '%' followed -# by a single format character, or followed by a set of format -# characters surrounded by '{' and '}' as separators. The format -# characters are: -# -# s = file name -# V = old version number (pre-checkin) -# v = new version number (post-checkin) -# diff --git a/test/repositories/cvs/CVSROOT/loginfo,v b/test/repositories/cvs/CVSROOT/loginfo,v deleted file mode 100644 index aac350e9..00000000 --- a/test/repositories/cvs/CVSROOT/loginfo,v +++ /dev/null @@ -1,48 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# The "loginfo" file controls where "cvs commit" log information -# is sent. The first entry on a line is a regular expression which must match -# the directory that the change is being made to, relative to the -# $CVSROOT. If a match is found, then the remainder of the line is a filter -# program that should expect log information on its standard input. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name ALL appears as a regular expression it is always used -# in addition to the first matching regex or DEFAULT. -# -# You may specify a format string as part of the -# filter. The string is composed of a '%' followed -# by a single format character, or followed by a set of format -# characters surrounded by '{' and '}' as separators. The format -# characters are: -# -# s = file name -# V = old version number (pre-checkin) -# v = new version number (post-checkin) -# -@ - diff --git a/test/repositories/cvs/CVSROOT/modules b/test/repositories/cvs/CVSROOT/modules deleted file mode 100644 index cb9e9efc..00000000 --- a/test/repositories/cvs/CVSROOT/modules +++ /dev/null @@ -1,26 +0,0 @@ -# Three different line formats are valid: -# key -a aliases... -# key [options] directory -# key [options] directory files... -# -# Where "options" are composed of: -# -i prog Run "prog" on "cvs commit" from top-level of module. -# -o prog Run "prog" on "cvs checkout" of module. -# -e prog Run "prog" on "cvs export" of module. -# -t prog Run "prog" on "cvs rtag" of module. -# -u prog Run "prog" on "cvs update" of module. -# -d dir Place module in directory "dir" instead of module name. -# -l Top-level directory only -- do not recurse. -# -# NOTE: If you change any of the "Run" options above, you'll have to -# release and re-checkout any working directories of these modules. -# -# And "directory" is a path to a directory relative to $CVSROOT. -# -# The "-a" option specifies an alias. An alias is interpreted as if -# everything on the right of the "-a" had been typed on the command line. -# -# You can encode a module within a module by using the special '&' -# character to interpose another module into the current module. This -# can be useful for creating a module that consists of many directories -# spread out over the entire source repository. diff --git a/test/repositories/cvs/CVSROOT/modules,v b/test/repositories/cvs/CVSROOT/modules,v deleted file mode 100644 index bced0056..00000000 --- a/test/repositories/cvs/CVSROOT/modules,v +++ /dev/null @@ -1,52 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# Three different line formats are valid: -# key -a aliases... -# key [options] directory -# key [options] directory files... -# -# Where "options" are composed of: -# -i prog Run "prog" on "cvs commit" from top-level of module. -# -o prog Run "prog" on "cvs checkout" of module. -# -e prog Run "prog" on "cvs export" of module. -# -t prog Run "prog" on "cvs rtag" of module. -# -u prog Run "prog" on "cvs update" of module. -# -d dir Place module in directory "dir" instead of module name. -# -l Top-level directory only -- do not recurse. -# -# NOTE: If you change any of the "Run" options above, you'll have to -# release and re-checkout any working directories of these modules. -# -# And "directory" is a path to a directory relative to $CVSROOT. -# -# The "-a" option specifies an alias. An alias is interpreted as if -# everything on the right of the "-a" had been typed on the command line. -# -# You can encode a module within a module by using the special '&' -# character to interpose another module into the current module. This -# can be useful for creating a module that consists of many directories -# spread out over the entire source repository. -@ - diff --git a/test/repositories/cvs/CVSROOT/modules2 b/test/repositories/cvs/CVSROOT/modules2 deleted file mode 100644 index 6cdc5bae..00000000 --- a/test/repositories/cvs/CVSROOT/modules2 +++ /dev/null @@ -1,22 +0,0 @@ -# *** modules2 currently has 'experimental' status. Testing is encouraged but. -# for greatest stability use the modules file. *** -# -# This file describes the layout of virtual directory structures -# within the repository. -# -# The layout is similar to a Windows .ini file. For example: -# -# [foo] -# dir1/dir2/dir3 = realdir1/realdir2 -# dir1/dir3 = !realdir1/realdir3 (^*js$|^*cpp$) -# -# [bar] -# / = realdir4 -# dir_to_delete = -# foo = foo -# -# The special character '!' stops recursion to directories below the one specified (-l option). -# The special character '+' stops parsing of that line, so that you can avoid infinte loops. -# -# Items in (...) are an extended regular expression applied to the filenames. All files which do not. -# match are ignored. diff --git a/test/repositories/cvs/CVSROOT/modules2,v b/test/repositories/cvs/CVSROOT/modules2,v deleted file mode 100644 index 0986d954..00000000 --- a/test/repositories/cvs/CVSROOT/modules2,v +++ /dev/null @@ -1,48 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# *** modules2 currently has 'experimental' status. Testing is encouraged but. -# for greatest stability use the modules file. *** -# -# This file describes the layout of virtual directory structures -# within the repository. -# -# The layout is similar to a Windows .ini file. For example: -# -# [foo] -# dir1/dir2/dir3 = realdir1/realdir2 -# dir1/dir3 = !realdir1/realdir3 (^*js$|^*cpp$) -# -# [bar] -# / = realdir4 -# dir_to_delete = -# foo = foo -# -# The special character '!' stops recursion to directories below the one specified (-l option). -# The special character '+' stops parsing of that line, so that you can avoid infinte loops. -# -# Items in (...) are an extended regular expression applied to the filenames. All files which do not. -# match are ignored. -@ - diff --git a/test/repositories/cvs/CVSROOT/notify b/test/repositories/cvs/CVSROOT/notify deleted file mode 100644 index cdb3320c..00000000 --- a/test/repositories/cvs/CVSROOT/notify +++ /dev/null @@ -1,22 +0,0 @@ -# The "notify" file controls where notifications from watches set by -# "cvs watch add" or "cvs edit" are sent. The first entry on a line is -# a regular expression which is tested against the directory that the -# change is being made to, relative to the $CVSROOT. If it matches, -# then the remainder of the line is a filter program that should contain -# one occurrence of %s for the user to notify, and information on its -# standard input. -# -# "ALL" or "DEFAULT" can be used in place of the regular expression. -# -# You may specify a format string as part of the -# filter. The format characters are: -# -# s = user being notified -# b = Bug identifier -# m = Message supplied on command line -# d = Date of action -# u = User performing the unedit -# t = tag or branch being edited -# -# For example: -#ALL mail %s -s "CVS notification for bug %b" diff --git a/test/repositories/cvs/CVSROOT/notify,v b/test/repositories/cvs/CVSROOT/notify,v deleted file mode 100644 index 5edf2f51..00000000 --- a/test/repositories/cvs/CVSROOT/notify,v +++ /dev/null @@ -1,48 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# The "notify" file controls where notifications from watches set by -# "cvs watch add" or "cvs edit" are sent. The first entry on a line is -# a regular expression which is tested against the directory that the -# change is being made to, relative to the $CVSROOT. If it matches, -# then the remainder of the line is a filter program that should contain -# one occurrence of %s for the user to notify, and information on its -# standard input. -# -# "ALL" or "DEFAULT" can be used in place of the regular expression. -# -# You may specify a format string as part of the -# filter. The format characters are: -# -# s = user being notified -# b = Bug identifier -# m = Message supplied on command line -# d = Date of action -# u = User performing the unedit -# t = tag or branch being edited -# -# For example: -#ALL mail %s -s "CVS notification for bug %b" -@ - diff --git a/test/repositories/cvs/CVSROOT/notify_email b/test/repositories/cvs/CVSROOT/notify_email deleted file mode 100644 index c673ab4c..00000000 --- a/test/repositories/cvs/CVSROOT/notify_email +++ /dev/null @@ -1,10 +0,0 @@ -# The "notify_email" file is used to control templates for emails sent -# when notifying users. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being made to, relative to the -# $CVSROOT. For the first match that is found, then the remainder of the -# line is the name of the file that contains the template. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. diff --git a/test/repositories/cvs/CVSROOT/notify_email,v b/test/repositories/cvs/CVSROOT/notify_email,v deleted file mode 100644 index e9fcc95e..00000000 --- a/test/repositories/cvs/CVSROOT/notify_email,v +++ /dev/null @@ -1,36 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# The "notify_email" file is used to control templates for emails sent -# when notifying users. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being made to, relative to the -# $CVSROOT. For the first match that is found, then the remainder of the -# line is the name of the file that contains the template. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -@ - diff --git a/test/repositories/cvs/CVSROOT/postcommand b/test/repositories/cvs/CVSROOT/postcommand deleted file mode 100644 index ab3ef145..00000000 --- a/test/repositories/cvs/CVSROOT/postcommand +++ /dev/null @@ -1,14 +0,0 @@ -# The "postcommand" file is run after a cvs command has finished. -# The filter on the right is invoked with the repository name and -# the name of the command that has been executed. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/test/repositories/cvs/CVSROOT/postcommand,v b/test/repositories/cvs/CVSROOT/postcommand,v deleted file mode 100644 index b9a194bd..00000000 --- a/test/repositories/cvs/CVSROOT/postcommand,v +++ /dev/null @@ -1,40 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# The "postcommand" file is run after a cvs command has finished. -# The filter on the right is invoked with the repository name and -# the name of the command that has been executed. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". -@ - diff --git a/test/repositories/cvs/CVSROOT/postmodule b/test/repositories/cvs/CVSROOT/postmodule deleted file mode 100644 index b6d258be..00000000 --- a/test/repositories/cvs/CVSROOT/postmodule +++ /dev/null @@ -1,14 +0,0 @@ -# The "postmodule" file is run after a cvs module is processed. -# The filter on the right is invoked with the repository name, -# the name of the command that has been executed, and the module name. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/test/repositories/cvs/CVSROOT/postmodule,v b/test/repositories/cvs/CVSROOT/postmodule,v deleted file mode 100644 index f70fae0b..00000000 --- a/test/repositories/cvs/CVSROOT/postmodule,v +++ /dev/null @@ -1,40 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# The "postmodule" file is run after a cvs module is processed. -# The filter on the right is invoked with the repository name, -# the name of the command that has been executed, and the module name. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". -@ - diff --git a/test/repositories/cvs/CVSROOT/precommand b/test/repositories/cvs/CVSROOT/precommand deleted file mode 100644 index 05c8b890..00000000 --- a/test/repositories/cvs/CVSROOT/precommand +++ /dev/null @@ -1,18 +0,0 @@ -# The "precommand" file is run before a cvs command is executed. -# The filter on the right is invoked with the repository name and -# the name of the command that has been executed. A non-zero return -# value with abort the command with an error. -# -# The standard input of the filter receives each command argument, -# separated by linefeeds. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/test/repositories/cvs/CVSROOT/precommand,v b/test/repositories/cvs/CVSROOT/precommand,v deleted file mode 100644 index f2a2db5e..00000000 --- a/test/repositories/cvs/CVSROOT/precommand,v +++ /dev/null @@ -1,44 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# The "precommand" file is run before a cvs command is executed. -# The filter on the right is invoked with the repository name and -# the name of the command that has been executed. A non-zero return -# value with abort the command with an error. -# -# The standard input of the filter receives each command argument, -# separated by linefeeds. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". -@ - diff --git a/test/repositories/cvs/CVSROOT/premodule b/test/repositories/cvs/CVSROOT/premodule deleted file mode 100644 index 4837892d..00000000 --- a/test/repositories/cvs/CVSROOT/premodule +++ /dev/null @@ -1,15 +0,0 @@ -# The "premodule" file is run before cvs module is processed. -# The filter on the right is invoked with the repository name, -# the name of the command that has been executed, and the module name. -# A non-zero return value with abort the command with an error. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/test/repositories/cvs/CVSROOT/premodule,v b/test/repositories/cvs/CVSROOT/premodule,v deleted file mode 100644 index 0d1b7c4d..00000000 --- a/test/repositories/cvs/CVSROOT/premodule,v +++ /dev/null @@ -1,41 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# The "premodule" file is run before cvs module is processed. -# The filter on the right is invoked with the repository name, -# the name of the command that has been executed, and the module name. -# A non-zero return value with abort the command with an error. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". -@ - diff --git a/test/repositories/cvs/CVSROOT/rcsinfo b/test/repositories/cvs/CVSROOT/rcsinfo deleted file mode 100644 index 27c002f7..00000000 --- a/test/repositories/cvs/CVSROOT/rcsinfo +++ /dev/null @@ -1,10 +0,0 @@ -# The "rcsinfo" file is used to control templates with which the editor -# is invoked on commit and import. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being made to, relative to the -# $CVSROOT. For the first match that is found, then the remainder of the -# line is the name of the file that contains the template. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. diff --git a/test/repositories/cvs/CVSROOT/rcsinfo,v b/test/repositories/cvs/CVSROOT/rcsinfo,v deleted file mode 100644 index a3c803d6..00000000 --- a/test/repositories/cvs/CVSROOT/rcsinfo,v +++ /dev/null @@ -1,36 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# The "rcsinfo" file is used to control templates with which the editor -# is invoked on commit and import. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being made to, relative to the -# $CVSROOT. For the first match that is found, then the remainder of the -# line is the name of the file that contains the template. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -@ - diff --git a/test/repositories/cvs/CVSROOT/shadow b/test/repositories/cvs/CVSROOT/shadow deleted file mode 100644 index 7ccd24e2..00000000 --- a/test/repositories/cvs/CVSROOT/shadow +++ /dev/null @@ -1,7 +0,0 @@ -# The "shadow" file is used to control automatic checkouts. -# -# Each line has 3 parts: -# -# -# In common with other commit support files, use forward slashes -# and escape any spaces in filenames. diff --git a/test/repositories/cvs/CVSROOT/shadow,v b/test/repositories/cvs/CVSROOT/shadow,v deleted file mode 100644 index a3c14d97..00000000 --- a/test/repositories/cvs/CVSROOT/shadow,v +++ /dev/null @@ -1,33 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# The "shadow" file is used to control automatic checkouts. -# -# Each line has 3 parts: -# -# -# In common with other commit support files, use forward slashes -# and escape any spaces in filenames. -@ - diff --git a/test/repositories/cvs/CVSROOT/tag_email b/test/repositories/cvs/CVSROOT/tag_email deleted file mode 100644 index 48d545fe..00000000 --- a/test/repositories/cvs/CVSROOT/tag_email +++ /dev/null @@ -1,10 +0,0 @@ -# The "tag_email" file is used to control templates for emails sent -# during tagging operations. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being made to, relative to the -# $CVSROOT. For the first match that is found, then the remainder of the -# line is the name of the file that contains the template. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. diff --git a/test/repositories/cvs/CVSROOT/tag_email,v b/test/repositories/cvs/CVSROOT/tag_email,v deleted file mode 100644 index 3fc9444b..00000000 --- a/test/repositories/cvs/CVSROOT/tag_email,v +++ /dev/null @@ -1,36 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# The "tag_email" file is used to control templates for emails sent -# during tagging operations. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being made to, relative to the -# $CVSROOT. For the first match that is found, then the remainder of the -# line is the name of the file that contains the template. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -@ - diff --git a/test/repositories/cvs/CVSROOT/taginfo b/test/repositories/cvs/CVSROOT/taginfo deleted file mode 100644 index 3beb822e..00000000 --- a/test/repositories/cvs/CVSROOT/taginfo +++ /dev/null @@ -1,21 +0,0 @@ -# The "taginfo" file is used to control pre-tag checks. -# The filter on the right is invoked with the following arguments: -# -# $1 -- tagname -# $2 -- operation "add" for tag, "mov" for tag -F, and "del" for tag -d -# $3 -- repository -# -# The filter is passed a series of filename/version pairs on its standard input -# -# A non-zero exit of the filter program will cause the tag to be aborted. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/test/repositories/cvs/CVSROOT/taginfo,v b/test/repositories/cvs/CVSROOT/taginfo,v deleted file mode 100644 index f511baba..00000000 --- a/test/repositories/cvs/CVSROOT/taginfo,v +++ /dev/null @@ -1,47 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# The "taginfo" file is used to control pre-tag checks. -# The filter on the right is invoked with the following arguments: -# -# $1 -- tagname -# $2 -- operation "add" for tag, "mov" for tag -F, and "del" for tag -d -# $3 -- repository -# -# The filter is passed a series of filename/version pairs on its standard input -# -# A non-zero exit of the filter program will cause the tag to be aborted. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". -@ - diff --git a/test/repositories/cvs/CVSROOT/triggers b/test/repositories/cvs/CVSROOT/triggers deleted file mode 100644 index 48a9fc33..00000000 --- a/test/repositories/cvs/CVSROOT/triggers +++ /dev/null @@ -1,5 +0,0 @@ -# The "triggers" file lists libraries which handle the events for each -# module. -# -# In addition to the lines here, the default_trigger library is loaded, if available. -# diff --git a/test/repositories/cvs/CVSROOT/triggers,v b/test/repositories/cvs/CVSROOT/triggers,v deleted file mode 100644 index 78a9e625..00000000 --- a/test/repositories/cvs/CVSROOT/triggers,v +++ /dev/null @@ -1,31 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# The "triggers" file lists libraries which handle the events for each -# module. -# -# In addition to the lines here, the default_trigger library is loaded, if available. -# -@ - diff --git a/test/repositories/cvs/CVSROOT/val-tags b/test/repositories/cvs/CVSROOT/val-tags deleted file mode 100644 index 6f25c268..00000000 --- a/test/repositories/cvs/CVSROOT/val-tags +++ /dev/null @@ -1,2 +0,0 @@ -my_branch y -another_branch y diff --git a/test/repositories/cvs/CVSROOT/verifymsg b/test/repositories/cvs/CVSROOT/verifymsg deleted file mode 100644 index 28b1d6ea..00000000 --- a/test/repositories/cvs/CVSROOT/verifymsg +++ /dev/null @@ -1,17 +0,0 @@ -# The "verifymsg" file is used to allow verification of logging -# information. It works best when a template (as specified in the -# rcsinfo file) is provided for the logging procedure. Given a -# template with locations for, a bug-id number, a list of people who -# reviewed the code before it can be checked in, and an external -# process to catalog the differences that were code reviewed, the -# following test can be applied to the code: -# -# Making sure that the entered bug-id number is correct. -# Validating that the code that was reviewed is indeed the code being -# checked in (using the bug-id number or a seperate review -# number to identify this particular code set.). -# -# If any of the above test failed, then the commit would be aborted. -# -# Actions such as mailing a copy of the report to each reviewer are -# better handled by an entry in the loginfo file. diff --git a/test/repositories/cvs/CVSROOT/verifymsg,v b/test/repositories/cvs/CVSROOT/verifymsg,v deleted file mode 100644 index 78394d81..00000000 --- a/test/repositories/cvs/CVSROOT/verifymsg,v +++ /dev/null @@ -1,43 +0,0 @@ -head 1.1; -access ; -symbols ; -locks ; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.19.58; author robin; state Exp; -branches; -next ; -kopt kv; -deltatype text; -permissions 664; - -desc -@@ - - - -1.1 -log -@initial checkin@ -text -@# The "verifymsg" file is used to allow verification of logging -# information. It works best when a template (as specified in the -# rcsinfo file) is provided for the logging procedure. Given a -# template with locations for, a bug-id number, a list of people who -# reviewed the code before it can be checked in, and an external -# process to catalog the differences that were code reviewed, the -# following test can be applied to the code: -# -# Making sure that the entered bug-id number is correct. -# Validating that the code that was reviewed is indeed the code being -# checked in (using the bug-id number or a seperate review -# number to identify this particular code set.). -# -# If any of the above test failed, then the commit would be aborted. -# -# Actions such as mailing a copy of the report to each reviewer are -# better handled by an entry in the loginfo file. -@ - diff --git a/test/repositories/cvs/simple/CVS/fileattr.xml b/test/repositories/cvs/simple/CVS/fileattr.xml deleted file mode 100644 index f8767f21..00000000 --- a/test/repositories/cvs/simple/CVS/fileattr.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - robin - - diff --git a/test/repositories/cvs/simple/another_file.rb,v b/test/repositories/cvs/simple/another_file.rb,v deleted file mode 100644 index 638a8f75..00000000 --- a/test/repositories/cvs/simple/another_file.rb,v +++ /dev/null @@ -1,113 +0,0 @@ -head 1.2; -access; -symbols - another_branch:1.1.0.2; -locks; strict; -comment @# @; - - -1.2 -date 2006.06.29.18.45.29; author robin; state Exp; -branches; -next 1.1; -deltatype text; -kopt kv; -permissions 644; -commitid db744a41fc8a6ac; -mergepoint1 1.1.2.2; -filename another_file.rb; - -1.1 -date 2006.06.29.18.44.27; author robin; state dead; -branches - 1.1.2.1; -next ; -deltatype text; -kopt kv; -permissions 644; -commitid db044a41f8b01e1; -filename another_file.rb; - -1.1.2.1 -date 2006.06.29.18.44.27; author robin; state Exp; -branches; -next 1.1.2.2; -deltatype text; -kopt kv; -permissions 644; -commitid db044a41f8b01e1; -filename another_file.rb; - -1.1.2.2 -date 2006.06.29.18.44.56; author robin; state Exp; -branches; -next 1.1.2.3; -deltatype text; -kopt kv; -permissions 644; -commitid db244a41fa871cc; -filename another_file.rb; - -1.1.2.3 -date 2006.06.29.18.50.37; author robin; state Exp; -branches; -next ; -deltatype text; -kopt kv; -permissions 600; -commitid dfc44a420fde53f; -mergepoint1 1.2; -filename another_file.rb; - - -desc -@@ - - -1.2 -log -@merged another_file from another_branch onto the HEAD -@ -text -@puts "this file was created on another branch" -puts "I edited this file on another branch only" -@ - - -1.1 -log -@file another_file.rb was initially added on branch another_branch. -@ -text -@d1 2 -@ - - -1.1.2.1 -log -@created another_file on another_branch -@ -text -@a0 1 -puts "this file was created on another branch" -@ - - -1.1.2.2 -log -@edited another_file -@ -text -@a1 1 -puts "I edited this file on another branch only" -@ - - -1.1.2.3 -log -@merged from head onto another_branch. this added file late_addition -@ -text -@@ - - diff --git a/test/repositories/cvs/simple/foo.rb,v b/test/repositories/cvs/simple/foo.rb,v deleted file mode 100644 index 6ed04b1c..00000000 --- a/test/repositories/cvs/simple/foo.rb,v +++ /dev/null @@ -1,50 +0,0 @@ -head 1.1; -branch 1.1.1; -access; -symbols - another_branch:1.1.1.1.0.4 - my_branch:1.1.1.1.0.2 - simple_release_tag:1.1.1.1 - simple_vendor_tag:1.1.1; -locks; strict; -comment @# @; - - -1.1 -date 2006.06.29.16.21.07; author robin; state Exp; -branches - 1.1.1.1; -next ; -deltatype text; -kopt kv; -permissions 644; - -1.1.1.1 -date 2006.06.29.16.21.07; author robin; state Exp; -branches; -next ; -deltatype text; -kopt kv; -permissions 644; - - -desc -@@ - - - -1.1 -log -@Initial revision -@ -text -@puts "Hi, I'm foo.rb!" -@ - - -1.1.1.1 -log -@Initial import. -@ -text -@@ diff --git a/test/repositories/cvs/simple/late_addition.rb,v b/test/repositories/cvs/simple/late_addition.rb,v deleted file mode 100644 index 91b4c72e..00000000 --- a/test/repositories/cvs/simple/late_addition.rb,v +++ /dev/null @@ -1,93 +0,0 @@ -head 1.2; -access; -symbols - another_branch:1.1.0.2; -locks; strict; -comment @# @; - - -1.2 -date 2006.06.29.18.52.23; author robin; state Exp; -branches; -next 1.1; -deltatype text; -kopt kv; -permissions 600; -commitid e0544a421671465; -mergepoint1 1.1.2.2; -filename late_addition.rb; - -1.1 -date 2006.06.29.18.48.54; author robin; state Exp; -branches - 1.1.2.1; -next ; -deltatype text; -kopt kv; -permissions 644; -commitid df344a420967b0e; -filename late_addition.rb; - -1.1.2.1 -date 2006.06.29.18.50.37; author robin; state Exp; -branches; -next 1.1.2.2; -deltatype text; -kopt kv; -permissions 644; -commitid dfc44a420fde53f; -mergepoint1 1.1; -filename late_addition.rb; - -1.1.2.2 -date 2006.06.29.18.51.25; author robin; state Exp; -branches; -next ; -deltatype text; -kopt kv; -permissions 644; -commitid dff44a4212d348f; -filename late_addition.rb; - - -desc -@@ - - -1.2 -log -@merged the change to late_addition from another_branch to the head -@ -text -@puts "This file was created on the HEAD after the branches were already made" -puts "This line of code was added on another_branch after merging from the head" -@ - - -1.1 -log -@created late_addition on the HEAD -@ -text -@d2 1 -@ - - -1.1.2.1 -log -@merged from head onto another_branch. this added file late_addition -@ -text -@@ - - -1.1.2.2 -log -@edited late_addition on another_branch -@ -text -@a1 1 -puts "This line of code was added on another_branch after merging from the head" -@ - - diff --git a/test/repositories/cvs/simple/new_file.rb,v b/test/repositories/cvs/simple/new_file.rb,v deleted file mode 100644 index 72d4e578..00000000 --- a/test/repositories/cvs/simple/new_file.rb,v +++ /dev/null @@ -1,112 +0,0 @@ -head 1.2; -access; -symbols - another_branch:1.2.0.2 - my_branch:1.1.0.2; -locks; strict; -comment @# @; - - -1.2 -date 2006.06.29.18.14.47; author robin; state Exp; -branches; -next 1.1; -deltatype text; -kopt kv; -permissions 644; -commitid c3944a41896430e; -mergepoint1 1.1.2.1; -filename new_file.rb; - -1.1 -date 2006.06.29.18.05.27; author robin; state dead; -branches - 1.1.2.1; -next ; -deltatype text; -kopt kv; -permissions 644; -commitid bd144a41667e765; -filename new_file.rb; - -1.1.2.1 -date 2006.06.29.18.05.27; author robin; state Exp; -branches; -next 1.1.2.2; -deltatype text; -kopt kv; -permissions 644; -commitid bd144a41667e765; -filename new_file.rb; - -1.1.2.2 -date 2006.06.29.18.17.49; author robin; state Exp; -branches; -next 1.1.2.3; -deltatype text; -kopt kv; -permissions 644; -commitid c7744a4194cefc8; -filename new_file.rb; - -1.1.2.3 -date 2006.06.29.18.40.38; author robin; state dead; -branches; -next ; -deltatype text; -kopt kv; -permissions 444; -commitid d4e44a41ea6477e; -filename new_file.rb; - - -desc -@@ - - -1.2 -log -@merged new_file.rb from branch onto the HEAD -@ -text -@puts "I was created on the branch" -@ - - -1.1 -log -@file new_file.rb was initially added on branch my_branch. -@ -text -@d1 1 -@ - - -1.1.2.1 -log -@added new_file.rb on the branch -@ -text -@a0 1 -puts "I was created on the branch" -@ - - -1.1.2.2 -log -@modifed new_file.rb on the branch only -@ -text -@a1 1 -puts "This file was edited on the branch after the orginal was merged onto the HEAD" -@ - - -1.1.2.3 -log -@removed new_file.rb from the branch only -@ -text -@@ - - From 513f63600f0ce288dfb6dd89e6025614f2c3059d Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Sun, 31 Aug 2014 19:44:58 +0530 Subject: [PATCH 157/219] OTWO-3206: Fix invalid utf-8 encoding issues --- bin/string_encoder | 13 +++++++ lib/scm/adapters/abstract_adapter.rb | 6 ++++ lib/scm/adapters/cvs/commits.rb | 2 +- lib/scm/adapters/cvs/misc.rb | 2 +- lib/scm/adapters/git/commits.rb | 4 +-- lib/scm/adapters/git/misc.rb | 2 +- lib/scm/adapters/hg/commits.rb | 6 ++-- lib/scm/adapters/hg/misc.rb | 2 +- test/data/invalid-utf-word | 1 + test/data/sample-content | 32 ++++++++++++++++++ .../bzr_with_invalid_encoding.tgz | Bin 0 -> 4904 bytes test/repositories/cvs.tgz | Bin 10054 -> 10303 bytes .../git_with_invalid_encoding.tgz | Bin 0 -> 5729 bytes .../repositories/hg_with_invalid_encoding.tgz | Bin 0 -> 2376 bytes .../svn_with_invalid_encoding.tgz | Bin 0 -> 12336 bytes test/unit/abstract_adapter_test.rb | 6 ++++ test/unit/bzr_commits_test.rb | 10 ++++++ test/unit/cvs_commits_test.rb | 16 +++++++++ test/unit/cvs_misc_test.rb | 5 +++ test/unit/git_commits_test.rb | 13 +++++++ test/unit/git_misc_test.rb | 13 +++++++ test/unit/hg_commits_test.rb | 30 ++++++++++++++++ test/unit/hg_misc_test.rb | 9 +++++ test/unit/string_encoder_command_line_test.rb | 27 +++++++++++++++ test/unit/svn_commits_test.rb | 10 ++++++ 25 files changed, 200 insertions(+), 9 deletions(-) create mode 100755 bin/string_encoder create mode 100644 test/data/invalid-utf-word create mode 100644 test/data/sample-content create mode 100644 test/repositories/bzr_with_invalid_encoding.tgz create mode 100644 test/repositories/git_with_invalid_encoding.tgz create mode 100644 test/repositories/hg_with_invalid_encoding.tgz create mode 100644 test/repositories/svn_with_invalid_encoding.tgz create mode 100644 test/unit/string_encoder_command_line_test.rb diff --git a/bin/string_encoder b/bin/string_encoder new file mode 100755 index 00000000..a0e6e69a --- /dev/null +++ b/bin/string_encoder @@ -0,0 +1,13 @@ +#! /usr/bin/env ruby +# Replaces invalid utf-8 characters with �. +# +# Usage: +# $ cat some_file | string_encoder + +while input = gets + if input.to_s.valid_encoding? + puts input + else + puts input.encode('UTF-8', 'binary', invalid: :replace, undef: :replace) + end +end diff --git a/lib/scm/adapters/abstract_adapter.rb b/lib/scm/adapters/abstract_adapter.rb index 361b5b4e..973c0f41 100644 --- a/lib/scm/adapters/abstract_adapter.rb +++ b/lib/scm/adapters/abstract_adapter.rb @@ -13,6 +13,12 @@ class << self end end + # Returns path to the string_encoder binary. + # For use with inline system commands like `run`. + def string_encoder + File.expand_path('../../../../bin/string_encoder', __FILE__) + end + end end diff --git a/lib/scm/adapters/cvs/commits.rb b/lib/scm/adapters/cvs/commits.rb index bfb9dd1f..53ad58d9 100644 --- a/lib/scm/adapters/cvs/commits.rb +++ b/lib/scm/adapters/cvs/commits.rb @@ -63,7 +63,7 @@ def open_log_file(opts={}) after = opts[:after] begin ensure_host_key - run "cvsnt -d #{self.url} rlog #{opt_branch} #{opt_time(after)} '#{self.module_name}' > #{rlog_filename}" + run "cvsnt -d #{self.url} rlog #{opt_branch} #{opt_time(after)} '#{self.module_name}' | #{ string_encoder } > #{rlog_filename}" File.open(rlog_filename, 'r') do |file| yield file end diff --git a/lib/scm/adapters/cvs/misc.rb b/lib/scm/adapters/cvs/misc.rb index 8c967bdf..258a4067 100644 --- a/lib/scm/adapters/cvs/misc.rb +++ b/lib/scm/adapters/cvs/misc.rb @@ -67,7 +67,7 @@ def ls(path=nil) def log(most_recent_token=nil) ensure_host_key - run "cvsnt -d #{self.url} rlog #{opt_branch} #{opt_time(most_recent_token)} '#{self.module_name}'" + run "cvsnt -d #{self.url} rlog #{opt_branch} #{opt_time(most_recent_token)} '#{self.module_name}' | #{ string_encoder }" end def checkout(r, local_directory) diff --git a/lib/scm/adapters/git/commits.rb b/lib/scm/adapters/git/commits.rb index 7f5ff579..a49292d8 100644 --- a/lib/scm/adapters/git/commits.rb +++ b/lib/scm/adapters/git/commits.rb @@ -80,7 +80,7 @@ def log(opts={}) if opts[:after] && opts[:after]==self.head_token '' # Nothing new. else - run "#{rev_list_command(opts)} | xargs -n 1 #{Scm::Parsers::GitStyledParser.whatchanged}" + run "#{rev_list_command(opts)} | xargs -n 1 #{Scm::Parsers::GitStyledParser.whatchanged} | #{ string_encoder }" end else '' @@ -96,7 +96,7 @@ def open_log_file(opts={}) '' # Nothing new. else begin - run "#{rev_list_command(opts)} | xargs -n 1 #{Scm::Parsers::GitStyledParser.whatchanged} > #{log_filename}" + run "#{rev_list_command(opts)} | xargs -n 1 #{Scm::Parsers::GitStyledParser.whatchanged} | #{ string_encoder } > #{log_filename}" File.open(log_filename, 'r') { |io| yield io } ensure File.delete(log_filename) if FileTest.exist?(log_filename) diff --git a/lib/scm/adapters/git/misc.rb b/lib/scm/adapters/git/misc.rb index 61c9e16e..4faa38c3 100644 --- a/lib/scm/adapters/git/misc.rb +++ b/lib/scm/adapters/git/misc.rb @@ -48,7 +48,7 @@ def checkout # Returns an array of all branch names def branches - run("cd '#{self.url}' && git branch").split.collect { |b| b =~ /\b(.+)$/ ; $1 }.compact + run("cd '#{self.url}' && git branch | #{ string_encoder }").split.collect { |b| b =~ /\b(.+)$/ ; $1 }.compact end def has_branch?(name=self.branch_name) diff --git a/lib/scm/adapters/hg/commits.rb b/lib/scm/adapters/hg/commits.rb index 77214a65..6a073edd 100644 --- a/lib/scm/adapters/hg/commits.rb +++ b/lib/scm/adapters/hg/commits.rb @@ -44,7 +44,7 @@ def commits(opts={}) # Returns a single commit, including its diffs def verbose_commit(token) - log = run("cd '#{self.url}' && hg log -v -r #{token} --style #{Scm::Parsers::HgStyledParser.verbose_style_path}") + log = run("cd '#{self.url}' && hg log -v -r #{token} --style #{Scm::Parsers::HgStyledParser.verbose_style_path} | #{ string_encoder }") Scm::Parsers::HgStyledParser.parse(log).first end @@ -64,7 +64,7 @@ def each_commit(opts={}) # Not used by Ohloh proper, but handy for debugging and testing def log(opts={}) after = opts[:after] || 0 - run "cd '#{url}' && hg log -f #{trunk_only(opts)} -v -r tip:#{after}" + run "cd '#{url}' && hg log -f #{trunk_only(opts)} -v -r tip:#{after} | #{ string_encoder }" end # Returns a file handle to the log. @@ -78,7 +78,7 @@ def open_log_file(opts={}) # As a time optimization, just create an empty file rather than fetch a log we know will be empty. File.open(log_filename, 'w') { } else - run "cd '#{url}' && hg log --verbose #{trunk_only(opts)} -r #{after || 0}:tip --style #{Scm::Parsers::HgStyledParser.verbose_style_path} > #{log_filename}" + run "cd '#{url}' && hg log --verbose #{trunk_only(opts)} -r #{after || 0}:tip --style #{Scm::Parsers::HgStyledParser.verbose_style_path} | #{ string_encoder } > #{log_filename}" end File.open(log_filename, 'r') { |io| yield io } ensure diff --git a/lib/scm/adapters/hg/misc.rb b/lib/scm/adapters/hg/misc.rb index f2091f27..6d395195 100644 --- a/lib/scm/adapters/hg/misc.rb +++ b/lib/scm/adapters/hg/misc.rb @@ -10,7 +10,7 @@ def exist? end def ls_tree(token) - run("cd '#{path}' && hg manifest -r #{token}").split("\n") + run("cd '#{path}' && hg manifest -r #{token} | #{ string_encoder }").split("\n") end def export(dest_dir, token='tip') diff --git a/test/data/invalid-utf-word b/test/data/invalid-utf-word new file mode 100644 index 00000000..22d22108 --- /dev/null +++ b/test/data/invalid-utf-word @@ -0,0 +1 @@ +ý¿¿¿¿¿ diff --git a/test/data/sample-content b/test/data/sample-content new file mode 100644 index 00000000..b28fd339 --- /dev/null +++ b/test/data/sample-content @@ -0,0 +1,32 @@ +RCS file: /cvsroot/cncms/phparticle212/admin/template.php,v +head: 1.4 +branch: +locks: strict +access list: +symbolic names: + pa212: 1.1.1.1 + niuboy: 1.1.1 +keyword substitution: kv +total revisions: 5; selected revisions: 4 + +description: +---------------------------- +revision 1.4 +date: 2006/12/08 12:08:10; author: semirock; state: Exp; lines: +514 -478 +Ìí¼Órss.phpÎļþĬÈÏÏÔʾ20ƪÎÄÕ + +---------------------------- +revision 1.3 +date: 2006/11/22 08:35:59; author: niuboy; state: Exp; lines: +6 -2 +no message +---------------------------- +revision 1.2 +date: 2006/11/19 19:51:28; author: niuboy; state: Exp; lines: +4 -4 +no message + +---------------------------- +revision 1.1 +date: 2006/11/11 07:21:46; author: niuboy; state: Exp; +branches: 1.1.1; +Initial revision +============================================================================= diff --git a/test/repositories/bzr_with_invalid_encoding.tgz b/test/repositories/bzr_with_invalid_encoding.tgz new file mode 100644 index 0000000000000000000000000000000000000000..cec80b9fd96e129b7fd1eec6c8fbb9fd181dd265 GIT binary patch literal 4904 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 a_CIA_6#5?k000000Ak%u++IKcpa1}jM&DEb literal 0 HcmV?d00001 diff --git a/test/repositories/cvs.tgz b/test/repositories/cvs.tgz index d047cc5894ddea0f2e7b79c4ea7a93be0a3b58f7..6603f7a887635d35659f8d7ef46ffd2609b8feb0 100644 GIT binary patch literal 10303 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 GNdE_aqqzY9 literal 10054 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 Mhc!=u*3m%!2RY6LUH||9 diff --git a/test/repositories/git_with_invalid_encoding.tgz b/test/repositories/git_with_invalid_encoding.tgz new file mode 100644 index 0000000000000000000000000000000000000000..24a3dd6a8f2014bc5fef110ea7b0d131e3421c68 GIT binary patch literal 5729 zcmV-n7M|%JiwFRG-2zkq1MFP~SQOXVULc9?+7+Y5He#c=?DW}1P(cWw5|RZ`v8=N@ zGqAeN-J#f95-XOA5)Jmo)m(@LF&g<*FrvoZu@GYmme`F+RJ^l*i4b%LFvEZ2ybnAx zJ9B2v*?G_VeW!eLHb&2C67+1WMsJEI4SGsLn{;MMZ;DY!-WWg*1cBMN5P?CZTe$dm zDI^e#a7i#6LJPIEn^*^=2Du zrAcGAda^hhR{;PMX{2oyQbz+emg-thR!DA}c^UL3+TEl0nBK$!MpAEbx1aQ= zCmUT)29!+$06KFV3;6m1Zh<6A0_;c&4X8;|4DDt=NSi1_*S}m;<}x-`Zv(hLHkJk` z?iR1P4gjn)8)r2EAopQx1%(ER3&@zQfV;iudccoM%58iB6yvsDULN-Ie`emzbzSjo{V#_vTK$87IKc{-Yqs*?$bN+kg9xX#a(P1O8bu##Ze-9NB-Is~ctc z$59Ly?Y|Icr-}3r)_fS+CrI;QxH`-~QVL5IbRx@{IhwMYNh8U21?2LQJwFIY&>IYZ z$;<+z#lj^5y1D_Z8L-<{n?m-|-6F!(kwJk{NU8w+;!HNPm8GdJ0Oa>#5B6is21-ZT z=ogoLtPT%W`-f@#`$mR@tEGXY)k>Ry5IwD>t*lf*#g^>#h_lgFo43szXVuYMv0`X% z6U~;t$w&TSLDHbaIPMCPGxI&|6$!{~K-(g4`> z>|aV66{L;`4gW}rd8@|R;!Q9JK_CKw_I&IvQR?koz7-`^3@Pg{J1DxkNg3G-|5WiM ze{o@@SG@uL9q2#SY#wf_t{13G`yYgHyZ#9n7VW8Qj952g1 z3=#+`+J7O?z8#>5vso2dy-7iv;sGsbi6i`_Ju)`WFNh>%Tn^l&I%A#|%IMwm7ZDYSz&<8^DlygUwrJqgg;s z%VeyTv;b~aBOqshKY9z^tkL2I1oaP%loeMSIsHc?OfKgR$gQ-2WcBehAXk^Wj7vZ# z7LP{w*^j^UQD=_lZV|&>BR7zym^g0N<|ns}Fuat;)2KIj53|XP@#XIN$0yNj{T2NE zzs_tl>e;H~QF;FlL9jUfCkRCU|8}Di`j4e`!_9G3umDxiKZ?Sl{)K?3|F;_s^l#P< zqjhXGM}YW`|KKRX?Q>^gar{RZ@Z?{KRHF)1fq&HA{}cKD`@x@o9i&x(B!nOYMBpkK zf@y@}h-7GthIA?#hfqdK=_<;jc#a=^_52Tvqhi|1Sg*ofgm9HO!@5!yco5 z@w(QgF>@lWX+Z6*^NtN4xAWwN0sS#U=haI!JC<+Bn_NrrD7v4M@j~jY0~4lZb(s8l zlNK`uj1Jp$ki3U{xv%pb=LYdNS|pg9yRGy{S=q90r@Dvce|KQhv@ah9q-bZ&a!#JE z82PaE?Wc0fP3M>v?4WIfej`r(v?uMv&3E@|k5Ct`T%3^XkKJnSS`@rr{%CuaB5}u9 z&qqhcUCLq-Lsg^PZ|;#tMU6kzu+QO|erEq9@YTOk5c`keFpL)4f1D8QzYyThKY@iCDG5?ZVmgWfNen|soa?n!0LS(pE6YEOq8KRJe<5JE|Ng^r!G=Mb zPI)kG)o6#mTF zVM_w{s@nBB*J{JBb3H7}<~GjTcYfsjH6VR+db3U%^@lB|_G0r^UUr%?wT%iP8=_B7 z4AlJCuZ`@djJs=Fw$`3b-oCY<*>54)f5`qvUd*?-6$|3hG6{I4+J&p)Ij zv;>IK2n4HiDw1SK5(05r$GHTIgmt7+g`f;xQ63KLKLjFpS^l~9KMslZUkD^Rja3hx zk=n!c=dV61nxbzL=&#Nnx8cH-c1cY8GtFBC?T?<+mbke-WB-AvVOxH?vv@=RUdPzh z_1corhqE7_Pd;s&mGO1A9XYq*`q_m~OpSt;KgMPan%O`8!L`jA4?dmNdu?Gu zv~b0-MF$w*OvkT2ocK7?KWj{@y!k7xj%u{x(uRkjE(zUt*Dktp!NpU$cyEVR@*MYq zQK@}__fzH?n|B#JGXZuTH!yI>djAVkL0Epj4!NXvu)k@dZpkMF2}3rS>n(1yy2-+* z1z!w%sPg$fUFsu!$M4Q4?^q4sl5w_OyRiKF&N=%`KdV++R;+6k6&HV)8Z>MD+3(JL zcM}NRp46nn4#lLoD?duQs{P_$$Fn4R>W){B2|Z34a*xex-F!;k<9>S2hhOG|FX-R- z$1Woy9wj&1o;Yj5nUlx5-v4^?=AR}n{=Mi9b9SStg?n!EUdf;2t=R9r|H-p9g%@f) z`90b9YVz25sjAS1KJMKuLysMU(a6AG4_?fivT4RDNn?$4@5kdJ#-v<)5_>&n(g?pM z2j|bHvo|hJsgv6+WR%`JEEnq$GbsNT<;8ugr{B*{4(_1V-0Bbmnu{dY3LD+1>Dnpc z?*>o%kAgz^f3T$g$0ZZ}zX0IRzmlSG2vssPNuU%2kvg1Ylo-nO2D#<{LMSOx32BLn z@^Iw;VFW76Ka3KfIR7UI5}l0d0pU$PaV;|GM}M!}95P`4nz+g8*t9O*6L!7h@?Jy_ zcgTMw89+(&nGoJcK@6FX#>AWzgYkF{+sT33nqE(wam0p zEmq9#llQP$3m^EhqIpjE`RPMLT*HF@L)_YUH|x>HppY}C!lo=&JXrTl+K$s$?}T;H z`yTg6+XlE??x-OO(yu?-+1;I)shi~Qv9;dehF)u^>jUEJZV7fNhz z$7;@GD!2GwADvpT`|+aqOUIc{O^VF#x79`NZeusbE^m};eSCF~ONaiKveH^Q>vvxt zuun6!+u4TAGv?v}|C&3K3g0y=boskSTNo!51~&FvmFzWoX6%37WKt8#L&NhjL7I**)~HZXD6Gv|nFxh~}W zLt|C%<+&RZrxy^}?18z1cFUp$J`VGwXEpTLa<}o<(jPj674-CPVm=b?lQwYC*^r?N zwzcWlWwyUIjQqgmq1)$EJ5C!p%r@8HMGfqD4%wKVY-}=icYgTO$@AKMw&l})AwP7? z8lpWM@N8m-U=5+UR5-rZ(z9xH_eLvkd5laNm(~uRK7Vt)BB!kMQ*&xs7;g!9+JA-? zcKjC?=YNF(fBqpY&ghgVPSZGo&^WH+{t%p`QH;b@qzcDy9jR4Tl!v47Ux?c;JN}D- zV*IZ#NObb@=oQv?J*ov!5JaF)EC+iZ3g362cS3r|0r}q0lf4gxcJXE`h1s2sJzsZa z#fc4%(r;(kI`un0?0o%`>-Fbu&)&DyBW;PHXw4UcKHj;0@QQ6a4}bjN$~sM*{DM9q zgV}Y*ue6jb_}FW3O@C7n6@jPz^(Mw#We-pp`(OJ04}>G4{TBi}`3F@3#s9!W>HM!4 z|04+a^AAz9eaIhW5Qb4wAcG+w0n#dpVst2mQ7A!TN|majJRJFd1jNhoZ}MOTfq^>%m_IxLI%)#dm zGVdI3qd0tXN^nX>+xE+^MxqhT@q(n!u1cgX^CJpt2VG80C|KMiczD3=0sl5JNkPy% zDWgUiwm-RFzkAFC@1*HjL7VG+uxx4P9Phmo*M)YNmfi6g9G0^sZ1$j`{bqj}+vxeP z6Z-ftyOQZ4MHBYa{dF#UL%R5$X=POO_Kft5s9$QG*{aZVX@*?L-tlAf!>0B3L_e+R zr})1Mp8B_ty5WNQe^i|R6$E_kzcAzff5!i!;`qNH;LksZGCBlAXdQ&0AO$O7jwMQ^ zRT3bADRoL*MRWUAng4&O|Nlq)uYDu>e*y4@`~N#Vo{XEn_owICPj}rKW4qHe~9D1f*{dpaZ+zt4(J-xI;N@FyVw6^IW@YzdtwAJ zr_+{bFzH0+Z@TvDw7|3r@oDwV`To{63nRbk=j$?K==!M#4|RN}Lw;tbM^RcZz0IO2 zBjD(^fr^}yI>wgJ@()K^NfvQ6LU*g&G{pmIR4MbE2 z4)m`xn;3meHS@4*{B`TU!uU($e>hmY{-b^VPt^b4kAXU~l^!gUT4{^frf1F8ktHj= z#?w}t-fXh3jxCcidIN1VQ#AL9wZ_phsg|_bKQN@h#(grFV@QL+N;7d5iezcqi(~`s zE46a>wl5^k9gC!GED&I3Wm4Km>J9c(+!49f%=VxYNu$L;d+W?b*+4y{Gz~6ZaofJ& z)QkGaB@YhhEv`KBhT%Z}9I4e_{;3{{%{i<3ECc5C5?= zNmZu;@ZA%GOqYzxY{;T-@w=fX(|8|4F{*9!KrL9%TgTMcO5&r?% zy8)v91%Rmkw;Pr6|5fY)RL1`o_y1rRBgFOJ1%aslw;TNR?^dFIx60>H8T}(LRNVg; z^)C!W{lDFCp#PrXVPT<>nxMeY$gqguD(2x(|1eQL{vXH0^`8YnXbJ5=9Lva+fPJFZ zK3glQ{cV8*{p(Fs^{c%j{UcEM`5zn?$Nz;vV5qt$w{f=rM>?NRg;oSI5k=?Qmz=Hb zi;y_fzrkF+ssCbBX8yk<{udYD{}2d#_^)md zQ04h2Fi>3oLlE%hzZyXxm5%>_xjj+;f}oQ8S7`*;QTq=@uyXMq2q@0~3ImWQ0KNl7 ze}wr0z7>V{b^{<3RKXCg#Fc;-h#{aAW9Gx^nED@Yg@Z zZvgc$W{GRpQ~j*@hj8V>rKuSJPErgrq9%zsh$3E7Sff z>Hi}bD$f54f|_gpDG{;#SM#W({;L!OR2lu3#Qz|WsDEKlWBMmhOw@nPgOC30TvR6y z2l_|gzrOzoiNF6V4EXC`?Ei`Vzcq1Tr6MG5~uJl8*m$sIk{(y5vMws&nk zO$1@|EVNx%w}O;QxoN#YxfUp(fWZVK1XI8QF+rnbDGRN(-DWK+zldjifJ72~p#u_k3Rn?J_9P}e?EwH()QUBeCB6wwwHtr{*MsG?0py8_Q0v3WD9pfuR_NP+8~ zwQMS=h$PbH^jd1kwC9bbBpFxANTe0i2A@Qp8?TH|(qKoM%i8Q_BO;-9E^EYIOc@#H zdZ#e0DmoNsbJm(2GshD`OZCyNDRk+mKqXZ>dJ|S?Y;9%5w9VyNPHRkCK~+H@bQH+; zP~1wHAz@q2e3E9?48;v=eZ4Eb+GW{^)kNAzcIUP+g#J$9bm{0uNJWp1Ui7I5>*yDf z0g=70kjv!E{Wmc)lTBD@9fLwtair7=D)-x9#yMxZklvx@J{_H+!r~gW#g1hQuctdY09FgrOrC)Z(t67ERtVl zc!k<(sJ$Kf7x+}vR;gnu>L&Qp^8x=?lreX|hSqwGyj4bxh?#f^eW6N07 z*q{RkFm+eEPu7C8tM0CB3_&R!u0Re*xiXOHkWR?amY9T)wk|1#fu@wS3^Wj62!Rlw z0m{*Y8ag$7E6K)DK#~t+Lf+?*S_~N8U6oA4 zH(dTsTanvgcTKA7h61#ZB4N0GF+WlzS5ax91B2bYOq9TknXm|DStDj+f~aKaH#uE} z4wrkfy}YCXR#*?2?5HTRIi1ydkYiGz%U)5A1tT%4Xy!fb8s^rckp`InG$-tES}16j zymC&qD(1$X@;NmjTJ+IaTXVNYRD`r(NQ;lDbNb}EN>LKzIvC}wtS+?|+hTD-U5THo zQT1@W2qo2Sr_EVfQCVp(FRrM3qFtb?I4Wvqe3L6O4^%a$EQ=pmRaFs1W| zD6*;wwwD>q0a>P4!?ax^6b+6tvNfF55W z>M2M1TQofrOpi8YwT~d2#A`orwfAU5t8e_N8u#i*Ofey>OaoL>pw-~NdMD;0K8ntuk~~>5IsZ+ z;i!IaM&b$f@uv!uC+$o-ikn?94XarN!)lMIFhTMdR@ zzjXd@#TN$T|KBep)PGfz70~rvppNhVFcgE%f24&J$al#%e0-x}Py)bm2$fq~LKjYB?Y*!kSd3rCv^&bS7(e>@aF4lrJ;g#kDV zEWj&x18#lkdXw|i*Z=GF#{mgo~_q^r9u6`mPtAA`l z%h_SqaL@JQ=PQrSdbhS$fA_>zn0)=gU7G zJiV`N_}=Ht4L^T=4eJ`P`4`ytsoL<&1*MOF8mc!e*gfTx{pkxUuX_uJoNXAAw{Gzx zd=9;>NjbK~w6fVW=C{6)V_xk2hY7Ep%RF@Mr2_|Eab{k4-uU_wZ5hO{&Ql{!f{Xjcj?6Op%)f@Qa@n$51!oKclQqR&8K!QT5@IT;+Nj|_lNxt zzd9(hBzyP2cCK4{plQX39mL;rFHQf`N9?AirSw$yy0sH;^nLMSORt54gKL6dU z8>{{S4u1QgSB|Z|GW5Y;3mVK zed9)q0n^5A<)-a<_UT;*8`qm24Nv;G&$(;94S9915B`1A@)IW?e(Pw-k6PYtIP=Gb zEthWAZp!;kzg{7H(^cW}mRFT!wa3H#KW{m7y}5An)g$@#_a^On&(=7!Pxc$7i*GDj zI*-b~__1l?K0O`r1azPj;;slR;p&~bTWegCJ@+iMZsL`wdD7gvFk`TrzK#ryvZ$sqfm7H;|f z^WbN0YjCUmPqsc3%FoAnf@1`W6=yvjk`QPQ&XZOzEdU;R|5l0z3~eC3oM5OMC~6wNH6$@w>h6!brG3M}a3RG`SRrgl7!zC~(0XP~U?h{hb|E`$+2ubyy{>uE% z!lM13v_N1q0XUjuS)LuoEJ367zqEj-ZvW8$a37L_{zqQ`^#M*$^PnSG z3xp2lk@WlzWr?5vvlit4rG-?rAH$6)-x_%$gJ=HcmM!ZbiQK% literal 0 HcmV?d00001 diff --git a/test/repositories/svn_with_invalid_encoding.tgz b/test/repositories/svn_with_invalid_encoding.tgz new file mode 100644 index 0000000000000000000000000000000000000000..15122bccd1579724cf8c4b0cb58aa9b0eeedc91b GIT binary patch literal 12336 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 W4K>tILk%^&8}NU7x)ihkKmh<1Q&MOE literal 0 HcmV?d00001 diff --git a/test/unit/abstract_adapter_test.rb b/test/unit/abstract_adapter_test.rb index d0f10ba7..e5798277 100644 --- a/test/unit/abstract_adapter_test.rb +++ b/test/unit/abstract_adapter_test.rb @@ -96,5 +96,11 @@ def test_shellout_error end end + def test_string_encoder_must_return_path_to_script + string_encoder_path = File.expand_path('../../../bin/string_encoder', __FILE__) + + assert_equal string_encoder_path, AbstractAdapter.new.string_encoder + end + end end diff --git a/test/unit/bzr_commits_test.rb b/test/unit/bzr_commits_test.rb index 490286f7..b08cb646 100644 --- a/test/unit/bzr_commits_test.rb +++ b/test/unit/bzr_commits_test.rb @@ -359,6 +359,16 @@ def test_committer_and_author_name end end + # Bzr converts invalid utf-8 characters into valid format before commit. + # So no utf-8 encoding issues are seen in ruby when dealing with Bzr. + def test_commits_encoding + with_bzr_repository('bzr_with_invalid_encoding') do |bzr| + assert_nothing_raised do + bzr.commits + end + end + end + protected def revision_ids diff --git a/test/unit/cvs_commits_test.rb b/test/unit/cvs_commits_test.rb index 540bb24e..498a6409 100644 --- a/test/unit/cvs_commits_test.rb +++ b/test/unit/cvs_commits_test.rb @@ -32,5 +32,21 @@ def test_commits_sets_scm end end end + + def test_open_log_file_encoding + with_cvs_repository('cvs', 'invalid_utf8') do |cvs| + cvs.open_log_file do |io| + assert_equal true, io.read.valid_encoding? + end + end + end + + def test_commits_valid_encoding + with_cvs_repository('cvs', 'invalid_utf8') do |cvs| + assert_nothing_raised do + cvs.commits + end + end + end end end diff --git a/test/unit/cvs_misc_test.rb b/test/unit/cvs_misc_test.rb index 67917591..7d3cbb65 100644 --- a/test/unit/cvs_misc_test.rb +++ b/test/unit/cvs_misc_test.rb @@ -57,5 +57,10 @@ def protocol assert_equal :pserver, CvsAdapter.new(:url => ':pserver:ext:@foo.com:/cvsroot/a', :module_name => 'b') end + def test_log_encoding + with_cvs_repository('cvs', 'invalid_utf8') do |cvs| + assert_equal true, cvs.log.valid_encoding? + end + end end end diff --git a/test/unit/git_commits_test.rb b/test/unit/git_commits_test.rb index b4b9bbc5..239d770c 100644 --- a/test/unit/git_commits_test.rb +++ b/test/unit/git_commits_test.rb @@ -127,5 +127,18 @@ def test_each_commit_with_null_merge end end + def test_log_encoding + with_git_repository('git_with_invalid_encoding') do |git| + assert_equal true, git.log.valid_encoding? + end + end + + def test_open_log_file_encoding + with_git_repository('git_with_invalid_encoding') do |git| + git.open_log_file do |io| + assert_equal true, io.read.valid_encoding? + end + end + end end end diff --git a/test/unit/git_misc_test.rb b/test/unit/git_misc_test.rb index b2996616..983d8f4a 100644 --- a/test/unit/git_misc_test.rb +++ b/test/unit/git_misc_test.rb @@ -31,5 +31,18 @@ def test_is_merge_commit assert !git.is_merge_commit?(Scm::Commit.new(:token => 'd067161caae2eeedbd74976aeff5c4d8f1ccc946')) end end + + def test_branches_encoding + with_git_repository('git_with_invalid_encoding') do |git| + assert_equal true, git.branches.all? { |branch| branch.valid_encoding? } + end + end + + # `git ls-tree` returns filenames in valid utf8 regardless of their original form. + def test_ls_tree_encoding + with_git_repository('git_with_invalid_encoding') do |git| + assert_equal true, git.ls_tree.all? { |filename| filename.valid_encoding? } + end + end end end diff --git a/test/unit/hg_commits_test.rb b/test/unit/hg_commits_test.rb index 2771b498..4fa67e3a 100644 --- a/test/unit/hg_commits_test.rb +++ b/test/unit/hg_commits_test.rb @@ -143,6 +143,36 @@ def test_each_commit_after '75532c1e1f1de55c2271f6fd29d98efbe35397c4'], commits.collect { |c| c.token } end end + + def test_open_log_file_encoding + with_hg_repository('hg_with_invalid_encoding') do |hg| + hg.open_log_file do |io| + assert_equal true, io.read.valid_encoding? + end + end + end + + def test_log_encoding + with_hg_repository('hg_with_invalid_encoding') do |hg| + assert_equal true, hg.log.valid_encoding? + end + end + + def test_commits_encoding + with_hg_repository('hg_with_invalid_encoding') do |hg| + assert_nothing_raised do + hg.commits + end + end + end + + def test_verbose_commit_encoding + with_hg_repository('hg_with_invalid_encoding') do |hg| + assert_nothing_raised do + hg.verbose_commit('51ea5277ca27') + end + end + end end end diff --git a/test/unit/hg_misc_test.rb b/test/unit/hg_misc_test.rb index fb371c56..52f90a2c 100644 --- a/test/unit/hg_misc_test.rb +++ b/test/unit/hg_misc_test.rb @@ -27,5 +27,14 @@ def test_export end end + def test_ls_tree_encoding + with_hg_repository('hg_with_invalid_encoding') do |hg| + filenames = hg.ls_tree('51ea5277ca27') + + filenames.each do |filename| + assert_equal true, filename.valid_encoding? + end + end + end end end diff --git a/test/unit/string_encoder_command_line_test.rb b/test/unit/string_encoder_command_line_test.rb new file mode 100644 index 00000000..ffe9befd --- /dev/null +++ b/test/unit/string_encoder_command_line_test.rb @@ -0,0 +1,27 @@ +require_relative '../test_helper' + +module Scm::Parsers + class StringEncoderCommandLineTest < Scm::Test + def test_length_of_content_unchanged + file_path = File.expand_path('../../data/sample-content', __FILE__) + original_content_length = File.size(file_path) + original_content_lines = File.readlines(file_path).size + + output = %x[cat #{ file_path } \ + | #{ Scm::Adapters::AbstractAdapter.new.string_encoder } ] + + assert_equal original_content_length, output.length + assert_equal original_content_lines, output.split("\n").length + end + + def test_encoding_invalid_characters + invalid_utf8_word_path = + File.expand_path('../../data/invalid-utf-word', __FILE__) + + string = %x[cat #{ invalid_utf8_word_path } \ + | #{ Scm::Adapters::AbstractAdapter.new.string_encoder } ] + + assert_equal true, string.valid_encoding? + end + end +end diff --git a/test/unit/svn_commits_test.rb b/test/unit/svn_commits_test.rb index b0eb7301..607938f3 100644 --- a/test/unit/svn_commits_test.rb +++ b/test/unit/svn_commits_test.rb @@ -244,5 +244,15 @@ def test_each_commit assert_equal '/trunk/COPYING', commits[4].diffs[1].path end + # Invalid utf-8 characters in commit message or filename cause encoding errors. + # Svn converts invalid utf-8 characters into valid format before commit. + # So no utf-8 encoding issues are seen in ruby when dealing with Svn. + def test_commits_encoding + with_svn_repository('svn_with_invalid_encoding') do |svn| + assert_nothing_raised do + svn.commits + end + end + end end end From 6147fb80b91db03ca49e264aebb9127ebd26c3a1 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Thu, 11 Sep 2014 14:11:25 +0530 Subject: [PATCH 158/219] OTWO-3218: Fix hung processes due to full io buffers --- lib/scm/shellout.rb | 14 ++------------ test/unit/shellout_test.rb | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 12 deletions(-) create mode 100644 test/unit/shellout_test.rb diff --git a/lib/scm/shellout.rb b/lib/scm/shellout.rb index 9562beec..7c49ab38 100644 --- a/lib/scm/shellout.rb +++ b/lib/scm/shellout.rb @@ -9,18 +9,8 @@ def self.relay src, dst end def self.execute(cmd) - out = '' - err = '' - exit_status = nil - Open3.popen3(cmd) { |stdin, stdout, stderr, wait_thread| - while line = stdout.gets - out << line - end - while line = stderr.gets - err << line - end - exit_status = wait_thread.value - } + out, err, exit_status = Open3.capture3(cmd) + return exit_status, out, err end diff --git a/test/unit/shellout_test.rb b/test/unit/shellout_test.rb new file mode 100644 index 00000000..dd8d4f27 --- /dev/null +++ b/test/unit/shellout_test.rb @@ -0,0 +1,25 @@ +require_relative '../test_helper' + +class ShelloutTest < Scm::Test + def test_execute_must_pipe_the_results_accurately + status, out, err = Shellout.execute("ruby -e 'puts %[hello world]; STDERR.puts(%[some error])'") + + assert_equal out, "hello world\n" + assert_equal err, "some error\n" + assert_equal status.success?, true + end + + def test_execute_must_return_appropriate_status_for_a_failed_process + status, out, err = Shellout.execute("ruby -e 'exit(1)'") + + assert_equal status.success?, false + end + + def test_execute_must_not_hang_when_io_buffer_is_full + assert_nothing_raised do + Timeout::timeout(1) do + Shellout.execute("ruby -e 'STDERR.puts(%[some line\n] * 10000)'") + end + end + end +end From 3a153412e524190169a5fa69c1d5ae810c7d9f53 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Thu, 2 Oct 2014 17:29:47 +0530 Subject: [PATCH 159/219] OTWO-3222: Fix svn checkout failures during svn-git conversion --- lib/scm/adapters/git/pull.rb | 7 +++++++ lib/scm/adapters/svn/misc.rb | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/lib/scm/adapters/git/pull.rb b/lib/scm/adapters/git/pull.rb index 6ea560f4..e99ccbe0 100644 --- a/lib/scm/adapters/git/pull.rb +++ b/lib/scm/adapters/git/pull.rb @@ -93,6 +93,13 @@ def convert(source_scm) r.scm.checkout(r, url) end + # Sometimes svn conflicts occur leading to a silent `svn checkout` failure. + if source_scm.is_a?(SvnAdapter) && SvnAdapter.has_conflicts?(url) + logger.info { "Working copy has svn conflicts. Cleaning and trying again..." } + clean_up_disk + r.scm.checkout(r, url) + end + logger.debug { "Committing revision #{r.token} (#{i+1} of #{commits.size})... " } commit_all(r) end diff --git a/lib/scm/adapters/svn/misc.rb b/lib/scm/adapters/svn/misc.rb index a9398257..89d45adf 100644 --- a/lib/scm/adapters/svn/misc.rb +++ b/lib/scm/adapters/svn/misc.rb @@ -132,5 +132,11 @@ def opt_auth opt_password = "--username='#{self.username}' --password='#{self.password}'" if self.username && self.username != '' " #{opt_password} --no-auth-cache " end + + class << self + def has_conflicts?(working_copy_url) + system("cd '#{ working_copy_url }' && svn status | grep 'Summary of conflicts'") + end + end end end From 8dd490b0479b366d6efee91b2ea2b7e080934535 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Sun, 5 Oct 2014 20:28:02 +0530 Subject: [PATCH 160/219] OTWO-3206: Fix utf-8 encoding issues for svn and git --- lib/scm/adapters/git/commits.rb | 2 +- lib/scm/adapters/svn/commits.rb | 6 ++-- lib/scm/adapters/svn/head.rb | 2 +- lib/scm/adapters/svn_chain/chain.rb | 2 +- test/bin/svn | 7 ++++ test/data/svn_with_invalid_encoding.log | 33 ++++++++++++++++++ .../git_with_invalid_encoding.tgz | Bin 5729 -> 6418 bytes test/test_helper.rb | 16 +++++++++ test/unit/git_commits_test.rb | 7 ++++ test/unit/git_head_test.rb | 7 ++++ test/unit/git_token_test.rb | 8 +++++ test/unit/svn_chain_test.rb | 5 +++ test/unit/svn_commits_test.rb | 27 +++++++++++--- test/unit/svn_head_test.rb | 8 +++++ 14 files changed, 119 insertions(+), 11 deletions(-) create mode 100755 test/bin/svn create mode 100644 test/data/svn_with_invalid_encoding.log diff --git a/lib/scm/adapters/git/commits.rb b/lib/scm/adapters/git/commits.rb index a49292d8..e71191e4 100644 --- a/lib/scm/adapters/git/commits.rb +++ b/lib/scm/adapters/git/commits.rb @@ -50,7 +50,7 @@ def each_commit(opts={}) # Returns a single commit, including its diffs def verbose_commit(token) - c = Scm::Parsers::GitStyledParser.parse(run("cd '#{url}' && #{Scm::Parsers::GitStyledParser.whatchanged} #{token}")).first + c = Scm::Parsers::GitStyledParser.parse(run("cd '#{url}' && #{Scm::Parsers::GitStyledParser.whatchanged} #{token} | #{ string_encoder }")).first fixup_null_merge(c) end diff --git a/lib/scm/adapters/svn/commits.rb b/lib/scm/adapters/svn/commits.rb index a3412311..d7220e98 100644 --- a/lib/scm/adapters/svn/commits.rb +++ b/lib/scm/adapters/svn/commits.rb @@ -144,7 +144,7 @@ def verbose_commit(rev) def log(opts={}) after = (opts[:after] || 0).to_i - run "svn log --trust-server-cert --non-interactive --xml --stop-on-copy -r #{after.to_i + 1}:#{final_token || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name.to_s))}@#{final_token || 'HEAD'}' #{opt_auth}" + run "svn log --trust-server-cert --non-interactive --xml --stop-on-copy -r #{after.to_i + 1}:#{final_token || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name.to_s))}@#{final_token || 'HEAD'}' #{opt_auth} | #{ string_encoder }" end def open_log_file(opts={}) @@ -154,7 +154,7 @@ def open_log_file(opts={}) # As a time optimization, just create an empty file rather than fetch a log we know will be empty. File.open(log_filename, 'w') { |f| f.puts '' } else - run "svn log --trust-server-cert --non-interactive --xml --stop-on-copy -r #{after + 1}:#{final_token || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}' #{opt_auth} > #{log_filename}" + run "svn log --trust-server-cert --non-interactive --xml --stop-on-copy -r #{after + 1}:#{final_token || 'HEAD'} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}' #{opt_auth} | #{ string_encoder } > #{log_filename}" end File.open(log_filename, 'r') { |io| yield io } ensure @@ -168,7 +168,7 @@ def log_filename # Returns one commit with the exact revision number provided def single_revision_xml(revision) - run "svn log --trust-server-cert --non-interactive --verbose --xml --stop-on-copy -r #{revision} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{revision}'" + run "svn log --trust-server-cert --non-interactive --verbose --xml --stop-on-copy -r #{revision} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{revision}' | #{ string_encoder }" end # Recurses the entire repository and returns an array of file names. diff --git a/lib/scm/adapters/svn/head.rb b/lib/scm/adapters/svn/head.rb index f95f43fb..698a81f2 100644 --- a/lib/scm/adapters/svn/head.rb +++ b/lib/scm/adapters/svn/head.rb @@ -11,7 +11,7 @@ def head def parents(commit) # Subversion doesn't have an actual "parent" command, so get # a log for this commit and the one preceding it, and keep only the preceding. - log = run "svn log --trust-server-cert --non-interactive --verbose --xml --stop-on-copy -r #{commit.token}:1 --limit 2 '#{SvnAdapter.uri_encode(self.url)}' #{opt_auth}" + log = run "svn log --trust-server-cert --non-interactive --verbose --xml --stop-on-copy -r #{commit.token}:1 --limit 2 '#{SvnAdapter.uri_encode(self.url)}' #{opt_auth} | #{ string_encoder }" [deepen_commit(strip_commit_branch(Scm::Parsers::SvnXmlParser.parse(log).last))] end end diff --git a/lib/scm/adapters/svn_chain/chain.rb b/lib/scm/adapters/svn_chain/chain.rb index af23523b..80e12a91 100644 --- a/lib/scm/adapters/svn_chain/chain.rb +++ b/lib/scm/adapters/svn_chain/chain.rb @@ -79,7 +79,7 @@ def first_commit(after=0) # Returns the first commit with a revision number greater than the provided revision number def next_revision_xml(after=0) return "" if after.to_i >= head_token - run "svn log --trust-server-cert --non-interactive --verbose --xml --stop-on-copy -r #{after.to_i+1}:#{final_token || 'HEAD'} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}'" + run "svn log --trust-server-cert --non-interactive --verbose --xml --stop-on-copy -r #{after.to_i+1}:#{final_token || 'HEAD'} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}' | #{ string_encoder }" end # If the passed diff represents the wholesale movement of the entire diff --git a/test/bin/svn b/test/bin/svn new file mode 100755 index 00000000..e5f2e9f6 --- /dev/null +++ b/test/bin/svn @@ -0,0 +1,7 @@ +#! /usr/bin/env bash +# This is for use with tests dealing with invalid encodings in svn log. +# This script returns a sample svn xml log with some non utf-8 characters. + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +cat $DIR/../data/svn_with_invalid_encoding.log diff --git a/test/data/svn_with_invalid_encoding.log b/test/data/svn_with_invalid_encoding.log new file mode 100644 index 00000000..7a2cf7d5 --- /dev/null +++ b/test/data/svn_with_invalid_encoding.log @@ -0,0 +1,33 @@ + + + +cartman +2000-08-29T18:45:43.000000Z +Ample parking day or night, people spouting: "Howdy, neighbor!" + + + +primus +2002-07-11T14:27:53.000000Z +I'm goin' down to South Park, gonna leave my woes behind. + +Thanks to Kenny Möller + + + +stan +2002-07-11T18:19:49.000000Z +Friendly faces everywhere, humble folks without temptation + + + +primus +2002-07-12T08:14:23.000000Z +I'm goin' down to South Park, gonna have myself a time. + + + diff --git a/test/repositories/git_with_invalid_encoding.tgz b/test/repositories/git_with_invalid_encoding.tgz index 24a3dd6a8f2014bc5fef110ea7b0d131e3421c68..5bf454bed1d28201591db1c23c888700dba658c8 100644 GIT binary patch literal 6418 zcmZ{nWmwaX`~B$iKBcvNXbc2EjBLtBiAks*O)I?fJTBJ)<(9tkbKzhVr z#2DNA=lA+Q{y(~(p6lG_I@jxPrBD!n>?QvrAVxY;Io$OEPFnH;S2S22r84CnOho=p zGEFvzbeQL`2YT$x{^Ra$NYB#=>*ufKS=_TLdq?-aM=Dx` zf=Eh)hvG-~jS@ zH^njQ#jS^8l^;`tJCt8meJo$+r6nGee}{hnJdF8#%ZGdvTP`uknZQFbW=L>af*bE2 z)cFmSds}G!ZIXJ@zHDm0ox1j5#sO6B?o6O&^aW}fEOk=~G#goaUY$4~^N znH@^osc0$@WgL#nELt|2O*7THJC(}H4?ta_i(s=5-Hd!_^uU|h7i=p!j(RX5E`-rW@UB<9)9o>NeXPojR*^ z=WUa}b9su|m1=aNhnv;`$O_jD1!*~R3TQ8ZFM>x0ZjfAqpBKIX)88#lqc<;=tiD}%K#%6u%-(;#?qdTXylhQ< zsBqz15~iGP=kLg||MX*h^QOdS1l7?C#_o&~D47QO#&}$lk9ncZB?CQD!C2p%gMPU2 zz@a3lJh!PLz*K1Vx0zy@@MU`)zIk+f9_HEuR7(rzYOH4{udM)@bQ7IG0MQx%T?rw^ zra!GQD=Z*;s78$B(sEtHcM8JMccZUC@MOqa$}}xnO-)0~Z7;bLLHPG(z3Z<=35elu7>I)5nidP!LBMkTGbEg2 zbJio$3Q^s7AYT#Qnnj9D>6~!59Z<2%%Xymj*g$$mz1rTS_@iHeR?sBvy27p8Cc2%N zP0&wT@u8A_zO_Sf@n-z0kDsl|=kNO)$LwaerIa+Z=|(*{eCbztsqNhX148m4(_U2T zd?(oVk-8G|_|f7$aQv`@T{$4n1&mUr?!we4LAlZL8r*Hvd4o)eQ*N!s9Qq3aV&rTIu3UkEpwfZJwjyR4+ zh0eubNuR@8fR|1hH;WUZ7*=Ms`-L_;p@9?FLGSE~^yIzrbR08okrL{D?eP4n$olxn zOfv^~^|eSndZpRb{%4e})2y6Y^YPNVQ&`*F$FG2v6+|Rd|#%a6q5gZI7K-Z4}{=(BzgGMa@4tPH1u@MjkD+yrI-#GBp9l6n@QBS zLmWeA%K^H?KkXRLaUkNBRW4DkgpN*CsR6bve!uTiY2zMpgT+)fz#>#@;Yn!c^rcm) zR+&XNot&%(Gc){j`EvQFvV0X)^+_zxIzLS*%l?(>cB-(@Ayzf~%x_Til|nH0{qZre->#QE;W9U6yXZ0* z;T3>1EL_j;4>waApYH&+xCYhy_QM>u`c;%GEjhIr|D!BFB+)0u7b1 zZ{7%!y))^(mOl#{nVo8c(1_a%{PlIpTx$D}zF_mV)tPW!+${vbhZ@!N_E>#n!1kPx zyVr}6@Wm&iMyrk+Ok{tFGTsYR3q1Uu3y{MW0Es?aJ|hU;Ur-f5!932ErRGJ!D^#45 zBAL^0w`G(tj&7y`ltuq)+YAOI(AUTU68g~*0GD8*oFyssx!-x^vvxblV{(*LldG1u zI|C7~6nlx_ZloLD%LT0T9g@59Ku*b(%8m|g(cK+r_xs$gb{}_GgIe5k3h?ZADs6r4 z@MDJINBXma$49ga3tibTJwc=EUc`43dpnwSKQjuJFd3y8D=6x)mSyY&B3{JSp>pn) zVy`8Kyu)gI6ecA(*4asMw|5~&6c8~!T*Uda4(l;xB;_`vD02YzocQs} zsxgX2x4p{kSDy?iV?`xm6XLrtR_VBC-OhhGO^K0ie~3*e`IVuhbWy}--6lL~<*4A| zD}^>U*4B|4?K>Q%(ep$rcu%Q5VtWk;gwh}&Jplkaj)U;CnySQDXK&i2(h`M z%uId}HL(vCOR&T!Na(R#E+4nyoleWs*5BfNA<{ZH z$Hzl?#TWOw{5?JG$GUtUgU*KnpGy=3^z-YHdI^Y9Om7jKHEN-$ z!-xuXGbQU8hfKuI2+0yx#-Yu(E7bQriHUAH>|V`88E%fGHlEg#+80?D?K~|lz3RKW z#TS!#BkuVH0*qp=p}sE4Kn8Wbg&UJ6h+Q4TUcJZ_n@ydZ`6Vvr56C$4alpUgUBFW{ zAGR+;B{R~2Z8B7q$`Lu{E+X-#8WRcq-uT|I>H~a2a^&XY-sBRRFxZ(8DmW-l$9g9i zjQ5Eg{h3|F>9O{6>J_a5*Q>tK+O*`r&K=GrS6H*5ZSUps#+xf&YUi%Nlgz=ZNAm_n zd5)(ScNUt!W>Zs7H~y4voM2&RHB|pt2?JjMUW@`R5x2B*5~WZw4Yp>Gx^6~ZSx#yO zk97A3HA=0|VZY|dTqO5@) z(YN8`tfNNIuLWNb8)k+mrp%dmt@A)%lUMTj4WEST<-y=dE?Cge7{d4OD2DNp`qLM{ z=gGzQMc}xmPzf^f)s~7>0L_U?xQ+&3!@5{O3EvA?ING&9iG`MFnF2Qu)G8Znmv;zJqi{`<*TmPpHrh*SF^Yj(YpXoR-lvT(F z`31n`dNs~lZqD!};=4c}sC~!{3GZfqrzA*PxgwbdNjaOYdnS6w~1pc%Yi|8~7V&UkLjC6Tn zmGAqgk)$l<2t}3T>?lcJAWl*5vl*%&dOS2OORUqie(#d2U3rS}hW{1PX8U;T$_|}Y zfGn1OG#2Q64$rT?`ud(%2+5WC!o%o3o7Q_LfDLc~fZ>Z2j;=vE{ zLR=v=AYv0{-772~^xDe9>a_e@rP34gv0&ZM<5HLgR~saN8~p$x7a?>a>nFd21{rL3Ld%Y9^j}!kzKTd!M0dOB6BNBq$B{=y4K$~z|NmMjW;dxm8lbw*&BeB?( z=nm8S**Up1Giz7iZ8O$X96ozT1dj~`z&|?yf1)i6IlaQq4EaOS=M*`AzBqh)9G@XU zGS1D!>&1}3PyOFNv6q0F?!RYlf&Yhg+-pHzAJZkc+R#X*DXT5zy?%wNhQ^a32HlCn zK2at^WrTZpQ^qmXTxep-+~v7udkHHkgkm3}8vgeiTY`ZPxLIiY7%yQ%<`L}lI8vH@ zX_OD|>(Q(#{>;&2J-}9Bp(wa(d9!osZOB1Lv~8eAM#b&(8Us1_M8f$oiyfJwaNg5> zs8|5kdgp%SHvxZrtIL+cT;M4)|{s!z`0I&qq?J#v6z!c*yt@&75H<8{h zJ~ow|e)y%~5I0D-EQ@Ro;Gv5$0wgoIfTH_7sld`~#;G`C0v`4&Y#oRmTmHa_t(Jb# z#k(nbF0pvM{tF=5YH9CQ(S5JDkxtGGx4CBvV-AP-L zP|7pqwtmQ#8}G3w+AAARf9Gk%{AV7)T*Y96+9d8=eNn#jq$)j?^6>W}6A~6w;gI1c zZpc1v?P~HBnXs~Gv&=h{Jj~r=dR0?b?wfj+ZCL?T(!#CtQ$f@e{zmG!4){*TdN$C4j-LT9b<#Lf9zV7d=w8?14z6q{qvO%k_}F9DI5*o6ejts|I+ z8(U=+&$-%tPvBwqh(A-T_YQPp47x?ugM+R}tl=#yjN#AkXC{~JelDJH(0goR=O3D+K+J-9RKP!7Ij^b??=@B5Hw~4(N!bBHdwC-P(Lpu;2v#!7FO~_Tk>&4} zyuojMoz^PG<^xxBw+IGMSCTh(e60hp5NwixsGrlXh?!vgmRx*k*lt7lIv4DXGR8abfPKA(9K z%nUf3*P&O>taJyN`T6nIk z>~GM9m>GVORt~Ms)rhwcs;;X`s*lTT{z*>#3*tdaDp{=?YIeq2ZjnQcZM>d2H4^Ww zvWKMJD3N_9yQifBg#WDtge5wJk`5sI{hp(@vll+^H3f-N{odv2|`DdoY_H5_EI ztCzE>Yoab_PEbwZsDIi>t^5+UY~6$J{#yosZQuNC2X3=mvGAZmkKO`93c;_+^;jWO zG)=han4ZBb&{7AdZ#4cOX>2;3#cZ|9Sg2NvEBn9v zE{!afh~H^v(hG6*AL^q}r7b)Bx8i@j`-)Z`I=5;{F*99sXmx(Bu_bJ6$@^sYbW@a) zdI_2Wx$%-{0gAKgCILYyp0GxkQ4(ZB~_o&Z>SmjLHt z-$KBZa-xtDtr#K^@EX_O4TjcAOhP-Bpiwxv&WZ*=4FH^{_r|1T8&|fC|MNyyjZTb8LcYf-nU=9{$(7Cd zclJ{Yq(}^@-F>~9nfj4xbco1^zumis+-iJQkH}<)DGVs&LrBtPUB0{8EX$Cu=qV2n z4Mmn1$B{jcXTg~tdnq?*9jNivQm^?H}oHppXzDI3*zXKS!?k)&Kwi literal 5729 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 "/trunk", :from_revision => 1, :from_path => "/branches/b")) end + def test_next_revision_xml_valid_encoding + with_invalid_encoded_svn_repository do |svn| + assert_equal true, svn.next_revision_xml(0).valid_encoding? + end + end end end diff --git a/test/unit/svn_commits_test.rb b/test/unit/svn_commits_test.rb index 607938f3..33e7e6a3 100644 --- a/test/unit/svn_commits_test.rb +++ b/test/unit/svn_commits_test.rb @@ -244,15 +244,32 @@ def test_each_commit assert_equal '/trunk/COPYING', commits[4].diffs[1].path end - # Invalid utf-8 characters in commit message or filename cause encoding errors. - # Svn converts invalid utf-8 characters into valid format before commit. - # So no utf-8 encoding issues are seen in ruby when dealing with Svn. + def test_log_valid_encoding + with_invalid_encoded_svn_repository do |svn| + assert_equal true, svn.log.valid_encoding? + end + end + def test_commits_encoding - with_svn_repository('svn_with_invalid_encoding') do |svn| + with_invalid_encoded_svn_repository do |svn| assert_nothing_raised do - svn.commits + svn.commits rescue raise Exception + end + end + end + + def test_open_log_file_encoding + with_invalid_encoded_svn_repository do |svn| + svn.open_log_file do |io| + assert_equal true, io.read.valid_encoding? end end end + + def test_single_revision_xml_valid_encoding + with_invalid_encoded_svn_repository do |svn| + assert_equal true, svn.single_revision_xml(:anything).valid_encoding? + end + end end end diff --git a/test/unit/svn_head_test.rb b/test/unit/svn_head_test.rb index 9e95ffd9..b08920fa 100644 --- a/test/unit/svn_head_test.rb +++ b/test/unit/svn_head_test.rb @@ -14,6 +14,14 @@ def test_head_and_parents end end + def test_parents_encoding + with_invalid_encoded_svn_repository do |svn| + assert_nothing_raised do + commit = Struct.new(:token).new(:anything) + svn.parents(commit) rescue raise Exception + end + end + end end end From 9da9218c698070ceea14ad3ada0e44a118d81050 Mon Sep 17 00:00:00 2001 From: Paddy Date: Thu, 9 Oct 2014 13:58:54 +0530 Subject: [PATCH 161/219] OTWO-3236 Fix SVN Failing Jobs (SlocJob) * Recently when using svn 1.8.8 and encountering a new directory change the expection wasn't handled and it was returning a non-zero exit code * Earlier in 1.6.6, it was returning 0 as exit code and hence it wasn't occuring * Now, the exception message has been updated matching the regex --- lib/scm/adapters/svn/cat_file.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scm/adapters/svn/cat_file.rb b/lib/scm/adapters/svn/cat_file.rb index b1712060..7563368a 100644 --- a/lib/scm/adapters/svn/cat_file.rb +++ b/lib/scm/adapters/svn/cat_file.rb @@ -12,7 +12,7 @@ def cat(path, revision) begin run "svn cat --trust-server-cert --non-interactive -r #{revision} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name.to_s, path.to_s))}@#{revision}'" rescue - raise unless $!.message =~ /svn:.*Could not cat all targets because some targets don't exist/ + raise unless $!.message =~ /svn:.*Could not cat all targets because some targets (don't exist|are directories)/ end end end From 8154441184252871bdf1e85fba29f2071e74d0bc Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Thu, 9 Oct 2014 15:50:47 +0530 Subject: [PATCH 162/219] OTWO-3248: Convert Ohloh SCM into a gem The function url_regex needs to match "@" in urls to support Ohloh's tests. Since rvm gem paths will have gemset@ruby pattern, @ can be a part of url for repositories inside this library's test folder. --- README.md | 5 +++++ lib/scm/adapters/bzr/validation.rb | 2 +- lib/scm/adapters/git/validation.rb | 2 +- lib/scm/adapters/hg/validation.rb | 2 +- lib/scm/adapters/svn/validation.rb | 2 +- lib/scm/version.rb | 5 +++++ ohloh_scm.gemspec | 19 +++++++++++++++++++ 7 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 lib/scm/version.rb create mode 100644 ohloh_scm.gemspec diff --git a/README.md b/README.md index 08eb3185..8096b37b 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,11 @@ hg 1.1.2 If you are using CVS instead of CVSNT, you can potentially try creating a shell alias or symlink mapping 'cvsnt' to 'cvs'. +## Usage with Bundler + +``` +gem 'ohloh_scm', git: 'https://github.com/blackducksw/ohloh_scm/', require: 'scm' +``` ## Running Ensure that cvsnt, svn, svnadmin, svnsync, git, and hg are all on your path. You'll also need to ensure that you have the xmloutput plugin installed for bazaar. diff --git a/lib/scm/adapters/bzr/validation.rb b/lib/scm/adapters/bzr/validation.rb index a29282be..199fb01e 100644 --- a/lib/scm/adapters/bzr/validation.rb +++ b/lib/scm/adapters/bzr/validation.rb @@ -1,7 +1,7 @@ module Scm::Adapters class BzrAdapter < AbstractAdapter def self.url_regex - /^((((http|https|bzr|bzr\+ssh|file):\/\/((\w+@)?[A-Za-z0-9_\-\.]+(:\d+)?\/)?)|(lp:[A-Za-z0-9_\-\.\~])))?[A-Za-z0-9_\-\.\/\~\+]*$/ + /^((((http|https|bzr|bzr\+ssh|file):\/\/((\w+@)?[A-Za-z0-9_\-\.]+(:\d+)?\/)?)|(lp:[A-Za-z0-9_\-\.\~])))?[A-Za-z0-9_@\-\.\/\~\+]*$/ end def self.public_url_regex diff --git a/lib/scm/adapters/git/validation.rb b/lib/scm/adapters/git/validation.rb index eba20539..884277cb 100644 --- a/lib/scm/adapters/git/validation.rb +++ b/lib/scm/adapters/git/validation.rb @@ -1,7 +1,7 @@ module Scm::Adapters class GitAdapter < AbstractAdapter def self.url_regex - /^(http|https|rsync|git|ssh):\/\/(\w+@)?[A-Za-z0-9_\-\.]+(:\d+)?\/[A-Za-z0-9_\-\.\/\~\+]*$/ + /^(http|https|rsync|git|ssh):\/\/(\w+@)?[A-Za-z0-9_\-\.]+(:\d+)?\/[A-Za-z0-9_@\-\.\/\~\+]*$/ end def self.public_url_regex diff --git a/lib/scm/adapters/hg/validation.rb b/lib/scm/adapters/hg/validation.rb index e2895474..b549121b 100644 --- a/lib/scm/adapters/hg/validation.rb +++ b/lib/scm/adapters/hg/validation.rb @@ -1,7 +1,7 @@ module Scm::Adapters class HgAdapter < AbstractAdapter def self.url_regex - /^((http|https|ssh|file):\/\/((\w+@)?[A-Za-z0-9_\-\.]+(:\d+)?\/)?)?[A-Za-z0-9_\-\.\/\~\+]*$/ + /^((http|https|ssh|file):\/\/((\w+@)?[A-Za-z0-9_\-\.]+(:\d+)?\/)?)?[A-Za-z0-9_@\-\.\/\~\+]*$/ end def self.public_url_regex diff --git a/lib/scm/adapters/svn/validation.rb b/lib/scm/adapters/svn/validation.rb index 49a2d3ea..101a9d18 100644 --- a/lib/scm/adapters/svn/validation.rb +++ b/lib/scm/adapters/svn/validation.rb @@ -1,7 +1,7 @@ module Scm::Adapters class SvnAdapter < AbstractAdapter def self.url_regex - /^(file|http|https|svn):\/\/(\/)?[A-Za-z0-9_\-\.]+(:\d+)?(\/[A-Za-z0-9_\-\.\/\+%^~ ]*)?$/ + /^(file|http|https|svn):\/\/(\/)?[A-Za-z0-9_\-\.]+(:\d+)?(\/[A-Za-z0-9_@\-\.\/\+%^~ ]*)?$/ end def self.public_url_regex diff --git a/lib/scm/version.rb b/lib/scm/version.rb new file mode 100644 index 00000000..9e2a3635 --- /dev/null +++ b/lib/scm/version.rb @@ -0,0 +1,5 @@ +module Scm + module Version + STRING = '0.0.1' + end +end diff --git a/ohloh_scm.gemspec b/ohloh_scm.gemspec new file mode 100644 index 00000000..09b7dcb9 --- /dev/null +++ b/ohloh_scm.gemspec @@ -0,0 +1,19 @@ +# -*- encoding: utf-8 -*- +$:.push File.expand_path("../lib", __FILE__) +require 'scm/version' + +Gem::Specification.new do |gem| + gem.name = 'ohloh_scm' + gem.version = Scm::Version::STRING + gem.authors = ["BlackDuck Software"] + gem.email = ["info@blackducksoftware.com"] + gem.summary = %[Source Control Management] + gem.description = %[The Ohloh source control management library] + gem.homepage = %[https://github.com/blackducksw/ohloh_scm/] + gem.license = %[GPL v2.0] + + gem.files = `git ls-files -z`.split("\x0") + gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) } + gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) + gem.require_paths = %w(lib) +end From 76cb53082963e79c32efeb72437eb86236234bc1 Mon Sep 17 00:00:00 2001 From: Peter Degen-Portnoy Date: Wed, 15 Oct 2014 05:55:07 -0400 Subject: [PATCH 163/219] Update version.rb Version 1.0 was the long-working version of this library running on Ruby 1.8.7 on CentOS 5.x. Version 2 is the new release running on Ruby 1.9.3 with updated versions of the SCM CLI's. --- lib/scm/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/scm/version.rb b/lib/scm/version.rb index 9e2a3635..2868efe2 100644 --- a/lib/scm/version.rb +++ b/lib/scm/version.rb @@ -1,5 +1,5 @@ module Scm module Version - STRING = '0.0.1' + STRING = '2.0.0' end end From ee93e372fc9ae5d59043d158471ab01331e1c9a0 Mon Sep 17 00:00:00 2001 From: Peter Degen-Portnoy Date: Wed, 15 Oct 2014 05:56:43 -0400 Subject: [PATCH 164/219] Update ohloh_scm.gemspec Change email to Open Hub contact email --- ohloh_scm.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ohloh_scm.gemspec b/ohloh_scm.gemspec index 09b7dcb9..ce47e001 100644 --- a/ohloh_scm.gemspec +++ b/ohloh_scm.gemspec @@ -6,7 +6,7 @@ Gem::Specification.new do |gem| gem.name = 'ohloh_scm' gem.version = Scm::Version::STRING gem.authors = ["BlackDuck Software"] - gem.email = ["info@blackducksoftware.com"] + gem.email = ["info@openhub.net"] gem.summary = %[Source Control Management] gem.description = %[The Ohloh source control management library] gem.homepage = %[https://github.com/blackducksw/ohloh_scm/] From 9da1b85fe9bb0c564a19d56a8e013bb8396f4e62 Mon Sep 17 00:00:00 2001 From: Peter Degen-Portnoy Date: Wed, 15 Oct 2014 11:09:02 +0000 Subject: [PATCH 165/219] Rename library to ohloh_scm --- README.md | 2 +- bin/ohlog | 4 +- lib/ohloh_scm.rb | 38 +++++++++++++++++++ .../adapters/abstract/misc.rb | 2 +- .../adapters/abstract/sha1.rb | 2 +- .../adapters/abstract/system.rb | 2 +- .../adapters/abstract/validation.rb | 2 +- .../adapters/abstract_adapter.rb | 2 +- .../adapters/bzr/cat_file.rb | 2 +- .../adapters/bzr/commits.rb | 8 ++-- lib/{scm => ohloh_scm}/adapters/bzr/head.rb | 2 +- lib/{scm => ohloh_scm}/adapters/bzr/misc.rb | 2 +- lib/{scm => ohloh_scm}/adapters/bzr/pull.rb | 2 +- lib/{scm => ohloh_scm}/adapters/bzr/push.rb | 2 +- .../adapters/bzr/validation.rb | 2 +- .../adapters/bzr_adapter.rb | 2 +- .../adapters/bzrlib/bzrlib_pipe_client.rb | 0 .../adapters/bzrlib/bzrlib_pipe_server.py | 0 .../adapters/bzrlib/cat_file.rb | 2 +- .../adapters/bzrlib/head.rb | 2 +- .../adapters/bzrlib_adapter.rb | 2 +- .../adapters/cvs/commits.rb | 4 +- lib/{scm => ohloh_scm}/adapters/cvs/misc.rb | 2 +- .../adapters/cvs/validation.rb | 2 +- .../adapters/cvs_adapter.rb | 2 +- lib/{scm => ohloh_scm}/adapters/factory.rb | 2 +- .../adapters/git/cat_file.rb | 2 +- .../adapters/git/commit_all.rb | 2 +- .../adapters/git/commits.rb | 10 ++--- lib/{scm => ohloh_scm}/adapters/git/head.rb | 2 +- lib/{scm => ohloh_scm}/adapters/git/misc.rb | 2 +- lib/{scm => ohloh_scm}/adapters/git/patch.rb | 2 +- lib/{scm => ohloh_scm}/adapters/git/pull.rb | 2 +- lib/{scm => ohloh_scm}/adapters/git/push.rb | 2 +- lib/{scm => ohloh_scm}/adapters/git/token.rb | 2 +- .../adapters/git/validation.rb | 2 +- .../adapters/git_adapter.rb | 2 +- .../adapters/hg/cat_file.rb | 2 +- lib/{scm => ohloh_scm}/adapters/hg/commits.rb | 14 +++---- lib/{scm => ohloh_scm}/adapters/hg/head.rb | 2 +- lib/{scm => ohloh_scm}/adapters/hg/misc.rb | 2 +- lib/{scm => ohloh_scm}/adapters/hg/patch.rb | 2 +- lib/{scm => ohloh_scm}/adapters/hg/pull.rb | 2 +- lib/{scm => ohloh_scm}/adapters/hg/push.rb | 2 +- .../adapters/hg/validation.rb | 2 +- lib/{scm => ohloh_scm}/adapters/hg_adapter.rb | 2 +- .../adapters/hglib/cat_file.rb | 2 +- .../adapters/hglib/client.rb | 0 lib/{scm => ohloh_scm}/adapters/hglib/head.rb | 2 +- .../adapters/hglib/server.py | 0 .../adapters/hglib_adapter.rb | 2 +- .../adapters/svn/cat_file.rb | 2 +- .../adapters/svn/commits.rb | 6 +-- lib/{scm => ohloh_scm}/adapters/svn/head.rb | 4 +- lib/{scm => ohloh_scm}/adapters/svn/misc.rb | 2 +- lib/{scm => ohloh_scm}/adapters/svn/patch.rb | 2 +- .../adapters/svn/pre-revprop-change | 0 lib/{scm => ohloh_scm}/adapters/svn/pull.rb | 2 +- lib/{scm => ohloh_scm}/adapters/svn/push.rb | 2 +- .../adapters/svn/validation.rb | 2 +- .../adapters/svn_adapter.rb | 2 +- .../adapters/svn_chain/cat_file.rb | 2 +- .../adapters/svn_chain/chain.rb | 4 +- .../adapters/svn_chain/commits.rb | 2 +- .../adapters/svn_chain_adapter.rb | 2 +- lib/{scm => ohloh_scm}/commit.rb | 0 lib/{scm => ohloh_scm}/diff.rb | 0 .../parsers/array_writer.rb | 2 +- .../parsers/branch_number.rb | 2 +- lib/{scm => ohloh_scm}/parsers/bzr_parser.rb | 2 +- .../parsers/bzr_xml_parser.rb | 2 +- lib/{scm => ohloh_scm}/parsers/cvs_parser.rb | 2 +- lib/{scm => ohloh_scm}/parsers/git_parser.rb | 2 +- .../parsers/git_styled_parser.rb | 2 +- lib/{scm => ohloh_scm}/parsers/hg_parser.rb | 2 +- lib/{scm => ohloh_scm}/parsers/hg_style | 0 .../parsers/hg_styled_parser.rb | 2 +- .../parsers/hg_verbose_style | 0 .../parsers/human_writer.rb | 2 +- lib/{scm => ohloh_scm}/parsers/parser.rb | 2 +- lib/{scm => ohloh_scm}/parsers/svn_parser.rb | 2 +- .../parsers/svn_xml_parser.rb | 2 +- lib/{scm => ohloh_scm}/parsers/xml_writer.rb | 2 +- lib/{scm => ohloh_scm}/scratch_dir.rb | 0 lib/{scm => ohloh_scm}/shellout.rb | 0 lib/{scm => ohloh_scm}/version.rb | 0 lib/scm.rb | 38 ------------------- ohloh_scm.gemspec | 6 +-- test/test_helper.rb | 24 ++++++------ test/unit/abstract_adapter_test.rb | 2 +- test/unit/adapter_factory_test.rb | 2 +- test/unit/array_writer_test.rb | 2 +- test/unit/bzr_cat_file_test.rb | 2 +- test/unit/bzr_commits_test.rb | 2 +- test/unit/bzr_head_test.rb | 2 +- test/unit/bzr_misc_test.rb | 2 +- test/unit/bzr_parser_test.rb | 2 +- test/unit/bzr_pull_test.rb | 2 +- test/unit/bzr_push_test.rb | 2 +- test/unit/bzr_validation_test.rb | 2 +- test/unit/bzr_xml_parser_test.rb | 2 +- test/unit/bzrlib_cat_file_test.rb | 2 +- test/unit/bzrlib_head_test.rb | 2 +- test/unit/cvs_branch_number_test.rb | 2 +- test/unit/cvs_commits_test.rb | 2 +- test/unit/cvs_convert_test.rb | 2 +- test/unit/cvs_misc_test.rb | 2 +- test/unit/cvs_parser_test.rb | 2 +- test/unit/cvs_validation_test.rb | 2 +- test/unit/git_cat_file_test.rb | 2 +- test/unit/git_commit_all_test.rb | 2 +- test/unit/git_commits_test.rb | 2 +- test/unit/git_head_test.rb | 2 +- test/unit/git_log_parser_test.rb | 2 +- test/unit/git_misc_test.rb | 2 +- test/unit/git_parser_test.rb | 2 +- test/unit/git_patch_test.rb | 2 +- test/unit/git_pull_test.rb | 2 +- test/unit/git_push_test.rb | 2 +- test/unit/git_rev_list_test.rb | 2 +- test/unit/git_styled_parser_test.rb | 2 +- test/unit/git_token_test.rb | 2 +- test/unit/git_validation_test.rb | 2 +- test/unit/hg_cat_file_test.rb | 2 +- test/unit/hg_commits_test.rb | 2 +- test/unit/hg_head_test.rb | 2 +- test/unit/hg_misc_test.rb | 2 +- test/unit/hg_parser_test.rb | 10 ++--- test/unit/hg_patch_test.rb | 2 +- test/unit/hg_pull_test.rb | 2 +- test/unit/hg_push_test.rb | 2 +- test/unit/hg_rev_list_test.rb | 2 +- test/unit/hg_validation_test.rb | 2 +- test/unit/hglib_cat_file_test.rb | 2 +- test/unit/hglib_head_test.rb | 2 +- test/unit/ohlog_command_line_test.rb | 2 +- test/unit/string_encoder_command_line_test.rb | 6 +-- test/unit/svn_cat_file_test.rb | 2 +- test/unit/svn_chain_cat_file_test.rb | 2 +- test/unit/svn_chain_commits_test.rb | 2 +- test/unit/svn_chain_test.rb | 4 +- test/unit/svn_commits_test.rb | 2 +- test/unit/svn_convert_test.rb | 2 +- test/unit/svn_head_test.rb | 2 +- test/unit/svn_misc_test.rb | 2 +- test/unit/svn_parser_test.rb | 2 +- test/unit/svn_patch_test.rb | 2 +- test/unit/svn_pull_test.rb | 2 +- test/unit/svn_push_test.rb | 2 +- test/unit/svn_validation_test.rb | 2 +- test/unit/svn_xml_parser_test.rb | 2 +- 151 files changed, 214 insertions(+), 214 deletions(-) create mode 100644 lib/ohloh_scm.rb rename lib/{scm => ohloh_scm}/adapters/abstract/misc.rb (75%) rename lib/{scm => ohloh_scm}/adapters/abstract/sha1.rb (97%) rename lib/{scm => ohloh_scm}/adapters/abstract/system.rb (97%) rename lib/{scm => ohloh_scm}/adapters/abstract/validation.rb (98%) rename lib/{scm => ohloh_scm}/adapters/abstract_adapter.rb (96%) rename lib/{scm => ohloh_scm}/adapters/bzr/cat_file.rb (96%) rename lib/{scm => ohloh_scm}/adapters/bzr/commits.rb (94%) rename lib/{scm => ohloh_scm}/adapters/bzr/head.rb (94%) rename lib/{scm => ohloh_scm}/adapters/bzr/misc.rb (97%) rename lib/{scm => ohloh_scm}/adapters/bzr/pull.rb (95%) rename lib/{scm => ohloh_scm}/adapters/bzr/push.rb (97%) rename lib/{scm => ohloh_scm}/adapters/bzr/validation.rb (95%) rename lib/{scm => ohloh_scm}/adapters/bzr_adapter.rb (91%) rename lib/{scm => ohloh_scm}/adapters/bzrlib/bzrlib_pipe_client.rb (100%) rename lib/{scm => ohloh_scm}/adapters/bzrlib/bzrlib_pipe_server.py (100%) rename lib/{scm => ohloh_scm}/adapters/bzrlib/cat_file.rb (83%) rename lib/{scm => ohloh_scm}/adapters/bzrlib/head.rb (82%) rename lib/{scm => ohloh_scm}/adapters/bzrlib_adapter.rb (93%) rename lib/{scm => ohloh_scm}/adapters/cvs/commits.rb (97%) rename lib/{scm => ohloh_scm}/adapters/cvs/misc.rb (99%) rename lib/{scm => ohloh_scm}/adapters/cvs/validation.rb (99%) rename lib/{scm => ohloh_scm}/adapters/cvs_adapter.rb (91%) rename lib/{scm => ohloh_scm}/adapters/factory.rb (97%) rename lib/{scm => ohloh_scm}/adapters/git/cat_file.rb (91%) rename lib/{scm => ohloh_scm}/adapters/git/commit_all.rb (99%) rename lib/{scm => ohloh_scm}/adapters/git/commits.rb (88%) rename lib/{scm => ohloh_scm}/adapters/git/head.rb (94%) rename lib/{scm => ohloh_scm}/adapters/git/misc.rb (98%) rename lib/{scm => ohloh_scm}/adapters/git/patch.rb (88%) rename lib/{scm => ohloh_scm}/adapters/git/pull.rb (99%) rename lib/{scm => ohloh_scm}/adapters/git/push.rb (97%) rename lib/{scm => ohloh_scm}/adapters/git/token.rb (98%) rename lib/{scm => ohloh_scm}/adapters/git/validation.rb (98%) rename lib/{scm => ohloh_scm}/adapters/git_adapter.rb (93%) rename lib/{scm => ohloh_scm}/adapters/hg/cat_file.rb (96%) rename lib/{scm => ohloh_scm}/adapters/hg/commits.rb (86%) rename lib/{scm => ohloh_scm}/adapters/hg/head.rb (96%) rename lib/{scm => ohloh_scm}/adapters/hg/misc.rb (95%) rename lib/{scm => ohloh_scm}/adapters/hg/patch.rb (89%) rename lib/{scm => ohloh_scm}/adapters/hg/pull.rb (95%) rename lib/{scm => ohloh_scm}/adapters/hg/push.rb (97%) rename lib/{scm => ohloh_scm}/adapters/hg/validation.rb (95%) rename lib/{scm => ohloh_scm}/adapters/hg_adapter.rb (92%) rename lib/{scm => ohloh_scm}/adapters/hglib/cat_file.rb (91%) rename lib/{scm => ohloh_scm}/adapters/hglib/client.rb (100%) rename lib/{scm => ohloh_scm}/adapters/hglib/head.rb (83%) rename lib/{scm => ohloh_scm}/adapters/hglib/server.py (100%) rename lib/{scm => ohloh_scm}/adapters/hglib_adapter.rb (93%) rename lib/{scm => ohloh_scm}/adapters/svn/cat_file.rb (95%) rename lib/{scm => ohloh_scm}/adapters/svn/commits.rb (98%) rename lib/{scm => ohloh_scm}/adapters/svn/head.rb (82%) rename lib/{scm => ohloh_scm}/adapters/svn/misc.rb (99%) rename lib/{scm => ohloh_scm}/adapters/svn/patch.rb (89%) rename lib/{scm => ohloh_scm}/adapters/svn/pre-revprop-change (100%) rename lib/{scm => ohloh_scm}/adapters/svn/pull.rb (98%) rename lib/{scm => ohloh_scm}/adapters/svn/push.rb (89%) rename lib/{scm => ohloh_scm}/adapters/svn/validation.rb (99%) rename lib/{scm => ohloh_scm}/adapters/svn_adapter.rb (92%) rename lib/{scm => ohloh_scm}/adapters/svn_chain/cat_file.rb (85%) rename lib/{scm => ohloh_scm}/adapters/svn_chain/chain.rb (96%) rename lib/{scm => ohloh_scm}/adapters/svn_chain/commits.rb (98%) rename lib/{scm => ohloh_scm}/adapters/svn_chain_adapter.rb (98%) rename lib/{scm => ohloh_scm}/commit.rb (100%) rename lib/{scm => ohloh_scm}/diff.rb (100%) rename lib/{scm => ohloh_scm}/parsers/array_writer.rb (90%) rename lib/{scm => ohloh_scm}/parsers/branch_number.rb (98%) rename lib/{scm => ohloh_scm}/parsers/bzr_parser.rb (99%) rename lib/{scm => ohloh_scm}/parsers/bzr_xml_parser.rb (99%) rename lib/{scm => ohloh_scm}/parsers/cvs_parser.rb (99%) rename lib/{scm => ohloh_scm}/parsers/git_parser.rb (98%) rename lib/{scm => ohloh_scm}/parsers/git_styled_parser.rb (99%) rename lib/{scm => ohloh_scm}/parsers/hg_parser.rb (98%) rename lib/{scm => ohloh_scm}/parsers/hg_style (100%) rename lib/{scm => ohloh_scm}/parsers/hg_styled_parser.rb (98%) rename lib/{scm => ohloh_scm}/parsers/hg_verbose_style (100%) rename lib/{scm => ohloh_scm}/parsers/human_writer.rb (98%) rename lib/{scm => ohloh_scm}/parsers/parser.rb (95%) rename lib/{scm => ohloh_scm}/parsers/svn_parser.rb (98%) rename lib/{scm => ohloh_scm}/parsers/svn_xml_parser.rb (98%) rename lib/{scm => ohloh_scm}/parsers/xml_writer.rb (98%) rename lib/{scm => ohloh_scm}/scratch_dir.rb (100%) rename lib/{scm => ohloh_scm}/shellout.rb (100%) rename lib/{scm => ohloh_scm}/version.rb (100%) delete mode 100644 lib/scm.rb diff --git a/README.md b/README.md index 8096b37b..e9a3adf4 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ Then you can run the unit tests: $ rake -You can load the library into your own Ruby application by requiring lib/scm.rb. +You can load the library into your own Ruby application by requiring lib/ohloh_scm.rb. # Functionality diff --git a/bin/ohlog b/bin/ohlog index 172926de..d814afc1 100755 --- a/bin/ohlog +++ b/bin/ohlog @@ -1,12 +1,12 @@ #!/usr/bin/env ruby -require File.dirname(__FILE__) + '/../lib/scm' +require File.dirname(__FILE__) + '/../lib/ohloh_scm' # This is a simple command line tool which parses CVS and Subversion logs. # It is not used by the main Ohloh system. # # I use it primarily to help debug Ohloh behavior. It's a convenient way # to turn an enormously long CVS log into something readable. -module Scm::Parsers +module OhlohScm::Parsers class CommandLine attr_accessor :paths, :writer diff --git a/lib/ohloh_scm.rb b/lib/ohloh_scm.rb new file mode 100644 index 00000000..cf0c9299 --- /dev/null +++ b/lib/ohloh_scm.rb @@ -0,0 +1,38 @@ +module OhlohScm +end + +#require 'rbconfig' + +#$: << File.join(File.dirname(__FILE__),"..") + +require_relative 'ohloh_scm/shellout' +require_relative 'ohloh_scm/scratch_dir' +require_relative 'ohloh_scm/commit' +require_relative 'ohloh_scm/diff' + +require_relative 'ohloh_scm/adapters/abstract_adapter' +require_relative 'ohloh_scm/adapters/cvs_adapter' +require_relative 'ohloh_scm/adapters/svn_adapter' +require_relative 'ohloh_scm/adapters/svn_chain_adapter' +require_relative 'ohloh_scm/adapters/git_adapter' +require_relative 'ohloh_scm/adapters/hg_adapter' +require_relative 'ohloh_scm/adapters/hglib_adapter' +require_relative 'ohloh_scm/adapters/bzr_adapter' +require_relative 'ohloh_scm/adapters/bzrlib_adapter' +require_relative 'ohloh_scm/adapters/factory' + +require_relative 'ohloh_scm/parsers/parser' +require_relative 'ohloh_scm/parsers/branch_number' +require_relative 'ohloh_scm/parsers/cvs_parser' +require_relative 'ohloh_scm/parsers/svn_parser' +require_relative 'ohloh_scm/parsers/svn_xml_parser' +require_relative 'ohloh_scm/parsers/git_parser' +require_relative 'ohloh_scm/parsers/git_styled_parser' +require_relative 'ohloh_scm/parsers/hg_parser' +require_relative 'ohloh_scm/parsers/hg_styled_parser' +require_relative 'ohloh_scm/parsers/bzr_xml_parser' +require_relative 'ohloh_scm/parsers/bzr_parser' + +require_relative 'ohloh_scm/parsers/array_writer' +require_relative 'ohloh_scm/parsers/xml_writer' +require_relative 'ohloh_scm/parsers/human_writer' diff --git a/lib/scm/adapters/abstract/misc.rb b/lib/ohloh_scm/adapters/abstract/misc.rb similarity index 75% rename from lib/scm/adapters/abstract/misc.rb rename to lib/ohloh_scm/adapters/abstract/misc.rb index f0552328..357ac0c3 100644 --- a/lib/scm/adapters/abstract/misc.rb +++ b/lib/ohloh_scm/adapters/abstract/misc.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class AbstractAdapter def is_merge_commit?(commit) diff --git a/lib/scm/adapters/abstract/sha1.rb b/lib/ohloh_scm/adapters/abstract/sha1.rb similarity index 97% rename from lib/scm/adapters/abstract/sha1.rb rename to lib/ohloh_scm/adapters/abstract/sha1.rb index f26601a1..cd1c5447 100644 --- a/lib/scm/adapters/abstract/sha1.rb +++ b/lib/ohloh_scm/adapters/abstract/sha1.rb @@ -2,7 +2,7 @@ NULL_SHA1 = '0000000000000000000000000000000000000000' unless defined?(NULL_SHA1) -module Scm::Adapters +module OhlohScm::Adapters class AbstractAdapter # This file provides SHA1 computation helpers for source control systems that diff --git a/lib/scm/adapters/abstract/system.rb b/lib/ohloh_scm/adapters/abstract/system.rb similarity index 97% rename from lib/scm/adapters/abstract/system.rb rename to lib/ohloh_scm/adapters/abstract/system.rb index aa223d0b..922c14ed 100644 --- a/lib/scm/adapters/abstract/system.rb +++ b/lib/ohloh_scm/adapters/abstract/system.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters require 'logger' class AbstractAdapter def self.logger diff --git a/lib/scm/adapters/abstract/validation.rb b/lib/ohloh_scm/adapters/abstract/validation.rb similarity index 98% rename from lib/scm/adapters/abstract/validation.rb rename to lib/ohloh_scm/adapters/abstract/validation.rb index 15f7f3d6..78c47e7e 100644 --- a/lib/scm/adapters/abstract/validation.rb +++ b/lib/ohloh_scm/adapters/abstract/validation.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class AbstractAdapter # The full regex that permits all possible URLs supported by the source control system. def self.url_regex diff --git a/lib/scm/adapters/abstract_adapter.rb b/lib/ohloh_scm/adapters/abstract_adapter.rb similarity index 96% rename from lib/scm/adapters/abstract_adapter.rb rename to lib/ohloh_scm/adapters/abstract_adapter.rb index 973c0f41..47d468d4 100644 --- a/lib/scm/adapters/abstract_adapter.rb +++ b/lib/ohloh_scm/adapters/abstract_adapter.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class AbstractAdapter attr_accessor :url, :branch_name, :username, :password, :errors, :public_urls_only diff --git a/lib/scm/adapters/bzr/cat_file.rb b/lib/ohloh_scm/adapters/bzr/cat_file.rb similarity index 96% rename from lib/scm/adapters/bzr/cat_file.rb rename to lib/ohloh_scm/adapters/bzr/cat_file.rb index bc0cc529..0c21b26c 100644 --- a/lib/scm/adapters/bzr/cat_file.rb +++ b/lib/ohloh_scm/adapters/bzr/cat_file.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class BzrAdapter < AbstractAdapter def cat_file(commit, diff) cat(commit.token, diff.path) diff --git a/lib/scm/adapters/bzr/commits.rb b/lib/ohloh_scm/adapters/bzr/commits.rb similarity index 94% rename from lib/scm/adapters/bzr/commits.rb rename to lib/ohloh_scm/adapters/bzr/commits.rb index 863744d0..2426fecc 100644 --- a/lib/scm/adapters/bzr/commits.rb +++ b/lib/ohloh_scm/adapters/bzr/commits.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class BzrAdapter < AbstractAdapter # Return the number of commits in the repository following +after+. @@ -19,7 +19,7 @@ def commit_tokens(opts={}) def commits(opts={}) after = opts[:after] log = run("#{rev_list_command(opts)} | cat") - a = Scm::Parsers::BzrXmlParser.parse(log) + a = OhlohScm::Parsers::BzrXmlParser.parse(log) if after && i = a.index { |commit| commit.token == after } a[(i+1)..-1] @@ -31,7 +31,7 @@ def commits(opts={}) # Returns a single commit, including its diffs def verbose_commit(token) log = run("cd '#{self.url}' && bzr xmllog --show-id -v --limit 1 -c #{to_rev_param(token)}") - Scm::Parsers::BzrXmlParser.parse(log).first + OhlohScm::Parsers::BzrXmlParser.parse(log).first end # Yields each commit after +after+, including its diffs. @@ -44,7 +44,7 @@ def each_commit(opts={}) skip_commits = !!after # Don't emit any commits until the 'after' resume point passes open_log_file(opts) do |io| - Scm::Parsers::BzrXmlParser.parse(io) do |commit| + OhlohScm::Parsers::BzrXmlParser.parse(io) do |commit| yield remove_directories(commit) if block_given? && !skip_commits skip_commits = false if commit.token == after end diff --git a/lib/scm/adapters/bzr/head.rb b/lib/ohloh_scm/adapters/bzr/head.rb similarity index 94% rename from lib/scm/adapters/bzr/head.rb rename to lib/ohloh_scm/adapters/bzr/head.rb index d35eba95..5abaedcf 100644 --- a/lib/scm/adapters/bzr/head.rb +++ b/lib/ohloh_scm/adapters/bzr/head.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class BzrAdapter < AbstractAdapter def head_token run("bzr log --limit 1 --show-id #{url} 2> /dev/null | grep ^revision-id | cut -f2 -d' '").strip diff --git a/lib/scm/adapters/bzr/misc.rb b/lib/ohloh_scm/adapters/bzr/misc.rb similarity index 97% rename from lib/scm/adapters/bzr/misc.rb rename to lib/ohloh_scm/adapters/bzr/misc.rb index 07d69413..12f5b9a5 100644 --- a/lib/scm/adapters/bzr/misc.rb +++ b/lib/ohloh_scm/adapters/bzr/misc.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class BzrAdapter < AbstractAdapter def exist? begin diff --git a/lib/scm/adapters/bzr/pull.rb b/lib/ohloh_scm/adapters/bzr/pull.rb similarity index 95% rename from lib/scm/adapters/bzr/pull.rb rename to lib/ohloh_scm/adapters/bzr/pull.rb index ec51ffa9..a02f9646 100644 --- a/lib/scm/adapters/bzr/pull.rb +++ b/lib/ohloh_scm/adapters/bzr/pull.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class BzrAdapter < AbstractAdapter def pull(from, &block) diff --git a/lib/scm/adapters/bzr/push.rb b/lib/ohloh_scm/adapters/bzr/push.rb similarity index 97% rename from lib/scm/adapters/bzr/push.rb rename to lib/ohloh_scm/adapters/bzr/push.rb index cff83d75..a84c1709 100644 --- a/lib/scm/adapters/bzr/push.rb +++ b/lib/ohloh_scm/adapters/bzr/push.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class BzrAdapter < AbstractAdapter def push(to, &block) diff --git a/lib/scm/adapters/bzr/validation.rb b/lib/ohloh_scm/adapters/bzr/validation.rb similarity index 95% rename from lib/scm/adapters/bzr/validation.rb rename to lib/ohloh_scm/adapters/bzr/validation.rb index 199fb01e..33adcfaa 100644 --- a/lib/scm/adapters/bzr/validation.rb +++ b/lib/ohloh_scm/adapters/bzr/validation.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class BzrAdapter < AbstractAdapter def self.url_regex /^((((http|https|bzr|bzr\+ssh|file):\/\/((\w+@)?[A-Za-z0-9_\-\.]+(:\d+)?\/)?)|(lp:[A-Za-z0-9_\-\.\~])))?[A-Za-z0-9_@\-\.\/\~\+]*$/ diff --git a/lib/scm/adapters/bzr_adapter.rb b/lib/ohloh_scm/adapters/bzr_adapter.rb similarity index 91% rename from lib/scm/adapters/bzr_adapter.rb rename to lib/ohloh_scm/adapters/bzr_adapter.rb index ef0e81f0..f0fd82d6 100644 --- a/lib/scm/adapters/bzr_adapter.rb +++ b/lib/ohloh_scm/adapters/bzr_adapter.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class BzrAdapter < AbstractAdapter def english_name "Bazaar" diff --git a/lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb b/lib/ohloh_scm/adapters/bzrlib/bzrlib_pipe_client.rb similarity index 100% rename from lib/scm/adapters/bzrlib/bzrlib_pipe_client.rb rename to lib/ohloh_scm/adapters/bzrlib/bzrlib_pipe_client.rb diff --git a/lib/scm/adapters/bzrlib/bzrlib_pipe_server.py b/lib/ohloh_scm/adapters/bzrlib/bzrlib_pipe_server.py similarity index 100% rename from lib/scm/adapters/bzrlib/bzrlib_pipe_server.py rename to lib/ohloh_scm/adapters/bzrlib/bzrlib_pipe_server.py diff --git a/lib/scm/adapters/bzrlib/cat_file.rb b/lib/ohloh_scm/adapters/bzrlib/cat_file.rb similarity index 83% rename from lib/scm/adapters/bzrlib/cat_file.rb rename to lib/ohloh_scm/adapters/bzrlib/cat_file.rb index 06eb4059..111c67a4 100644 --- a/lib/scm/adapters/bzrlib/cat_file.rb +++ b/lib/ohloh_scm/adapters/bzrlib/cat_file.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class BzrlibAdapter < BzrAdapter def cat(revision, path) diff --git a/lib/scm/adapters/bzrlib/head.rb b/lib/ohloh_scm/adapters/bzrlib/head.rb similarity index 82% rename from lib/scm/adapters/bzrlib/head.rb rename to lib/ohloh_scm/adapters/bzrlib/head.rb index fe1f1364..147e076a 100644 --- a/lib/scm/adapters/bzrlib/head.rb +++ b/lib/ohloh_scm/adapters/bzrlib/head.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class BzrlibAdapter < BzrAdapter def parent_tokens(commit) diff --git a/lib/scm/adapters/bzrlib_adapter.rb b/lib/ohloh_scm/adapters/bzrlib_adapter.rb similarity index 93% rename from lib/scm/adapters/bzrlib_adapter.rb rename to lib/ohloh_scm/adapters/bzrlib_adapter.rb index c836026a..512cd937 100644 --- a/lib/scm/adapters/bzrlib_adapter.rb +++ b/lib/ohloh_scm/adapters/bzrlib_adapter.rb @@ -1,7 +1,7 @@ require 'rubygems' require_relative 'bzrlib/bzrlib_pipe_client' -module Scm::Adapters +module OhlohScm::Adapters class BzrlibAdapter < BzrAdapter def setup diff --git a/lib/scm/adapters/cvs/commits.rb b/lib/ohloh_scm/adapters/cvs/commits.rb similarity index 97% rename from lib/scm/adapters/cvs/commits.rb rename to lib/ohloh_scm/adapters/cvs/commits.rb index 53ad58d9..51aa3fd7 100644 --- a/lib/scm/adapters/cvs/commits.rb +++ b/lib/ohloh_scm/adapters/cvs/commits.rb @@ -1,11 +1,11 @@ -module Scm::Adapters +module OhlohScm::Adapters class CvsAdapter def commits(opts={}) after = opts[:after] result = [] open_log_file(opts) do |io| - result = Scm::Parsers::CvsParser.parse(io, :branch_name => branch_name) + result = OhlohScm::Parsers::CvsParser.parse(io, :branch_name => branch_name) end # Git converter needs a backpointer to the scm for each commit diff --git a/lib/scm/adapters/cvs/misc.rb b/lib/ohloh_scm/adapters/cvs/misc.rb similarity index 99% rename from lib/scm/adapters/cvs/misc.rb rename to lib/ohloh_scm/adapters/cvs/misc.rb index 258a4067..c53b9a7e 100644 --- a/lib/scm/adapters/cvs/misc.rb +++ b/lib/ohloh_scm/adapters/cvs/misc.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class CvsAdapter # Returns an array of file and directory names from the remote server. # Directory names will end with a trailing '/' character. diff --git a/lib/scm/adapters/cvs/validation.rb b/lib/ohloh_scm/adapters/cvs/validation.rb similarity index 99% rename from lib/scm/adapters/cvs/validation.rb rename to lib/ohloh_scm/adapters/cvs/validation.rb index 9677514c..53a4b7f8 100644 --- a/lib/scm/adapters/cvs/validation.rb +++ b/lib/ohloh_scm/adapters/cvs/validation.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class CvsAdapter def self.url_regex /^(:(pserver|ext):[\w\-\+\_]*(:[\w\-\+\_]*)?@[A-Za-z0-9_\-\+\.]+:[0-9]*)?\/[A-Za-z0-9_\-\+\.\/]*$/ diff --git a/lib/scm/adapters/cvs_adapter.rb b/lib/ohloh_scm/adapters/cvs_adapter.rb similarity index 91% rename from lib/scm/adapters/cvs_adapter.rb rename to lib/ohloh_scm/adapters/cvs_adapter.rb index 3fd76ced..b5c2a328 100644 --- a/lib/scm/adapters/cvs_adapter.rb +++ b/lib/ohloh_scm/adapters/cvs_adapter.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class CvsAdapter < AbstractAdapter attr_accessor :module_name diff --git a/lib/scm/adapters/factory.rb b/lib/ohloh_scm/adapters/factory.rb similarity index 97% rename from lib/scm/adapters/factory.rb rename to lib/ohloh_scm/adapters/factory.rb index b9e1e661..920aad81 100644 --- a/lib/scm/adapters/factory.rb +++ b/lib/ohloh_scm/adapters/factory.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class Factory # Given a local path on disk, try to guess what kind of repository it is, diff --git a/lib/scm/adapters/git/cat_file.rb b/lib/ohloh_scm/adapters/git/cat_file.rb similarity index 91% rename from lib/scm/adapters/git/cat_file.rb rename to lib/ohloh_scm/adapters/git/cat_file.rb index a2e15258..0b6165a9 100644 --- a/lib/scm/adapters/git/cat_file.rb +++ b/lib/ohloh_scm/adapters/git/cat_file.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class GitAdapter < AbstractAdapter def cat_file(commit, diff) cat(diff.sha1) diff --git a/lib/scm/adapters/git/commit_all.rb b/lib/ohloh_scm/adapters/git/commit_all.rb similarity index 99% rename from lib/scm/adapters/git/commit_all.rb rename to lib/ohloh_scm/adapters/git/commit_all.rb index 353f6c5f..2493248f 100644 --- a/lib/scm/adapters/git/commit_all.rb +++ b/lib/ohloh_scm/adapters/git/commit_all.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class GitAdapter < AbstractAdapter #--------------------------------------------------------------------------- diff --git a/lib/scm/adapters/git/commits.rb b/lib/ohloh_scm/adapters/git/commits.rb similarity index 88% rename from lib/scm/adapters/git/commits.rb rename to lib/ohloh_scm/adapters/git/commits.rb index e71191e4..9b79d808 100644 --- a/lib/scm/adapters/git/commits.rb +++ b/lib/ohloh_scm/adapters/git/commits.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class GitAdapter < AbstractAdapter # Returns the number of commits in the repository following the commit with SHA1 'after'. @@ -41,7 +41,7 @@ def each_commit(opts={}) previous = nil open_log_file(opts) do |io| - Scm::Parsers::GitStyledParser.parse(io) do |e| + OhlohScm::Parsers::GitStyledParser.parse(io) do |e| yield fixup_null_merge(e) unless previous && previous.token == e.token previous = e end @@ -50,7 +50,7 @@ def each_commit(opts={}) # Returns a single commit, including its diffs def verbose_commit(token) - c = Scm::Parsers::GitStyledParser.parse(run("cd '#{url}' && #{Scm::Parsers::GitStyledParser.whatchanged} #{token} | #{ string_encoder }")).first + c = OhlohScm::Parsers::GitStyledParser.parse(run("cd '#{url}' && #{OhlohScm::Parsers::GitStyledParser.whatchanged} #{token} | #{ string_encoder }")).first fixup_null_merge(c) end @@ -80,7 +80,7 @@ def log(opts={}) if opts[:after] && opts[:after]==self.head_token '' # Nothing new. else - run "#{rev_list_command(opts)} | xargs -n 1 #{Scm::Parsers::GitStyledParser.whatchanged} | #{ string_encoder }" + run "#{rev_list_command(opts)} | xargs -n 1 #{OhlohScm::Parsers::GitStyledParser.whatchanged} | #{ string_encoder }" end else '' @@ -96,7 +96,7 @@ def open_log_file(opts={}) '' # Nothing new. else begin - run "#{rev_list_command(opts)} | xargs -n 1 #{Scm::Parsers::GitStyledParser.whatchanged} | #{ string_encoder } > #{log_filename}" + run "#{rev_list_command(opts)} | xargs -n 1 #{OhlohScm::Parsers::GitStyledParser.whatchanged} | #{ string_encoder } > #{log_filename}" File.open(log_filename, 'r') { |io| yield io } ensure File.delete(log_filename) if FileTest.exist?(log_filename) diff --git a/lib/scm/adapters/git/head.rb b/lib/ohloh_scm/adapters/git/head.rb similarity index 94% rename from lib/scm/adapters/git/head.rb rename to lib/ohloh_scm/adapters/git/head.rb index 851de72d..1cc80acd 100644 --- a/lib/scm/adapters/git/head.rb +++ b/lib/ohloh_scm/adapters/git/head.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class GitAdapter < AbstractAdapter def head_token diff --git a/lib/scm/adapters/git/misc.rb b/lib/ohloh_scm/adapters/git/misc.rb similarity index 98% rename from lib/scm/adapters/git/misc.rb rename to lib/ohloh_scm/adapters/git/misc.rb index 4faa38c3..1e99df3e 100644 --- a/lib/scm/adapters/git/misc.rb +++ b/lib/ohloh_scm/adapters/git/misc.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class GitAdapter < AbstractAdapter def git_path File.join(self.url, '/.git') diff --git a/lib/scm/adapters/git/patch.rb b/lib/ohloh_scm/adapters/git/patch.rb similarity index 88% rename from lib/scm/adapters/git/patch.rb rename to lib/ohloh_scm/adapters/git/patch.rb index 33411f92..cc234969 100644 --- a/lib/scm/adapters/git/patch.rb +++ b/lib/ohloh_scm/adapters/git/patch.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class GitAdapter < AbstractAdapter def patch_for_commit(commit) parent_tokens(commit).map {|token| diff --git a/lib/scm/adapters/git/pull.rb b/lib/ohloh_scm/adapters/git/pull.rb similarity index 99% rename from lib/scm/adapters/git/pull.rb rename to lib/ohloh_scm/adapters/git/pull.rb index e99ccbe0..c3bbd3be 100644 --- a/lib/scm/adapters/git/pull.rb +++ b/lib/ohloh_scm/adapters/git/pull.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class GitAdapter < AbstractAdapter def pull(from, &block) diff --git a/lib/scm/adapters/git/push.rb b/lib/ohloh_scm/adapters/git/push.rb similarity index 97% rename from lib/scm/adapters/git/push.rb rename to lib/ohloh_scm/adapters/git/push.rb index 11aa8918..bae4e69a 100644 --- a/lib/scm/adapters/git/push.rb +++ b/lib/ohloh_scm/adapters/git/push.rb @@ -1,6 +1,6 @@ require 'socket' -module Scm::Adapters +module OhlohScm::Adapters class GitAdapter < AbstractAdapter COMMITTER_NAME = 'ohloh_slave' unless defined?(COMMITTER_NAME) diff --git a/lib/scm/adapters/git/token.rb b/lib/ohloh_scm/adapters/git/token.rb similarity index 98% rename from lib/scm/adapters/git/token.rb rename to lib/ohloh_scm/adapters/git/token.rb index b102af9b..115a5f41 100644 --- a/lib/scm/adapters/git/token.rb +++ b/lib/ohloh_scm/adapters/git/token.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class GitAdapter < AbstractAdapter #--------------------------------------------------------------------------- diff --git a/lib/scm/adapters/git/validation.rb b/lib/ohloh_scm/adapters/git/validation.rb similarity index 98% rename from lib/scm/adapters/git/validation.rb rename to lib/ohloh_scm/adapters/git/validation.rb index 884277cb..e7d5d51d 100644 --- a/lib/scm/adapters/git/validation.rb +++ b/lib/ohloh_scm/adapters/git/validation.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class GitAdapter < AbstractAdapter def self.url_regex /^(http|https|rsync|git|ssh):\/\/(\w+@)?[A-Za-z0-9_\-\.]+(:\d+)?\/[A-Za-z0-9_@\-\.\/\~\+]*$/ diff --git a/lib/scm/adapters/git_adapter.rb b/lib/ohloh_scm/adapters/git_adapter.rb similarity index 93% rename from lib/scm/adapters/git_adapter.rb rename to lib/ohloh_scm/adapters/git_adapter.rb index 61ae04a3..1441f370 100644 --- a/lib/scm/adapters/git_adapter.rb +++ b/lib/ohloh_scm/adapters/git_adapter.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class GitAdapter < AbstractAdapter def english_name "Git" diff --git a/lib/scm/adapters/hg/cat_file.rb b/lib/ohloh_scm/adapters/hg/cat_file.rb similarity index 96% rename from lib/scm/adapters/hg/cat_file.rb rename to lib/ohloh_scm/adapters/hg/cat_file.rb index 74e6038f..e8caf7d6 100644 --- a/lib/scm/adapters/hg/cat_file.rb +++ b/lib/ohloh_scm/adapters/hg/cat_file.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class HgAdapter < AbstractAdapter def cat_file(commit, diff) cat(commit.token, diff.path) diff --git a/lib/scm/adapters/hg/commits.rb b/lib/ohloh_scm/adapters/hg/commits.rb similarity index 86% rename from lib/scm/adapters/hg/commits.rb rename to lib/ohloh_scm/adapters/hg/commits.rb index 6a073edd..ac3a9daa 100644 --- a/lib/scm/adapters/hg/commits.rb +++ b/lib/ohloh_scm/adapters/hg/commits.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class HgAdapter < AbstractAdapter # Return the number of commits in the repository following +after+. @@ -32,8 +32,8 @@ def commit_tokens(opts={}) def commits(opts={}) after = opts[:after] || 0 - log = run("cd '#{self.url}' && hg log -f #{trunk_only(opts)} -v -r tip:#{after} --style #{Scm::Parsers::HgStyledParser.style_path}") - a = Scm::Parsers::HgStyledParser.parse(log).reverse + log = run("cd '#{self.url}' && hg log -f #{trunk_only(opts)} -v -r tip:#{after} --style #{OhlohScm::Parsers::HgStyledParser.style_path}") + a = OhlohScm::Parsers::HgStyledParser.parse(log).reverse if a.any? && a.first.token == after a[1..-1] @@ -44,8 +44,8 @@ def commits(opts={}) # Returns a single commit, including its diffs def verbose_commit(token) - log = run("cd '#{self.url}' && hg log -v -r #{token} --style #{Scm::Parsers::HgStyledParser.verbose_style_path} | #{ string_encoder }") - Scm::Parsers::HgStyledParser.parse(log).first + log = run("cd '#{self.url}' && hg log -v -r #{token} --style #{OhlohScm::Parsers::HgStyledParser.verbose_style_path} | #{ string_encoder }") + OhlohScm::Parsers::HgStyledParser.parse(log).first end # Yields each commit after +after+, including its diffs. @@ -55,7 +55,7 @@ def verbose_commit(token) def each_commit(opts={}) after = opts[:after] || 0 open_log_file(opts) do |io| - Scm::Parsers::HgStyledParser.parse(io) do |commit| + OhlohScm::Parsers::HgStyledParser.parse(io) do |commit| yield commit if block_given? && commit.token != after end end @@ -78,7 +78,7 @@ def open_log_file(opts={}) # As a time optimization, just create an empty file rather than fetch a log we know will be empty. File.open(log_filename, 'w') { } else - run "cd '#{url}' && hg log --verbose #{trunk_only(opts)} -r #{after || 0}:tip --style #{Scm::Parsers::HgStyledParser.verbose_style_path} | #{ string_encoder } > #{log_filename}" + run "cd '#{url}' && hg log --verbose #{trunk_only(opts)} -r #{after || 0}:tip --style #{OhlohScm::Parsers::HgStyledParser.verbose_style_path} | #{ string_encoder } > #{log_filename}" end File.open(log_filename, 'r') { |io| yield io } ensure diff --git a/lib/scm/adapters/hg/head.rb b/lib/ohloh_scm/adapters/hg/head.rb similarity index 96% rename from lib/scm/adapters/hg/head.rb rename to lib/ohloh_scm/adapters/hg/head.rb index 9cdaf962..c65f767c 100644 --- a/lib/scm/adapters/hg/head.rb +++ b/lib/ohloh_scm/adapters/hg/head.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class HgAdapter < AbstractAdapter def head_token # This only returns first 12 characters. diff --git a/lib/scm/adapters/hg/misc.rb b/lib/ohloh_scm/adapters/hg/misc.rb similarity index 95% rename from lib/scm/adapters/hg/misc.rb rename to lib/ohloh_scm/adapters/hg/misc.rb index 6d395195..72624ea0 100644 --- a/lib/scm/adapters/hg/misc.rb +++ b/lib/ohloh_scm/adapters/hg/misc.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class HgAdapter < AbstractAdapter def exist? begin diff --git a/lib/scm/adapters/hg/patch.rb b/lib/ohloh_scm/adapters/hg/patch.rb similarity index 89% rename from lib/scm/adapters/hg/patch.rb rename to lib/ohloh_scm/adapters/hg/patch.rb index 1b9cff53..0ea390a7 100644 --- a/lib/scm/adapters/hg/patch.rb +++ b/lib/ohloh_scm/adapters/hg/patch.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class HgAdapter < AbstractAdapter def patch_for_commit(commit) parent_tokens(commit).map {|token| diff --git a/lib/scm/adapters/hg/pull.rb b/lib/ohloh_scm/adapters/hg/pull.rb similarity index 95% rename from lib/scm/adapters/hg/pull.rb rename to lib/ohloh_scm/adapters/hg/pull.rb index b24fa83c..c8a25f11 100644 --- a/lib/scm/adapters/hg/pull.rb +++ b/lib/ohloh_scm/adapters/hg/pull.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class HgAdapter < AbstractAdapter def pull(from, &block) diff --git a/lib/scm/adapters/hg/push.rb b/lib/ohloh_scm/adapters/hg/push.rb similarity index 97% rename from lib/scm/adapters/hg/push.rb rename to lib/ohloh_scm/adapters/hg/push.rb index 4c86fa4c..9805bc17 100644 --- a/lib/scm/adapters/hg/push.rb +++ b/lib/ohloh_scm/adapters/hg/push.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class HgAdapter < AbstractAdapter def push(to, &block) diff --git a/lib/scm/adapters/hg/validation.rb b/lib/ohloh_scm/adapters/hg/validation.rb similarity index 95% rename from lib/scm/adapters/hg/validation.rb rename to lib/ohloh_scm/adapters/hg/validation.rb index b549121b..d0747f98 100644 --- a/lib/scm/adapters/hg/validation.rb +++ b/lib/ohloh_scm/adapters/hg/validation.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class HgAdapter < AbstractAdapter def self.url_regex /^((http|https|ssh|file):\/\/((\w+@)?[A-Za-z0-9_\-\.]+(:\d+)?\/)?)?[A-Za-z0-9_@\-\.\/\~\+]*$/ diff --git a/lib/scm/adapters/hg_adapter.rb b/lib/ohloh_scm/adapters/hg_adapter.rb similarity index 92% rename from lib/scm/adapters/hg_adapter.rb rename to lib/ohloh_scm/adapters/hg_adapter.rb index 0629aa46..427668b1 100644 --- a/lib/scm/adapters/hg_adapter.rb +++ b/lib/ohloh_scm/adapters/hg_adapter.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class HgAdapter < AbstractAdapter def english_name "Mercurial" diff --git a/lib/scm/adapters/hglib/cat_file.rb b/lib/ohloh_scm/adapters/hglib/cat_file.rb similarity index 91% rename from lib/scm/adapters/hglib/cat_file.rb rename to lib/ohloh_scm/adapters/hglib/cat_file.rb index d22e2ae5..621e3946 100644 --- a/lib/scm/adapters/hglib/cat_file.rb +++ b/lib/ohloh_scm/adapters/hglib/cat_file.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class HglibAdapter < HgAdapter def cat_file(commit, diff) diff --git a/lib/scm/adapters/hglib/client.rb b/lib/ohloh_scm/adapters/hglib/client.rb similarity index 100% rename from lib/scm/adapters/hglib/client.rb rename to lib/ohloh_scm/adapters/hglib/client.rb diff --git a/lib/scm/adapters/hglib/head.rb b/lib/ohloh_scm/adapters/hglib/head.rb similarity index 83% rename from lib/scm/adapters/hglib/head.rb rename to lib/ohloh_scm/adapters/hglib/head.rb index 48ba2078..31b5366c 100644 --- a/lib/scm/adapters/hglib/head.rb +++ b/lib/ohloh_scm/adapters/hglib/head.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class HglibAdapter < HgAdapter def parent_tokens(commit) diff --git a/lib/scm/adapters/hglib/server.py b/lib/ohloh_scm/adapters/hglib/server.py similarity index 100% rename from lib/scm/adapters/hglib/server.py rename to lib/ohloh_scm/adapters/hglib/server.py diff --git a/lib/scm/adapters/hglib_adapter.rb b/lib/ohloh_scm/adapters/hglib_adapter.rb similarity index 93% rename from lib/scm/adapters/hglib_adapter.rb rename to lib/ohloh_scm/adapters/hglib_adapter.rb index cb5d8b0c..f0eb6ac6 100644 --- a/lib/scm/adapters/hglib_adapter.rb +++ b/lib/ohloh_scm/adapters/hglib_adapter.rb @@ -1,7 +1,7 @@ require 'rubygems' require_relative 'hglib/client' -module Scm::Adapters +module OhlohScm::Adapters class HglibAdapter < HgAdapter def setup diff --git a/lib/scm/adapters/svn/cat_file.rb b/lib/ohloh_scm/adapters/svn/cat_file.rb similarity index 95% rename from lib/scm/adapters/svn/cat_file.rb rename to lib/ohloh_scm/adapters/svn/cat_file.rb index 7563368a..3a15ecf6 100644 --- a/lib/scm/adapters/svn/cat_file.rb +++ b/lib/ohloh_scm/adapters/svn/cat_file.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class SvnAdapter < AbstractAdapter def cat_file(commit, diff) cat(diff.path, commit.token) diff --git a/lib/scm/adapters/svn/commits.rb b/lib/ohloh_scm/adapters/svn/commits.rb similarity index 98% rename from lib/scm/adapters/svn/commits.rb rename to lib/ohloh_scm/adapters/svn/commits.rb index d7220e98..64530cc6 100644 --- a/lib/scm/adapters/svn/commits.rb +++ b/lib/ohloh_scm/adapters/svn/commits.rb @@ -1,6 +1,6 @@ require 'rexml/document' -module Scm::Adapters +module OhlohScm::Adapters class SvnAdapter < AbstractAdapter # In all commit- and log-related methods, 'after' refers to the revision @@ -39,7 +39,7 @@ def commit_tokens(opts={}) def commits(opts={}) list = [] open_log_file(opts) do |io| - list = Scm::Parsers::SvnXmlParser.parse(io) + list = OhlohScm::Parsers::SvnXmlParser.parse(io) end list.each { |c| c.scm = self } end @@ -133,7 +133,7 @@ def strip_path_branch(path) end def verbose_commit(rev) - c = Scm::Parsers::SvnXmlParser.parse(single_revision_xml(rev)).first + c = OhlohScm::Parsers::SvnXmlParser.parse(single_revision_xml(rev)).first c.scm = self deepen_commit(strip_commit_branch(c)) end diff --git a/lib/scm/adapters/svn/head.rb b/lib/ohloh_scm/adapters/svn/head.rb similarity index 82% rename from lib/scm/adapters/svn/head.rb rename to lib/ohloh_scm/adapters/svn/head.rb index 698a81f2..131d1d6f 100644 --- a/lib/scm/adapters/svn/head.rb +++ b/lib/ohloh_scm/adapters/svn/head.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class SvnAdapter < AbstractAdapter def head_token self.info =~ /^Revision: (\d+)$/ ? $1.to_i : nil @@ -12,7 +12,7 @@ def parents(commit) # Subversion doesn't have an actual "parent" command, so get # a log for this commit and the one preceding it, and keep only the preceding. log = run "svn log --trust-server-cert --non-interactive --verbose --xml --stop-on-copy -r #{commit.token}:1 --limit 2 '#{SvnAdapter.uri_encode(self.url)}' #{opt_auth} | #{ string_encoder }" - [deepen_commit(strip_commit_branch(Scm::Parsers::SvnXmlParser.parse(log).last))] + [deepen_commit(strip_commit_branch(OhlohScm::Parsers::SvnXmlParser.parse(log).last))] end end end diff --git a/lib/scm/adapters/svn/misc.rb b/lib/ohloh_scm/adapters/svn/misc.rb similarity index 99% rename from lib/scm/adapters/svn/misc.rb rename to lib/ohloh_scm/adapters/svn/misc.rb index 89d45adf..ad8eebc1 100644 --- a/lib/scm/adapters/svn/misc.rb +++ b/lib/ohloh_scm/adapters/svn/misc.rb @@ -1,6 +1,6 @@ require 'open-uri' -module Scm::Adapters +module OhlohScm::Adapters class SvnAdapter < AbstractAdapter # Converts an URL of form file://local/path to simply /local/path. def path diff --git a/lib/scm/adapters/svn/patch.rb b/lib/ohloh_scm/adapters/svn/patch.rb similarity index 89% rename from lib/scm/adapters/svn/patch.rb rename to lib/ohloh_scm/adapters/svn/patch.rb index e9c46c8b..5bb982fc 100644 --- a/lib/scm/adapters/svn/patch.rb +++ b/lib/ohloh_scm/adapters/svn/patch.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class SvnAdapter < AbstractAdapter def patch_for_commit(commit) parent = commit.token.to_i - 1 diff --git a/lib/scm/adapters/svn/pre-revprop-change b/lib/ohloh_scm/adapters/svn/pre-revprop-change similarity index 100% rename from lib/scm/adapters/svn/pre-revprop-change rename to lib/ohloh_scm/adapters/svn/pre-revprop-change diff --git a/lib/scm/adapters/svn/pull.rb b/lib/ohloh_scm/adapters/svn/pull.rb similarity index 98% rename from lib/scm/adapters/svn/pull.rb rename to lib/ohloh_scm/adapters/svn/pull.rb index be6d9e3e..67b0ddf4 100644 --- a/lib/scm/adapters/svn/pull.rb +++ b/lib/ohloh_scm/adapters/svn/pull.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class SvnAdapter < AbstractAdapter def pull(from) diff --git a/lib/scm/adapters/svn/push.rb b/lib/ohloh_scm/adapters/svn/push.rb similarity index 89% rename from lib/scm/adapters/svn/push.rb rename to lib/ohloh_scm/adapters/svn/push.rb index 1a8f99e2..a338004e 100644 --- a/lib/scm/adapters/svn/push.rb +++ b/lib/ohloh_scm/adapters/svn/push.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class SvnAdapter < AbstractAdapter def push(to) diff --git a/lib/scm/adapters/svn/validation.rb b/lib/ohloh_scm/adapters/svn/validation.rb similarity index 99% rename from lib/scm/adapters/svn/validation.rb rename to lib/ohloh_scm/adapters/svn/validation.rb index 101a9d18..43d4a5ab 100644 --- a/lib/scm/adapters/svn/validation.rb +++ b/lib/ohloh_scm/adapters/svn/validation.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class SvnAdapter < AbstractAdapter def self.url_regex /^(file|http|https|svn):\/\/(\/)?[A-Za-z0-9_\-\.]+(:\d+)?(\/[A-Za-z0-9_@\-\.\/\+%^~ ]*)?$/ diff --git a/lib/scm/adapters/svn_adapter.rb b/lib/ohloh_scm/adapters/svn_adapter.rb similarity index 92% rename from lib/scm/adapters/svn_adapter.rb rename to lib/ohloh_scm/adapters/svn_adapter.rb index 92a9e908..f6a50729 100644 --- a/lib/scm/adapters/svn_adapter.rb +++ b/lib/ohloh_scm/adapters/svn_adapter.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class SvnAdapter < AbstractAdapter def english_name "Subversion" diff --git a/lib/scm/adapters/svn_chain/cat_file.rb b/lib/ohloh_scm/adapters/svn_chain/cat_file.rb similarity index 85% rename from lib/scm/adapters/svn_chain/cat_file.rb rename to lib/ohloh_scm/adapters/svn_chain/cat_file.rb index 26657f7b..d4632424 100644 --- a/lib/scm/adapters/svn_chain/cat_file.rb +++ b/lib/ohloh_scm/adapters/svn_chain/cat_file.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class SvnChainAdapter < SvnAdapter def cat(path, revision) parent_svn(revision) ? parent_svn.cat(path, revision) : super(path, revision) diff --git a/lib/scm/adapters/svn_chain/chain.rb b/lib/ohloh_scm/adapters/svn_chain/chain.rb similarity index 96% rename from lib/scm/adapters/svn_chain/chain.rb rename to lib/ohloh_scm/adapters/svn_chain/chain.rb index 80e12a91..8b4c7b2f 100644 --- a/lib/scm/adapters/svn_chain/chain.rb +++ b/lib/ohloh_scm/adapters/svn_chain/chain.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class SvnChainAdapter < SvnAdapter # Returns the entire SvnAdapter ancestry chain as a simple array. @@ -73,7 +73,7 @@ def first_token(after=0) def first_commit(after=0) @first_commit ||={} # Poor man's memoize - @first_commit[after] ||= Scm::Parsers::SvnXmlParser.parse(next_revision_xml(after)).first + @first_commit[after] ||= OhlohScm::Parsers::SvnXmlParser.parse(next_revision_xml(after)).first end # Returns the first commit with a revision number greater than the provided revision number diff --git a/lib/scm/adapters/svn_chain/commits.rb b/lib/ohloh_scm/adapters/svn_chain/commits.rb similarity index 98% rename from lib/scm/adapters/svn_chain/commits.rb rename to lib/ohloh_scm/adapters/svn_chain/commits.rb index f3ea371c..32f21c52 100644 --- a/lib/scm/adapters/svn_chain/commits.rb +++ b/lib/ohloh_scm/adapters/svn_chain/commits.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters class SvnChainAdapter < SvnAdapter # Returns the count of commits following revision number 'after'. diff --git a/lib/scm/adapters/svn_chain_adapter.rb b/lib/ohloh_scm/adapters/svn_chain_adapter.rb similarity index 98% rename from lib/scm/adapters/svn_chain_adapter.rb rename to lib/ohloh_scm/adapters/svn_chain_adapter.rb index 0f694d7a..c9c06bfb 100644 --- a/lib/scm/adapters/svn_chain_adapter.rb +++ b/lib/ohloh_scm/adapters/svn_chain_adapter.rb @@ -1,4 +1,4 @@ -module Scm::Adapters +module OhlohScm::Adapters # Some explanation is in order about "chaining." # # First, realize that a base SvnAdapter only tracks the history of a single diff --git a/lib/scm/commit.rb b/lib/ohloh_scm/commit.rb similarity index 100% rename from lib/scm/commit.rb rename to lib/ohloh_scm/commit.rb diff --git a/lib/scm/diff.rb b/lib/ohloh_scm/diff.rb similarity index 100% rename from lib/scm/diff.rb rename to lib/ohloh_scm/diff.rb diff --git a/lib/scm/parsers/array_writer.rb b/lib/ohloh_scm/parsers/array_writer.rb similarity index 90% rename from lib/scm/parsers/array_writer.rb rename to lib/ohloh_scm/parsers/array_writer.rb index 53716024..4d248999 100644 --- a/lib/scm/parsers/array_writer.rb +++ b/lib/ohloh_scm/parsers/array_writer.rb @@ -1,4 +1,4 @@ -module Scm::Parsers +module OhlohScm::Parsers class ArrayWriter attr_accessor :buffer diff --git a/lib/scm/parsers/branch_number.rb b/lib/ohloh_scm/parsers/branch_number.rb similarity index 98% rename from lib/scm/parsers/branch_number.rb rename to lib/ohloh_scm/parsers/branch_number.rb index 6b235c7e..234cbc47 100644 --- a/lib/scm/parsers/branch_number.rb +++ b/lib/ohloh_scm/parsers/branch_number.rb @@ -1,4 +1,4 @@ -module Scm::Parsers +module OhlohScm::Parsers class BranchNumber def initialize(s) @a = s.split('.').collect { |i| i.to_i } diff --git a/lib/scm/parsers/bzr_parser.rb b/lib/ohloh_scm/parsers/bzr_parser.rb similarity index 99% rename from lib/scm/parsers/bzr_parser.rb rename to lib/ohloh_scm/parsers/bzr_parser.rb index 4e924e1f..9a879e49 100644 --- a/lib/scm/parsers/bzr_parser.rb +++ b/lib/ohloh_scm/parsers/bzr_parser.rb @@ -1,4 +1,4 @@ -module Scm::Parsers +module OhlohScm::Parsers # This parser can process the default bzr logs, with or without the --verbose flag. class BzrParser < Parser def self.scm diff --git a/lib/scm/parsers/bzr_xml_parser.rb b/lib/ohloh_scm/parsers/bzr_xml_parser.rb similarity index 99% rename from lib/scm/parsers/bzr_xml_parser.rb rename to lib/ohloh_scm/parsers/bzr_xml_parser.rb index 902d3b9b..32a926c0 100644 --- a/lib/scm/parsers/bzr_xml_parser.rb +++ b/lib/ohloh_scm/parsers/bzr_xml_parser.rb @@ -1,7 +1,7 @@ require 'rexml/document' require 'rexml/streamlistener' -module Scm::Parsers +module OhlohScm::Parsers class BazaarListener include REXML::StreamListener attr_accessor :callback diff --git a/lib/scm/parsers/cvs_parser.rb b/lib/ohloh_scm/parsers/cvs_parser.rb similarity index 99% rename from lib/scm/parsers/cvs_parser.rb rename to lib/ohloh_scm/parsers/cvs_parser.rb index 17fd4274..a8d86b20 100644 --- a/lib/scm/parsers/cvs_parser.rb +++ b/lib/ohloh_scm/parsers/cvs_parser.rb @@ -1,4 +1,4 @@ -module Scm::Parsers +module OhlohScm::Parsers class CvsParser < Parser def self.scm diff --git a/lib/scm/parsers/git_parser.rb b/lib/ohloh_scm/parsers/git_parser.rb similarity index 98% rename from lib/scm/parsers/git_parser.rb rename to lib/ohloh_scm/parsers/git_parser.rb index 14269e91..9b2a8ee7 100644 --- a/lib/scm/parsers/git_parser.rb +++ b/lib/ohloh_scm/parsers/git_parser.rb @@ -1,4 +1,4 @@ -module Scm::Parsers +module OhlohScm::Parsers class GitParser < Parser def self.scm 'git' diff --git a/lib/scm/parsers/git_styled_parser.rb b/lib/ohloh_scm/parsers/git_styled_parser.rb similarity index 99% rename from lib/scm/parsers/git_styled_parser.rb rename to lib/ohloh_scm/parsers/git_styled_parser.rb index 51ee194c..fba110e0 100644 --- a/lib/scm/parsers/git_styled_parser.rb +++ b/lib/ohloh_scm/parsers/git_styled_parser.rb @@ -1,4 +1,4 @@ -module Scm::Parsers +module OhlohScm::Parsers # This parser processes Git whatchanged generated using a custom style. # This custom style provides additional information required by Ohloh. class GitStyledParser < Parser diff --git a/lib/scm/parsers/hg_parser.rb b/lib/ohloh_scm/parsers/hg_parser.rb similarity index 98% rename from lib/scm/parsers/hg_parser.rb rename to lib/ohloh_scm/parsers/hg_parser.rb index 6c006fac..ea753f28 100644 --- a/lib/scm/parsers/hg_parser.rb +++ b/lib/ohloh_scm/parsers/hg_parser.rb @@ -1,4 +1,4 @@ -module Scm::Parsers +module OhlohScm::Parsers # This parser can process the default hg logs, with or without the --verbose flag. # It is handy for debugging but is not detailed enough for Ohloh analysis. # See the HgStyledParser. diff --git a/lib/scm/parsers/hg_style b/lib/ohloh_scm/parsers/hg_style similarity index 100% rename from lib/scm/parsers/hg_style rename to lib/ohloh_scm/parsers/hg_style diff --git a/lib/scm/parsers/hg_styled_parser.rb b/lib/ohloh_scm/parsers/hg_styled_parser.rb similarity index 98% rename from lib/scm/parsers/hg_styled_parser.rb rename to lib/ohloh_scm/parsers/hg_styled_parser.rb index 40181218..811d8975 100644 --- a/lib/scm/parsers/hg_styled_parser.rb +++ b/lib/ohloh_scm/parsers/hg_styled_parser.rb @@ -1,4 +1,4 @@ -module Scm::Parsers +module OhlohScm::Parsers # This parser processes Mercurial logs which have been generated using a custom style. # This custom style provides additional information required by Ohloh. class HgStyledParser < Parser diff --git a/lib/scm/parsers/hg_verbose_style b/lib/ohloh_scm/parsers/hg_verbose_style similarity index 100% rename from lib/scm/parsers/hg_verbose_style rename to lib/ohloh_scm/parsers/hg_verbose_style diff --git a/lib/scm/parsers/human_writer.rb b/lib/ohloh_scm/parsers/human_writer.rb similarity index 98% rename from lib/scm/parsers/human_writer.rb rename to lib/ohloh_scm/parsers/human_writer.rb index 972c2515..67d4d702 100644 --- a/lib/scm/parsers/human_writer.rb +++ b/lib/ohloh_scm/parsers/human_writer.rb @@ -1,4 +1,4 @@ -module Scm::Parsers +module OhlohScm::Parsers class HumanWriter # Note that we use << instead of write() or puts() in this writer because # the << operator works on both File and String objects. diff --git a/lib/scm/parsers/parser.rb b/lib/ohloh_scm/parsers/parser.rb similarity index 95% rename from lib/scm/parsers/parser.rb rename to lib/ohloh_scm/parsers/parser.rb index a321db8c..233c51e6 100644 --- a/lib/scm/parsers/parser.rb +++ b/lib/ohloh_scm/parsers/parser.rb @@ -1,6 +1,6 @@ require 'stringio' -module Scm::Parsers +module OhlohScm::Parsers class Parser def self.parse(buffer='', opts={}) buffer = StringIO.new(buffer) if buffer.is_a? String diff --git a/lib/scm/parsers/svn_parser.rb b/lib/ohloh_scm/parsers/svn_parser.rb similarity index 98% rename from lib/scm/parsers/svn_parser.rb rename to lib/ohloh_scm/parsers/svn_parser.rb index c3541d50..5fc65b2b 100644 --- a/lib/scm/parsers/svn_parser.rb +++ b/lib/ohloh_scm/parsers/svn_parser.rb @@ -1,4 +1,4 @@ -module Scm::Parsers +module OhlohScm::Parsers class SvnParser < Parser def self.scm 'svn' diff --git a/lib/scm/parsers/svn_xml_parser.rb b/lib/ohloh_scm/parsers/svn_xml_parser.rb similarity index 98% rename from lib/scm/parsers/svn_xml_parser.rb rename to lib/ohloh_scm/parsers/svn_xml_parser.rb index d28a77e4..6eae2954 100644 --- a/lib/scm/parsers/svn_xml_parser.rb +++ b/lib/ohloh_scm/parsers/svn_xml_parser.rb @@ -1,7 +1,7 @@ require 'rexml/document' require 'rexml/streamlistener' -module Scm::Parsers +module OhlohScm::Parsers class SubversionListener include REXML::StreamListener diff --git a/lib/scm/parsers/xml_writer.rb b/lib/ohloh_scm/parsers/xml_writer.rb similarity index 98% rename from lib/scm/parsers/xml_writer.rb rename to lib/ohloh_scm/parsers/xml_writer.rb index 4442e0e6..ae20ba46 100644 --- a/lib/scm/parsers/xml_writer.rb +++ b/lib/ohloh_scm/parsers/xml_writer.rb @@ -1,4 +1,4 @@ -module Scm::Parsers +module OhlohScm::Parsers class XmlWriter # Note that we use << instead of write() or puts() in this writer because # the << operator works on both File and String objects. diff --git a/lib/scm/scratch_dir.rb b/lib/ohloh_scm/scratch_dir.rb similarity index 100% rename from lib/scm/scratch_dir.rb rename to lib/ohloh_scm/scratch_dir.rb diff --git a/lib/scm/shellout.rb b/lib/ohloh_scm/shellout.rb similarity index 100% rename from lib/scm/shellout.rb rename to lib/ohloh_scm/shellout.rb diff --git a/lib/scm/version.rb b/lib/ohloh_scm/version.rb similarity index 100% rename from lib/scm/version.rb rename to lib/ohloh_scm/version.rb diff --git a/lib/scm.rb b/lib/scm.rb deleted file mode 100644 index c5365a02..00000000 --- a/lib/scm.rb +++ /dev/null @@ -1,38 +0,0 @@ -module Scm -end - -#require 'rbconfig' - -#$: << File.join(File.dirname(__FILE__),"..") - -require_relative 'scm/shellout' -require_relative 'scm/scratch_dir' -require_relative 'scm/commit' -require_relative 'scm/diff' - -require_relative 'scm/adapters/abstract_adapter' -require_relative 'scm/adapters/cvs_adapter' -require_relative 'scm/adapters/svn_adapter' -require_relative 'scm/adapters/svn_chain_adapter' -require_relative 'scm/adapters/git_adapter' -require_relative 'scm/adapters/hg_adapter' -require_relative 'scm/adapters/hglib_adapter' -require_relative 'scm/adapters/bzr_adapter' -require_relative 'scm/adapters/bzrlib_adapter' -require_relative 'scm/adapters/factory' - -require_relative 'scm/parsers/parser' -require_relative 'scm/parsers/branch_number' -require_relative 'scm/parsers/cvs_parser' -require_relative 'scm/parsers/svn_parser' -require_relative 'scm/parsers/svn_xml_parser' -require_relative 'scm/parsers/git_parser' -require_relative 'scm/parsers/git_styled_parser' -require_relative 'scm/parsers/hg_parser' -require_relative 'scm/parsers/hg_styled_parser' -require_relative 'scm/parsers/bzr_xml_parser' -require_relative 'scm/parsers/bzr_parser' - -require_relative 'scm/parsers/array_writer' -require_relative 'scm/parsers/xml_writer' -require_relative 'scm/parsers/human_writer' diff --git a/ohloh_scm.gemspec b/ohloh_scm.gemspec index ce47e001..1e958b76 100644 --- a/ohloh_scm.gemspec +++ b/ohloh_scm.gemspec @@ -1,6 +1,6 @@ # -*- encoding: utf-8 -*- $:.push File.expand_path("../lib", __FILE__) -require 'scm/version' +require 'ohloh_scm/version' Gem::Specification.new do |gem| gem.name = 'ohloh_scm' @@ -8,11 +8,11 @@ Gem::Specification.new do |gem| gem.authors = ["BlackDuck Software"] gem.email = ["info@openhub.net"] gem.summary = %[Source Control Management] - gem.description = %[The Ohloh source control management library] + gem.description = %[The Ohloh source control management library for interacting with Git, SVN, CVS, Hg and Bzr repositories.] gem.homepage = %[https://github.com/blackducksw/ohloh_scm/] gem.license = %[GPL v2.0] - gem.files = `git ls-files -z`.split("\x0") + gem.files = `git ls-files`.split("\n") gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) } gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) gem.require_paths = %w(lib) diff --git a/test/test_helper.rb b/test/test_helper.rb index cf70e742..f8ddbba7 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -5,9 +5,9 @@ unless defined?(TEST_DIR) TEST_DIR = File.dirname(__FILE__) end -require_relative '../lib/scm' +require_relative '../lib/ohloh_scm' -Scm::Adapters::AbstractAdapter.logger = Logger.new(File.open('log/test.log','a')) +OhlohScm::Adapters::AbstractAdapter.logger = Logger.new(File.open('log/test.log','a')) unless defined?(REPO_DIR) REPO_DIR = File.expand_path(File.join(TEST_DIR, 'repositories')) @@ -25,7 +25,7 @@ def default_test def assert_convert(parser, log, expected) result = '' - parser.parse File.new(log), :writer => Scm::Parsers::XmlWriter.new(result) + parser.parse File.new(log), :writer => OhlohScm::Parsers::XmlWriter.new(result) assert_buffers_equal File.read(expected), result end @@ -65,7 +65,7 @@ def with_repository(type, name) # an xml log with invalid characters in it. # We prepend our custom svn's location to $PATH to make it available during our tests. def with_invalid_encoded_svn_repository - with_repository(Scm::Adapters::SvnChainAdapter, 'svn_with_invalid_encoding') do |svn| + with_repository(OhlohScm::Adapters::SvnChainAdapter, 'svn_with_invalid_encoding') do |svn| original_env_path = ENV['PATH'] custom_svn_path = File.expand_path('../bin/', __FILE__) ENV['PATH'] = custom_svn_path + ':' + ENV['PATH'] @@ -77,7 +77,7 @@ def with_invalid_encoded_svn_repository end def with_svn_repository(name, branch_name='') - with_repository(Scm::Adapters::SvnAdapter, name) do |svn| + with_repository(OhlohScm::Adapters::SvnAdapter, name) do |svn| svn.branch_name = branch_name svn.url = File.join(svn.root, svn.branch_name) svn.url = svn.url[0..-2] if svn.url[-1..-1] == '/' # Strip trailing / @@ -86,7 +86,7 @@ def with_svn_repository(name, branch_name='') end def with_svn_chain_repository(name, branch_name='') - with_repository(Scm::Adapters::SvnChainAdapter, name) do |svn| + with_repository(OhlohScm::Adapters::SvnChainAdapter, name) do |svn| svn.branch_name = branch_name svn.url = File.join(svn.root, svn.branch_name) svn.url = svn.url[0..-2] if svn.url[-1..-1] == '/' # Strip trailing / @@ -95,29 +95,29 @@ def with_svn_chain_repository(name, branch_name='') end def with_cvs_repository(name, module_name='') - with_repository(Scm::Adapters::CvsAdapter, name) do |cvs| + with_repository(OhlohScm::Adapters::CvsAdapter, name) do |cvs| cvs.module_name = module_name yield cvs end end def with_git_repository(name) - with_repository(Scm::Adapters::GitAdapter, name) { |git| yield git } + with_repository(OhlohScm::Adapters::GitAdapter, name) { |git| yield git } end def with_hg_repository(name) - with_repository(Scm::Adapters::HgAdapter, name) { |hg| yield hg } + with_repository(OhlohScm::Adapters::HgAdapter, name) { |hg| yield hg } end def with_hglib_repository(name) - with_repository(Scm::Adapters::HglibAdapter, name) { |hg| yield hg } + with_repository(OhlohScm::Adapters::HglibAdapter, name) { |hg| yield hg } end def with_bzr_repository(name) - with_repository(Scm::Adapters::BzrAdapter, name) { |bzr| yield bzr } + with_repository(OhlohScm::Adapters::BzrAdapter, name) { |bzr| yield bzr } end def with_bzrlib_repository(name) - with_repository(Scm::Adapters::BzrlibAdapter, name) { |bzr| yield bzr } + with_repository(OhlohScm::Adapters::BzrlibAdapter, name) { |bzr| yield bzr } end end diff --git a/test/unit/abstract_adapter_test.rb b/test/unit/abstract_adapter_test.rb index e5798277..4e5c5be7 100644 --- a/test/unit/abstract_adapter_test.rb +++ b/test/unit/abstract_adapter_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class AbstractAdapterTest < Scm::Test def test_simple_validation scm = AbstractAdapter.new() diff --git a/test/unit/adapter_factory_test.rb b/test/unit/adapter_factory_test.rb index d9934664..977d0557 100644 --- a/test/unit/adapter_factory_test.rb +++ b/test/unit/adapter_factory_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class FactoryTest < Scm::Test def test_factory_hg diff --git a/test/unit/array_writer_test.rb b/test/unit/array_writer_test.rb index 97c3c673..037843c2 100644 --- a/test/unit/array_writer_test.rb +++ b/test/unit/array_writer_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Parsers +module OhlohScm::Parsers class ArrayWriterTest < Scm::Test def test_basic diff --git a/test/unit/bzr_cat_file_test.rb b/test/unit/bzr_cat_file_test.rb index 83d5682d..58bd4169 100644 --- a/test/unit/bzr_cat_file_test.rb +++ b/test/unit/bzr_cat_file_test.rb @@ -1,7 +1,7 @@ # encoding: utf-8 require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class BzrCatFileTest < Scm::Test def test_cat_file diff --git a/test/unit/bzr_commits_test.rb b/test/unit/bzr_commits_test.rb index b08cb646..fa912a50 100644 --- a/test/unit/bzr_commits_test.rb +++ b/test/unit/bzr_commits_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class BzrCommitsTest < Scm::Test def test_commit_count diff --git a/test/unit/bzr_head_test.rb b/test/unit/bzr_head_test.rb index 525d47ac..c718b5d9 100644 --- a/test/unit/bzr_head_test.rb +++ b/test/unit/bzr_head_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class BzrHeadTest < Scm::Test def test_head_and_parents diff --git a/test/unit/bzr_misc_test.rb b/test/unit/bzr_misc_test.rb index d475b7fd..acd769aa 100644 --- a/test/unit/bzr_misc_test.rb +++ b/test/unit/bzr_misc_test.rb @@ -1,7 +1,7 @@ # encoding: utf-8 require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class BzrMiscTest < Scm::Test def test_exist diff --git a/test/unit/bzr_parser_test.rb b/test/unit/bzr_parser_test.rb index e208e999..b67d4c81 100644 --- a/test/unit/bzr_parser_test.rb +++ b/test/unit/bzr_parser_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Parsers +module OhlohScm::Parsers class BzrParserTest < Scm::Test def test_empty_array diff --git a/test/unit/bzr_pull_test.rb b/test/unit/bzr_pull_test.rb index 690bc72b..1d05f76d 100644 --- a/test/unit/bzr_pull_test.rb +++ b/test/unit/bzr_pull_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class BzrPullTest < Scm::Test def test_pull diff --git a/test/unit/bzr_push_test.rb b/test/unit/bzr_push_test.rb index 3d221fe5..ef162284 100644 --- a/test/unit/bzr_push_test.rb +++ b/test/unit/bzr_push_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class BzrPushTest < Scm::Test def test_hostname diff --git a/test/unit/bzr_validation_test.rb b/test/unit/bzr_validation_test.rb index 23e50376..10e488dc 100644 --- a/test/unit/bzr_validation_test.rb +++ b/test/unit/bzr_validation_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class BzrValidationTest < Scm::Test def test_rejected_urls [ nil, "", "foo", "http:/", "http:://", "http://", "http://a", diff --git a/test/unit/bzr_xml_parser_test.rb b/test/unit/bzr_xml_parser_test.rb index b78af68f..9a50e3fc 100644 --- a/test/unit/bzr_xml_parser_test.rb +++ b/test/unit/bzr_xml_parser_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Parsers +module OhlohScm::Parsers class BzrXmlParserTest < Scm::Test def test_empty_array diff --git a/test/unit/bzrlib_cat_file_test.rb b/test/unit/bzrlib_cat_file_test.rb index 400e6b7f..2d02329d 100644 --- a/test/unit/bzrlib_cat_file_test.rb +++ b/test/unit/bzrlib_cat_file_test.rb @@ -1,7 +1,7 @@ # encoding: utf-8 require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class BzrlibCatFileTest < Scm::Test def test_cat_file diff --git a/test/unit/bzrlib_head_test.rb b/test/unit/bzrlib_head_test.rb index f75946f9..a9831dc6 100644 --- a/test/unit/bzrlib_head_test.rb +++ b/test/unit/bzrlib_head_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class BzrBzrlibHeadTest < Scm::Test def test_head_and_parents diff --git a/test/unit/cvs_branch_number_test.rb b/test/unit/cvs_branch_number_test.rb index 8949ad2f..17cf3aea 100644 --- a/test/unit/cvs_branch_number_test.rb +++ b/test/unit/cvs_branch_number_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Parsers +module OhlohScm::Parsers class CvsBranchNumberTest < Scm::Test def test_basic assert_equal [1,1], BranchNumber.new('1.1').to_a diff --git a/test/unit/cvs_commits_test.rb b/test/unit/cvs_commits_test.rb index 498a6409..4a2e92f7 100644 --- a/test/unit/cvs_commits_test.rb +++ b/test/unit/cvs_commits_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class CvsCommitsTest < Scm::Test def test_commits diff --git a/test/unit/cvs_convert_test.rb b/test/unit/cvs_convert_test.rb index 860cd013..80550928 100644 --- a/test/unit/cvs_convert_test.rb +++ b/test/unit/cvs_convert_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class CvsConvertTest < Scm::Test def test_basic_convert diff --git a/test/unit/cvs_misc_test.rb b/test/unit/cvs_misc_test.rb index 7d3cbb65..fa6d2d03 100644 --- a/test/unit/cvs_misc_test.rb +++ b/test/unit/cvs_misc_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class CvsMiscTest < Scm::Test def test_local_directory_trim r = CvsAdapter.new(:url => "/Users/robin/cvs_repo/", :module_name => "simple") diff --git a/test/unit/cvs_parser_test.rb b/test/unit/cvs_parser_test.rb index c3a37053..33dc473b 100644 --- a/test/unit/cvs_parser_test.rb +++ b/test/unit/cvs_parser_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Parsers +module OhlohScm::Parsers class CvsParserTest < Scm::Test def test_basic diff --git a/test/unit/cvs_validation_test.rb b/test/unit/cvs_validation_test.rb index e393b41b..6d12c43f 100644 --- a/test/unit/cvs_validation_test.rb +++ b/test/unit/cvs_validation_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class CvsValidationTest < Scm::Test def test_rejected_urls [ nil, "", "foo", "http:/", "http:://", "http://", "http://a", diff --git a/test/unit/git_cat_file_test.rb b/test/unit/git_cat_file_test.rb index 10cbd4a4..7186af27 100644 --- a/test/unit/git_cat_file_test.rb +++ b/test/unit/git_cat_file_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class GitCatFileTest < Scm::Test def test_cat_file diff --git a/test/unit/git_commit_all_test.rb b/test/unit/git_commit_all_test.rb index 5b9b0ead..cf1e766c 100644 --- a/test/unit/git_commit_all_test.rb +++ b/test/unit/git_commit_all_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class GitCommitAllTest < Scm::Test def test_commit_all diff --git a/test/unit/git_commits_test.rb b/test/unit/git_commits_test.rb index 7a49d62f..96008088 100644 --- a/test/unit/git_commits_test.rb +++ b/test/unit/git_commits_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class GitCommitsTest < Scm::Test def test_commit_count diff --git a/test/unit/git_head_test.rb b/test/unit/git_head_test.rb index b6001237..93c5f44d 100644 --- a/test/unit/git_head_test.rb +++ b/test/unit/git_head_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class GitHeadTest < Scm::Test def test_head_and_parents diff --git a/test/unit/git_log_parser_test.rb b/test/unit/git_log_parser_test.rb index df2252c9..477e1724 100644 --- a/test/unit/git_log_parser_test.rb +++ b/test/unit/git_log_parser_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' require 'date' -module Scm::Parsers +module OhlohScm::Parsers class GitStyledParserTest < Scm::Test def test_basic diff --git a/test/unit/git_misc_test.rb b/test/unit/git_misc_test.rb index 983d8f4a..377949ab 100644 --- a/test/unit/git_misc_test.rb +++ b/test/unit/git_misc_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class GitMiscTest < Scm::Test def test_export diff --git a/test/unit/git_parser_test.rb b/test/unit/git_parser_test.rb index 962aae7d..d37d04dc 100644 --- a/test/unit/git_parser_test.rb +++ b/test/unit/git_parser_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Parsers +module OhlohScm::Parsers class GitParserTest < Scm::Test def test_empty_array diff --git a/test/unit/git_patch_test.rb b/test/unit/git_patch_test.rb index ddcb5e46..65d0283c 100644 --- a/test/unit/git_patch_test.rb +++ b/test/unit/git_patch_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class GitPatchTest < Scm::Test def test_patch_for_commit with_git_repository('git') do |repo| diff --git a/test/unit/git_pull_test.rb b/test/unit/git_pull_test.rb index 0534b605..780e7a1b 100644 --- a/test/unit/git_pull_test.rb +++ b/test/unit/git_pull_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class GitPullTest < Scm::Test def test_basic_pull diff --git a/test/unit/git_push_test.rb b/test/unit/git_push_test.rb index 52e6e8ae..45d58ee6 100644 --- a/test/unit/git_push_test.rb +++ b/test/unit/git_push_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class GitPushTest < Scm::Test def test_hostname diff --git a/test/unit/git_rev_list_test.rb b/test/unit/git_rev_list_test.rb index f9244f0e..8034026f 100644 --- a/test/unit/git_rev_list_test.rb +++ b/test/unit/git_rev_list_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters # Repository git_walk has the following structure: # # G -> H -> I -> J -> development diff --git a/test/unit/git_styled_parser_test.rb b/test/unit/git_styled_parser_test.rb index 12e91b70..5d630dc1 100644 --- a/test/unit/git_styled_parser_test.rb +++ b/test/unit/git_styled_parser_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Parsers +module OhlohScm::Parsers class GitStyledParserTest < Scm::Test def test_empty_array diff --git a/test/unit/git_token_test.rb b/test/unit/git_token_test.rb index 3cac89dc..6d5c41bf 100644 --- a/test/unit/git_token_test.rb +++ b/test/unit/git_token_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class GitTokenTest < Scm::Test def test_no_token_returns_nil diff --git a/test/unit/git_validation_test.rb b/test/unit/git_validation_test.rb index bf8b426f..8b526f4f 100644 --- a/test/unit/git_validation_test.rb +++ b/test/unit/git_validation_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class GitValidationTest < Scm::Test def test_rejected_urls [ nil, "", "foo", "http:/", "http:://", "http://", "http://a", diff --git a/test/unit/hg_cat_file_test.rb b/test/unit/hg_cat_file_test.rb index 013ca9de..c85d6e82 100644 --- a/test/unit/hg_cat_file_test.rb +++ b/test/unit/hg_cat_file_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class HgCatFileTest < Scm::Test def test_cat_file diff --git a/test/unit/hg_commits_test.rb b/test/unit/hg_commits_test.rb index 4fa67e3a..86fdc4b3 100644 --- a/test/unit/hg_commits_test.rb +++ b/test/unit/hg_commits_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class HgCommitsTest < Scm::Test def test_commit_count diff --git a/test/unit/hg_head_test.rb b/test/unit/hg_head_test.rb index f8a13586..cefccbd6 100644 --- a/test/unit/hg_head_test.rb +++ b/test/unit/hg_head_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class HgHeadTest < Scm::Test def test_head_and_parents diff --git a/test/unit/hg_misc_test.rb b/test/unit/hg_misc_test.rb index 52f90a2c..2916e403 100644 --- a/test/unit/hg_misc_test.rb +++ b/test/unit/hg_misc_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class HgMiscTest < Scm::Test def test_exist diff --git a/test/unit/hg_parser_test.rb b/test/unit/hg_parser_test.rb index 23408d7a..f7230ca9 100644 --- a/test/unit/hg_parser_test.rb +++ b/test/unit/hg_parser_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Parsers +module OhlohScm::Parsers class HgParserTest < Scm::Test def test_empty_array @@ -137,13 +137,13 @@ def test_log_parser_verbose def test_styled_parser with_hg_repository('hg') do |hg| assert FileTest.exist?(HgStyledParser.style_path) - log = hg.run("cd #{hg.url} && hg log --style #{Scm::Parsers::HgStyledParser.style_path}") - commits = Scm::Parsers::HgStyledParser.parse(log) + log = hg.run("cd #{hg.url} && hg log --style #{OhlohScm::Parsers::HgStyledParser.style_path}") + commits = OhlohScm::Parsers::HgStyledParser.parse(log) assert_styled_commits(commits, false) assert FileTest.exist?(HgStyledParser.verbose_style_path) - log = hg.run("cd #{hg.url} && hg log --style #{Scm::Parsers::HgStyledParser.verbose_style_path}") - commits = Scm::Parsers::HgStyledParser.parse(log) + log = hg.run("cd #{hg.url} && hg log --style #{OhlohScm::Parsers::HgStyledParser.verbose_style_path}") + commits = OhlohScm::Parsers::HgStyledParser.parse(log) assert_styled_commits(commits, true) end end diff --git a/test/unit/hg_patch_test.rb b/test/unit/hg_patch_test.rb index 655e9a90..95745390 100644 --- a/test/unit/hg_patch_test.rb +++ b/test/unit/hg_patch_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class HgPatchTest < Scm::Test def test_patch_for_commit with_hg_repository('hg') do |repo| diff --git a/test/unit/hg_pull_test.rb b/test/unit/hg_pull_test.rb index ee36b905..475d8ff1 100644 --- a/test/unit/hg_pull_test.rb +++ b/test/unit/hg_pull_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class HgPullTest < Scm::Test def test_pull diff --git a/test/unit/hg_push_test.rb b/test/unit/hg_push_test.rb index e987de3e..f2e898b5 100644 --- a/test/unit/hg_push_test.rb +++ b/test/unit/hg_push_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class HgPushTest < Scm::Test def test_hostname diff --git a/test/unit/hg_rev_list_test.rb b/test/unit/hg_rev_list_test.rb index d8c2ff6c..7d699131 100644 --- a/test/unit/hg_rev_list_test.rb +++ b/test/unit/hg_rev_list_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters # Repository hg_walk has the following structure: # # G -> H -> I diff --git a/test/unit/hg_validation_test.rb b/test/unit/hg_validation_test.rb index 4e6f77f0..ea257179 100644 --- a/test/unit/hg_validation_test.rb +++ b/test/unit/hg_validation_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class HgValidationTest < Scm::Test def test_rejected_urls [ nil, "", "foo", "http:/", "http:://", "http://", "http://a", diff --git a/test/unit/hglib_cat_file_test.rb b/test/unit/hglib_cat_file_test.rb index c65611d8..dcb194a5 100644 --- a/test/unit/hglib_cat_file_test.rb +++ b/test/unit/hglib_cat_file_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class HglibCatFileTest < Scm::Test def test_cat_file diff --git a/test/unit/hglib_head_test.rb b/test/unit/hglib_head_test.rb index 0491553f..e7c85541 100644 --- a/test/unit/hglib_head_test.rb +++ b/test/unit/hglib_head_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class HgHeadTest < Scm::Test def test_head_and_parents diff --git a/test/unit/ohlog_command_line_test.rb b/test/unit/ohlog_command_line_test.rb index 2c630d0a..48fa9402 100644 --- a/test/unit/ohlog_command_line_test.rb +++ b/test/unit/ohlog_command_line_test.rb @@ -1,4 +1,4 @@ -module Scm::Parsers +module OhlohScm::Parsers class CommandLineTest < Scm::Test def test_cvs_from_file result = `#{File.dirname(__FILE__) + '/../../bin/ohlog'} --xml --cvs #{DATA_DIR + '/basic.rlog'}` diff --git a/test/unit/string_encoder_command_line_test.rb b/test/unit/string_encoder_command_line_test.rb index ffe9befd..5db7538d 100644 --- a/test/unit/string_encoder_command_line_test.rb +++ b/test/unit/string_encoder_command_line_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Parsers +module OhlohScm::Parsers class StringEncoderCommandLineTest < Scm::Test def test_length_of_content_unchanged file_path = File.expand_path('../../data/sample-content', __FILE__) @@ -8,7 +8,7 @@ def test_length_of_content_unchanged original_content_lines = File.readlines(file_path).size output = %x[cat #{ file_path } \ - | #{ Scm::Adapters::AbstractAdapter.new.string_encoder } ] + | #{ OhlohScm::Adapters::AbstractAdapter.new.string_encoder } ] assert_equal original_content_length, output.length assert_equal original_content_lines, output.split("\n").length @@ -19,7 +19,7 @@ def test_encoding_invalid_characters File.expand_path('../../data/invalid-utf-word', __FILE__) string = %x[cat #{ invalid_utf8_word_path } \ - | #{ Scm::Adapters::AbstractAdapter.new.string_encoder } ] + | #{ OhlohScm::Adapters::AbstractAdapter.new.string_encoder } ] assert_equal true, string.valid_encoding? end diff --git a/test/unit/svn_cat_file_test.rb b/test/unit/svn_cat_file_test.rb index 7fd93be1..f65c0ee6 100644 --- a/test/unit/svn_cat_file_test.rb +++ b/test/unit/svn_cat_file_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class SvnCatFileTest < Scm::Test def test_cat_file diff --git a/test/unit/svn_chain_cat_file_test.rb b/test/unit/svn_chain_cat_file_test.rb index 33759c3c..08e6139c 100644 --- a/test/unit/svn_chain_cat_file_test.rb +++ b/test/unit/svn_chain_cat_file_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class SvnChainCatFileTest < Scm::Test def test_cat_file_with_chaining diff --git a/test/unit/svn_chain_commits_test.rb b/test/unit/svn_chain_commits_test.rb index 6e4f890f..52e9d0c7 100644 --- a/test/unit/svn_chain_commits_test.rb +++ b/test/unit/svn_chain_commits_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Parsers +module OhlohScm::Parsers class SvnChainTest < Scm::Test def test_chained_commit_tokens diff --git a/test/unit/svn_chain_test.rb b/test/unit/svn_chain_test.rb index 4aab7152..d646e73a 100644 --- a/test/unit/svn_chain_test.rb +++ b/test/unit/svn_chain_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Parsers +module OhlohScm::Parsers class SvnChainTest < Scm::Test def test_chain @@ -52,7 +52,7 @@ def test_parent_svn end def test_parent_branch_name - svn = Scm::Adapters::SvnChainAdapter.new(:branch_name => "/trunk") + svn = OhlohScm::Adapters::SvnChainAdapter.new(:branch_name => "/trunk") assert_equal "/branches/b", svn.parent_branch_name(Scm::Diff.new(:action => 'A', :path => "/trunk", :from_revision => 1, :from_path => "/branches/b")) diff --git a/test/unit/svn_commits_test.rb b/test/unit/svn_commits_test.rb index 33e7e6a3..2deb521d 100644 --- a/test/unit/svn_commits_test.rb +++ b/test/unit/svn_commits_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class SvnCommitsTest < Scm::Test def test_commits diff --git a/test/unit/svn_convert_test.rb b/test/unit/svn_convert_test.rb index 334991ce..08a3fca1 100644 --- a/test/unit/svn_convert_test.rb +++ b/test/unit/svn_convert_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class SvnConvertTest < Scm::Test def test_basic_convert with_svn_repository('svn') do |src| diff --git a/test/unit/svn_head_test.rb b/test/unit/svn_head_test.rb index b08920fa..30499ff3 100644 --- a/test/unit/svn_head_test.rb +++ b/test/unit/svn_head_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class SvnHeadTest < Scm::Test def test_head_and_parents diff --git a/test/unit/svn_misc_test.rb b/test/unit/svn_misc_test.rb index 13c5589d..3f3cece8 100644 --- a/test/unit/svn_misc_test.rb +++ b/test/unit/svn_misc_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class SvnMiscTest < Scm::Test def test_export diff --git a/test/unit/svn_parser_test.rb b/test/unit/svn_parser_test.rb index e91a7ff2..c50cafa6 100644 --- a/test/unit/svn_parser_test.rb +++ b/test/unit/svn_parser_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Parsers +module OhlohScm::Parsers class SvnParserTest < Scm::Test def test_basic diff --git a/test/unit/svn_patch_test.rb b/test/unit/svn_patch_test.rb index 21ffbd92..eda5b35e 100644 --- a/test/unit/svn_patch_test.rb +++ b/test/unit/svn_patch_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class SvnPatchTest < Scm::Test def test_patch_for_commit with_svn_repository('svn') do |repo| diff --git a/test/unit/svn_pull_test.rb b/test/unit/svn_pull_test.rb index 4ca959ab..7341f21d 100644 --- a/test/unit/svn_pull_test.rb +++ b/test/unit/svn_pull_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' require 'socket' -module Scm::Adapters +module OhlohScm::Adapters class SvnPullTest < Scm::Test def test_svnadmin_create diff --git a/test/unit/svn_push_test.rb b/test/unit/svn_push_test.rb index f431f4a2..fa59ec99 100644 --- a/test/unit/svn_push_test.rb +++ b/test/unit/svn_push_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' require 'socket' -module Scm::Adapters +module OhlohScm::Adapters class SvnPushTest < Scm::Test def test_basic_push_using_svnsync diff --git a/test/unit/svn_validation_test.rb b/test/unit/svn_validation_test.rb index 50602fe8..274b8cfe 100644 --- a/test/unit/svn_validation_test.rb +++ b/test/unit/svn_validation_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Adapters +module OhlohScm::Adapters class SvnValidationTest < Scm::Test def test_valid_usernames [nil,'','joe_36','a'*32,'robin@ohloh.net'].each do |username| diff --git a/test/unit/svn_xml_parser_test.rb b/test/unit/svn_xml_parser_test.rb index 39623cbe..a2bd9f58 100644 --- a/test/unit/svn_xml_parser_test.rb +++ b/test/unit/svn_xml_parser_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -module Scm::Parsers +module OhlohScm::Parsers class SvnXmlParserTest < Scm::Test def test_basic From 528b35b3e29318e1b9ef24f2d9107e2a6a04ddf6 Mon Sep 17 00:00:00 2001 From: Peter Degen-Portnoy Date: Wed, 15 Oct 2014 11:27:25 +0000 Subject: [PATCH 166/219] Update gemspec to build gem correctly --- ohloh_scm.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ohloh_scm.gemspec b/ohloh_scm.gemspec index 1e958b76..aaa3b7ba 100644 --- a/ohloh_scm.gemspec +++ b/ohloh_scm.gemspec @@ -12,7 +12,7 @@ Gem::Specification.new do |gem| gem.homepage = %[https://github.com/blackducksw/ohloh_scm/] gem.license = %[GPL v2.0] - gem.files = `git ls-files`.split("\n") + gem.files = `git ls-files -z`.split("\x0") gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) } gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) gem.require_paths = %w(lib) From b4043f8d63dd003fddf3f7d0f7623129d63f177a Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Thu, 16 Oct 2014 14:41:44 +0530 Subject: [PATCH 167/219] Rename Scm modules to OhlohScm --- lib/ohloh_scm/adapters/svn/commits.rb | 2 +- lib/ohloh_scm/commit.rb | 2 +- lib/ohloh_scm/diff.rb | 8 ++-- lib/ohloh_scm/parsers/bzr_parser.rb | 8 ++-- lib/ohloh_scm/parsers/bzr_xml_parser.rb | 26 ++++++------ lib/ohloh_scm/parsers/cvs_parser.rb | 2 +- lib/ohloh_scm/parsers/git_parser.rb | 4 +- lib/ohloh_scm/parsers/git_styled_parser.rb | 4 +- lib/ohloh_scm/parsers/hg_parser.rb | 4 +- lib/ohloh_scm/parsers/hg_styled_parser.rb | 4 +- lib/ohloh_scm/parsers/svn_parser.rb | 4 +- lib/ohloh_scm/parsers/svn_xml_parser.rb | 4 +- lib/ohloh_scm/scratch_dir.rb | 2 +- lib/ohloh_scm/version.rb | 2 +- ohloh_scm.gemspec | 2 +- test/test_helper.rb | 4 +- test/unit/abstract_adapter_test.rb | 8 ++-- test/unit/adapter_factory_test.rb | 14 +++---- test/unit/array_writer_test.rb | 2 +- test/unit/bzr_cat_file_test.rb | 24 +++++------ test/unit/bzr_commits_test.rb | 24 +++++------ test/unit/bzr_head_test.rb | 2 +- test/unit/bzr_misc_test.rb | 4 +- test/unit/bzr_parser_test.rb | 10 ++--- test/unit/bzr_pull_test.rb | 4 +- test/unit/bzr_push_test.rb | 4 +- test/unit/bzr_validation_test.rb | 6 +-- test/unit/bzr_xml_parser_test.rb | 40 +++++++++---------- test/unit/bzrlib_cat_file_test.rb | 20 +++++----- test/unit/bzrlib_head_test.rb | 2 +- test/unit/cvs_branch_number_test.rb | 2 +- test/unit/cvs_commits_test.rb | 2 +- test/unit/cvs_convert_test.rb | 4 +- test/unit/cvs_misc_test.rb | 2 +- test/unit/cvs_parser_test.rb | 2 +- test/unit/cvs_validation_test.rb | 2 +- test/unit/git_cat_file_test.rb | 4 +- test/unit/git_commit_all_test.rb | 6 +-- test/unit/git_commits_test.rb | 2 +- test/unit/git_head_test.rb | 2 +- test/unit/git_log_parser_test.rb | 4 +- test/unit/git_misc_test.rb | 8 ++-- test/unit/git_parser_test.rb | 2 +- test/unit/git_patch_test.rb | 2 +- test/unit/git_pull_test.rb | 4 +- test/unit/git_push_test.rb | 6 +-- test/unit/git_rev_list_test.rb | 2 +- test/unit/git_styled_parser_test.rb | 8 ++-- test/unit/git_token_test.rb | 12 +++--- test/unit/git_validation_test.rb | 2 +- test/unit/hg_cat_file_test.rb | 12 +++--- test/unit/hg_commits_test.rb | 2 +- test/unit/hg_head_test.rb | 2 +- test/unit/hg_misc_test.rb | 4 +- test/unit/hg_parser_test.rb | 2 +- test/unit/hg_patch_test.rb | 2 +- test/unit/hg_pull_test.rb | 4 +- test/unit/hg_push_test.rb | 4 +- test/unit/hg_rev_list_test.rb | 2 +- test/unit/hg_validation_test.rb | 2 +- test/unit/hglib_cat_file_test.rb | 12 +++--- test/unit/hglib_head_test.rb | 2 +- test/unit/ohlog_command_line_test.rb | 2 +- test/unit/shellout_test.rb | 2 +- test/unit/string_encoder_command_line_test.rb | 2 +- test/unit/svn_cat_file_test.rb | 6 +-- test/unit/svn_chain_cat_file_test.rb | 6 +-- test/unit/svn_chain_commits_test.rb | 2 +- test/unit/svn_chain_test.rb | 4 +- test/unit/svn_commits_test.rb | 30 +++++++------- test/unit/svn_convert_test.rb | 4 +- test/unit/svn_head_test.rb | 2 +- test/unit/svn_misc_test.rb | 4 +- test/unit/svn_parser_test.rb | 2 +- test/unit/svn_patch_test.rb | 2 +- test/unit/svn_pull_test.rb | 10 ++--- test/unit/svn_push_test.rb | 6 +-- test/unit/svn_validation_test.rb | 6 +-- test/unit/svn_xml_parser_test.rb | 4 +- 79 files changed, 234 insertions(+), 234 deletions(-) diff --git a/lib/ohloh_scm/adapters/svn/commits.rb b/lib/ohloh_scm/adapters/svn/commits.rb index 64530cc6..216497ad 100644 --- a/lib/ohloh_scm/adapters/svn/commits.rb +++ b/lib/ohloh_scm/adapters/svn/commits.rb @@ -96,7 +96,7 @@ def deepen_diff(diff, rev) if (diff.action == 'D' or diff.action == 'A') && is_directory?(diff.path, recurse_rev) # Deleting or adding a directory. Expand it out to show every file. recurse_files(diff.path, recurse_rev).collect do |f| - Scm::Diff.new(:action => diff.action, :path => File.join(diff.path, f)) + OhlohScm::Diff.new(:action => diff.action, :path => File.join(diff.path, f)) end else # An ordinary file action. Just return the diff. diff --git a/lib/ohloh_scm/commit.rb b/lib/ohloh_scm/commit.rb index ddb9fa13..2a8e12f0 100644 --- a/lib/ohloh_scm/commit.rb +++ b/lib/ohloh_scm/commit.rb @@ -1,4 +1,4 @@ -module Scm +module OhlohScm # A commit is a collection of diffs united by a single timestamp, author, and # message. # diff --git a/lib/ohloh_scm/diff.rb b/lib/ohloh_scm/diff.rb index 1263cb96..83169185 100644 --- a/lib/ohloh_scm/diff.rb +++ b/lib/ohloh_scm/diff.rb @@ -1,10 +1,10 @@ -module Scm +module OhlohScm # A +Diff+ represents a change to a single file. It can represent the addition or # deletion of a file, or it can represent a modification of the file contents. - # + # # Ohloh does not track filename changes. If a file is renamed, Ohloh treats this # as the deletion of one file and the creation of another. - # + # # Ohloh does not track directories, only the files within directories. # # Don't confuse our use of the word "Diff" with a patch file or the output of the @@ -22,7 +22,7 @@ class Diff # 'M' modified # 'D' deleted attr_accessor :action - + # The SHA1 hash of the file contents both before and after the change. # These must be computed using the same method as Git. attr_accessor :parent_sha1, :sha1 diff --git a/lib/ohloh_scm/parsers/bzr_parser.rb b/lib/ohloh_scm/parsers/bzr_parser.rb index 9a879e49..acc79bba 100644 --- a/lib/ohloh_scm/parsers/bzr_parser.rb +++ b/lib/ohloh_scm/parsers/bzr_parser.rb @@ -30,7 +30,7 @@ def self.internal_parse(buffer, opts) e.diffs = remove_dupes(e.diffs) yield e end - e = Scm::Commit.new + e = OhlohScm::Commit.new e.diffs = [] next_state = :data when /^#{indent}revno:\s+(\d+)$/ @@ -98,10 +98,10 @@ def self.parse_diffs(action, line) # Note that is possible to be renamed to the empty string! # This happens when a subdirectory is moved to become the root. before, after = line.scan(/(.+) => ?(.*)/).first - [ Scm::Diff.new(:action => 'D', :path => before), - Scm::Diff.new(:action => 'A', :path => after || '' )] + [ OhlohScm::Diff.new(:action => 'D', :path => before), + OhlohScm::Diff.new(:action => 'A', :path => after || '' )] else - [Scm::Diff.new(:action => action, :path => line)] + [OhlohScm::Diff.new(:action => action, :path => line)] end.each do |d| d.path = strip_trailing_asterisk(d.path) end diff --git a/lib/ohloh_scm/parsers/bzr_xml_parser.rb b/lib/ohloh_scm/parsers/bzr_xml_parser.rb index 32a926c0..325e25e4 100644 --- a/lib/ohloh_scm/parsers/bzr_xml_parser.rb +++ b/lib/ohloh_scm/parsers/bzr_xml_parser.rb @@ -18,7 +18,7 @@ def initialize(callback) def tag_start(name, attrs) case name when 'log' - @commit = Scm::Commit.new + @commit = OhlohScm::Commit.new @commit.diffs = [] when 'affected-files' @diffs = [] @@ -87,18 +87,18 @@ def parse_diff(action, path, before_path) case action # A rename action requires two diffs: one to remove the old filename, # another to add the new filename. - # + # # Note that is possible to be renamed to the empty string! # This happens when a subdirectory is moved to become the root. when 'renamed' - diffs = [ Scm::Diff.new(:action => 'D', :path => before_path), - Scm::Diff.new(:action => 'A', :path => path || '')] + diffs = [ OhlohScm::Diff.new(:action => 'D', :path => before_path), + OhlohScm::Diff.new(:action => 'A', :path => path || '')] when 'added' - diffs = [Scm::Diff.new(:action => 'A', :path => path)] + diffs = [OhlohScm::Diff.new(:action => 'A', :path => path)] when 'modified' - diffs = [Scm::Diff.new(:action => 'M', :path => path)] + diffs = [OhlohScm::Diff.new(:action => 'M', :path => path)] when 'removed' - diffs = [Scm::Diff.new(:action => 'D', :path => path)] + diffs = [OhlohScm::Diff.new(:action => 'D', :path => path)] end diffs.each do |d| d.path = strip_trailing_asterisk(d.path) @@ -108,11 +108,11 @@ def parse_diff(action, path, before_path) def strip_trailing_asterisk(path) path[-1..-1] == '*' ? path[0..-2] : path - end + end def remove_dupes(diffs) BzrXmlParser.remove_dupes(diffs) - end + end end @@ -133,14 +133,14 @@ def self.scm def self.remove_dupes(diffs) # Bazaar may report that a file was added and modified in a single commit. # Reduce these cases to a single 'A' action. - diffs.delete_if do |d| + diffs.delete_if do |d| d.action == 'M' && diffs.select { |x| x.path == d.path && x.action == 'A' }.any? - end + end # Bazaar may report that a file was both deleted and added in a single commit. # Reduce these cases to a single 'M' action. - diffs.each do |d| - d.action = 'M' if diffs.select { |x| x.path == d.path }.size > 1 + diffs.each do |d| + d.action = 'M' if diffs.select { |x| x.path == d.path }.size > 1 end.uniq end diff --git a/lib/ohloh_scm/parsers/cvs_parser.rb b/lib/ohloh_scm/parsers/cvs_parser.rb index a8d86b20..99a49816 100644 --- a/lib/ohloh_scm/parsers/cvs_parser.rb +++ b/lib/ohloh_scm/parsers/cvs_parser.rb @@ -139,7 +139,7 @@ def self.read_commit(io, filename, commit_number, should_yield) should_yield = false if commit_number == '1.1' and state == 'dead' message = read_message(io) if should_yield - commit = Scm::Commit.new + commit = OhlohScm::Commit.new commit.token = committer_date[0..18] commit.committer_date = Time.parse(committer_date[0..18] + ' +0000').utc commit.committer_name = committer_name diff --git a/lib/ohloh_scm/parsers/git_parser.rb b/lib/ohloh_scm/parsers/git_parser.rb index 9b2a8ee7..8a48a46d 100644 --- a/lib/ohloh_scm/parsers/git_parser.rb +++ b/lib/ohloh_scm/parsers/git_parser.rb @@ -27,7 +27,7 @@ def self.internal_parse(io, opts) when /^commit ([a-z0-9]{40,40})$/ sha1 = $1 yield e if e - e = Scm::Commit.new + e = OhlohScm::Commit.new e.diffs = [] e.token = sha1 e.author_name = ANONYMOUS @@ -53,7 +53,7 @@ def self.internal_parse(io, opts) elsif state == :diffs if line =~ /^([ADM])\t(.+)$/ - e.diffs << Scm::Diff.new( :action => $1, :path => $2) + e.diffs << OhlohScm::Diff.new( :action => $1, :path => $2) end else diff --git a/lib/ohloh_scm/parsers/git_styled_parser.rb b/lib/ohloh_scm/parsers/git_styled_parser.rb index fba110e0..beec97ba 100644 --- a/lib/ohloh_scm/parsers/git_styled_parser.rb +++ b/lib/ohloh_scm/parsers/git_styled_parser.rb @@ -35,7 +35,7 @@ def self.internal_parse(io, opts) if line =~ /^Commit: ([a-z0-9]+)$/ sha1 = $1 yield e if e - e = Scm::Commit.new + e = OhlohScm::Commit.new e.diffs = [] e.token = sha1 e.author_name = ANONYMOUS @@ -70,7 +70,7 @@ def self.internal_parse(io, opts) elsif line =~ /:([0-9]+) ([0-9]+) ([a-z0-9]+) ([a-z0-9]+) ([A-Z])\t"?(.+[^"])"?$/ # Submodules have a file mode of '160000', which indicates a "gitlink" # We ignore submodules completely. - e.diffs << Scm::Diff.new( :action => $5, :path => $6, :sha1 => $4, :parent_sha1 => $3 ) unless $1=='160000' || $2=='160000' + e.diffs << OhlohScm::Diff.new( :action => $5, :path => $6, :sha1 => $4, :parent_sha1 => $3 ) unless $1=='160000' || $2=='160000' end else diff --git a/lib/ohloh_scm/parsers/hg_parser.rb b/lib/ohloh_scm/parsers/hg_parser.rb index ea753f28..48cf9cee 100644 --- a/lib/ohloh_scm/parsers/hg_parser.rb +++ b/lib/ohloh_scm/parsers/hg_parser.rb @@ -17,7 +17,7 @@ def self.internal_parse(buffer, opts) case l when /^changeset:\s+\d+:([0-9a-f]+)/ yield e if e && block_given? - e = Scm::Commit.new + e = OhlohScm::Commit.new e.diffs = [] e.token = $1 when /^user:\s+(.+?)(\s+<(.+)>)?$/ @@ -27,7 +27,7 @@ def self.internal_parse(buffer, opts) e.committer_date = Time.parse($1).utc when /^files:\s+(.+)/ ($1 || '').split(' ').each do |file| - e.diffs << Scm::Diff.new(:action => '?', :path => file) + e.diffs << OhlohScm::Diff.new(:action => '?', :path => file) end when /^summary:\s+(.+)/ e.message = $1 diff --git a/lib/ohloh_scm/parsers/hg_styled_parser.rb b/lib/ohloh_scm/parsers/hg_styled_parser.rb index 811d8975..2dc6e753 100644 --- a/lib/ohloh_scm/parsers/hg_styled_parser.rb +++ b/lib/ohloh_scm/parsers/hg_styled_parser.rb @@ -25,7 +25,7 @@ def self.internal_parse(buffer, opts) if state == :data case l when /^changeset:\s+([0-9a-f]+)/ - e = Scm::Commit.new + e = OhlohScm::Commit.new e.diffs = [] e.token = $1 when /^user:\s+(.+?)(\s+<(.+)>)?$/ @@ -46,7 +46,7 @@ def self.internal_parse(buffer, opts) if l == "__END_FILES__\n" next_state = :data elsif l =~ /^([MAD]) (.+)$/ - e.diffs << Scm::Diff.new(:action => $1, :path => $2) + e.diffs << OhlohScm::Diff.new(:action => $1, :path => $2) end elsif state == :long_comment diff --git a/lib/ohloh_scm/parsers/svn_parser.rb b/lib/ohloh_scm/parsers/svn_parser.rb index 5fc65b2b..7977649f 100644 --- a/lib/ohloh_scm/parsers/svn_parser.rb +++ b/lib/ohloh_scm/parsers/svn_parser.rb @@ -13,7 +13,7 @@ def self.internal_parse(buffer, opts) next_state = state if state == :data if l =~ /^r(\d+) \| (.*) \| (\d+-\d+-\d+ .*) \(.*\) \| .*/ - e = Scm::Commit.new + e = OhlohScm::Commit.new e.token = $1.to_i e.committer_name = $2 e.committer_date = Time.parse($3).utc @@ -26,7 +26,7 @@ def self.internal_parse(buffer, opts) elsif state == :diffs if l =~ /^ (\w) ([^\(\)]+)( \(from (.+):(\d+)\))?$/ e.diffs ||= [] - e.diffs << Scm::Diff.new(:action => $1, :path => $2, :from_path => $4, :from_revision => $5.to_i) + e.diffs << OhlohScm::Diff.new(:action => $1, :path => $2, :from_path => $4, :from_revision => $5.to_i) else next_state = :comment end diff --git a/lib/ohloh_scm/parsers/svn_xml_parser.rb b/lib/ohloh_scm/parsers/svn_xml_parser.rb index 6eae2954..bfac5854 100644 --- a/lib/ohloh_scm/parsers/svn_xml_parser.rb +++ b/lib/ohloh_scm/parsers/svn_xml_parser.rb @@ -15,11 +15,11 @@ def initialize(callback) def tag_start(name, attrs) case name when 'logentry' - @commit = Scm::Commit.new + @commit = OhlohScm::Commit.new @commit.diffs = [] @commit.token = attrs['revision'].to_i when 'path' - @diff = Scm::Diff.new(:action => attrs['action'], + @diff = OhlohScm::Diff.new(:action => attrs['action'], :from_path => attrs['copyfrom-path'], :from_revision => attrs['copyfrom-rev'].to_i) end diff --git a/lib/ohloh_scm/scratch_dir.rb b/lib/ohloh_scm/scratch_dir.rb index 4eaa06a5..b68c4fb4 100644 --- a/lib/ohloh_scm/scratch_dir.rb +++ b/lib/ohloh_scm/scratch_dir.rb @@ -1,7 +1,7 @@ require 'fileutils' # A utility class to manage the creation and automatic cleanup of temporary directories. -module Scm +module OhlohScm class ScratchDir attr_reader :path diff --git a/lib/ohloh_scm/version.rb b/lib/ohloh_scm/version.rb index 2868efe2..3e692ad5 100644 --- a/lib/ohloh_scm/version.rb +++ b/lib/ohloh_scm/version.rb @@ -1,4 +1,4 @@ -module Scm +module OhlohScm module Version STRING = '2.0.0' end diff --git a/ohloh_scm.gemspec b/ohloh_scm.gemspec index aaa3b7ba..0de6e165 100644 --- a/ohloh_scm.gemspec +++ b/ohloh_scm.gemspec @@ -4,7 +4,7 @@ require 'ohloh_scm/version' Gem::Specification.new do |gem| gem.name = 'ohloh_scm' - gem.version = Scm::Version::STRING + gem.version = OhlohScm::Version::STRING gem.authors = ["BlackDuck Software"] gem.email = ["info@openhub.net"] gem.summary = %[Source Control Management] diff --git a/test/test_helper.rb b/test/test_helper.rb index f8ddbba7..cfd4d926 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -17,7 +17,7 @@ DATA_DIR = File.expand_path(File.join(TEST_DIR, 'data')) end -class Scm::Test < Test::Unit::TestCase +class OhlohScm::Test < Test::Unit::TestCase # For reasons unknown, the base class defines a default_test method to throw a failure. # We override it with a no-op to prevent this 'helpful' feature. def default_test @@ -48,7 +48,7 @@ def assert_buffers_equal(expected, actual) end def with_repository(type, name) - Scm::ScratchDir.new do |dir| + OhlohScm::ScratchDir.new do |dir| if Dir.entries(REPO_DIR).include?(name) `cp -R #{File.join(REPO_DIR, name)} #{dir}` elsif Dir.entries(REPO_DIR).include?(name + '.tgz') diff --git a/test/unit/abstract_adapter_test.rb b/test/unit/abstract_adapter_test.rb index 4e5c5be7..762ad3a3 100644 --- a/test/unit/abstract_adapter_test.rb +++ b/test/unit/abstract_adapter_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class AbstractAdapterTest < Scm::Test + class AbstractAdapterTest < OhlohScm::Test def test_simple_validation scm = AbstractAdapter.new() assert !scm.valid? @@ -74,7 +74,7 @@ def test_shellout stdout = AbstractAdapter.run(cmd) assert_equal "Hello World\n", stdout end - + def test_shellout_with_stderr cmd = %q( ruby -e" t = 'Hello World'; STDOUT.puts t; STDERR.puts t " ) stdout, stderr, status = AbstractAdapter.run_with_err(cmd) @@ -82,7 +82,7 @@ def test_shellout_with_stderr assert_equal "Hello World\n", stdout assert_equal "Hello World\n", stderr end - + def test_shellout_large_output cat = 'ruby -e" puts Array.new(65536){ 42 } "' stdout = AbstractAdapter.run(cat) @@ -91,7 +91,7 @@ def test_shellout_large_output def test_shellout_error cmd = "false" - assert_raise RuntimeError do + assert_raise RuntimeError do stdout = AbstractAdapter.run(cmd) end end diff --git a/test/unit/adapter_factory_test.rb b/test/unit/adapter_factory_test.rb index 977d0557..a298ff5f 100644 --- a/test/unit/adapter_factory_test.rb +++ b/test/unit/adapter_factory_test.rb @@ -1,10 +1,10 @@ require_relative '../test_helper' module OhlohScm::Adapters - class FactoryTest < Scm::Test + class FactoryTest < OhlohScm::Test def test_factory_hg - Scm::ScratchDir.new do |path| + OhlohScm::ScratchDir.new do |path| `cd #{path} && hg init` hg = Factory.from_path(path) assert hg.is_a?(HgAdapter) @@ -13,7 +13,7 @@ def test_factory_hg end def test_factory_bzr - Scm::ScratchDir.new do |path| + OhlohScm::ScratchDir.new do |path| `cd #{path} && bzr init` bzr = Factory.from_path(path) assert bzr.is_a?(BzrAdapter) @@ -22,7 +22,7 @@ def test_factory_bzr end def test_factory_git - Scm::ScratchDir.new do |path| + OhlohScm::ScratchDir.new do |path| `cd #{path} && git init` git = Factory.from_path(path) assert git.is_a?(GitAdapter) @@ -31,7 +31,7 @@ def test_factory_git end def test_factory_svn - Scm::ScratchDir.new do |path| + OhlohScm::ScratchDir.new do |path| `cd #{path} && svnadmin create foo` svn = Factory.from_path(File.join(path, 'foo')) assert svn.is_a?(SvnAdapter) @@ -40,7 +40,7 @@ def test_factory_svn end def test_factory_svn_checkout - Scm::ScratchDir.new do |path| + OhlohScm::ScratchDir.new do |path| `cd #{path} && svnadmin create foo` `cd #{path} && svn co file://#{File.expand_path(File.join(path, 'foo'))} bar` svn = Factory.from_path(File.join(path, 'bar')) @@ -53,7 +53,7 @@ def test_factory_svn_checkout def test_factory_from_cvs_checkout with_cvs_repository('cvs', 'simple') do |cvs| - Scm::ScratchDir.new do |path| + OhlohScm::ScratchDir.new do |path| `cd #{path} && cvsnt -d #{File.expand_path(cvs.url)} co simple 2> /dev/null` factory_response = Factory.from_path(File.join(path, 'simple')) assert factory_response.is_a?(CvsAdapter) diff --git a/test/unit/array_writer_test.rb b/test/unit/array_writer_test.rb index 037843c2..86a3d32b 100644 --- a/test/unit/array_writer_test.rb +++ b/test/unit/array_writer_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Parsers - class ArrayWriterTest < Scm::Test + class ArrayWriterTest < OhlohScm::Test def test_basic diff --git a/test/unit/bzr_cat_file_test.rb b/test/unit/bzr_cat_file_test.rb index 58bd4169..f7b08d88 100644 --- a/test/unit/bzr_cat_file_test.rb +++ b/test/unit/bzr_cat_file_test.rb @@ -2,7 +2,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class BzrCatFileTest < Scm::Test + class BzrCatFileTest < OhlohScm::Test def test_cat_file with_bzr_repository('bzr') do |bzr| @@ -11,12 +11,12 @@ def test_cat_file second line EXPECTED assert_equal expected, - bzr.cat_file(Scm::Commit::new(:token => 6), - Scm::Diff.new(:path => "file1.txt")) + bzr.cat_file(OhlohScm::Commit::new(:token => 6), + OhlohScm::Diff.new(:path => "file1.txt")) # file2.txt has been removed in commit #5 assert_equal nil, bzr.cat_file(bzr.head, - Scm::Diff.new(:path => "file2.txt")) + OhlohScm::Diff.new(:path => "file2.txt")) end end @@ -27,10 +27,10 @@ def test_cat_file_non_ascii_name second line EXPECTED assert_equal expected, - bzr.cat_file(Scm::Commit::new(:token => 7), - Scm::Diff.new(:path => "Cédric.txt")) - end - end + bzr.cat_file(OhlohScm::Commit::new(:token => 7), + OhlohScm::Diff.new(:path => "Cédric.txt")) + end + end def test_cat_file_parent with_bzr_repository('bzr') do |bzr| @@ -39,16 +39,16 @@ def test_cat_file_parent second line EXPECTED assert_equal expected, - bzr.cat_file_parent(Scm::Commit::new(:token => 6), - Scm::Diff.new(:path => "file1.txt")) + bzr.cat_file_parent(OhlohScm::Commit::new(:token => 6), + OhlohScm::Diff.new(:path => "file1.txt")) # file2.txt has been removed in commit #5 expected = <<-EXPECTED another file EXPECTED assert_equal expected, - bzr.cat_file_parent(Scm::Commit.new(:token => 5), - Scm::Diff.new(:path => "file2.txt")) + bzr.cat_file_parent(OhlohScm::Commit.new(:token => 5), + OhlohScm::Diff.new(:path => "file2.txt")) end end diff --git a/test/unit/bzr_commits_test.rb b/test/unit/bzr_commits_test.rb index fa912a50..755ebcd8 100644 --- a/test/unit/bzr_commits_test.rb +++ b/test/unit/bzr_commits_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class BzrCommitsTest < Scm::Test + class BzrCommitsTest < OhlohScm::Test def test_commit_count with_bzr_repository('bzr') do |bzr| @@ -63,7 +63,7 @@ def test_commit_tokens_trunk_only_false assert_equal [ 'test@example.com-20090206214301-s93cethy9atcqu9h', 'test@example.com-20090206214451-lzjngefdyw3vmgms', - 'test@example.com-20090206214350-rqhdpz92l11eoq2t', # branch commit + 'test@example.com-20090206214350-rqhdpz92l11eoq2t', # branch commit 'test@example.com-20090206214515-21lkfj3dbocao5pr' # merge commit ], bzr.commit_tokens(:trunk_only => false) end @@ -95,8 +95,8 @@ def test_nested_branches_commit_tokens_trunk_only_false 'test@example.com-20110803170648-o0xcbni7lwp97azj', 'test@example.com-20110803170818-v44umypquqg8migo' ], bzr.commit_tokens(:trunk_only => false) - end - end + end + end def test_nested_branches_commit_tokens_trunk_only_true with_bzr_repository('bzr_with_nested_branches') do |bzr| @@ -109,15 +109,15 @@ def test_nested_branches_commit_tokens_trunk_only_true 'obnox@samba.org-20090204004942-73rnw0izen42f154', 'test@example.com-20110803170818-v44umypquqg8migo' ], bzr.commit_tokens(:trunk_only => true) - end - end + end + end def test_commits_trunk_only_false with_bzr_repository('bzr_with_branch') do |bzr| assert_equal [ 'test@example.com-20090206214301-s93cethy9atcqu9h', 'test@example.com-20090206214451-lzjngefdyw3vmgms', - 'test@example.com-20090206214350-rqhdpz92l11eoq2t', # branch commit + 'test@example.com-20090206214350-rqhdpz92l11eoq2t', # branch commit 'test@example.com-20090206214515-21lkfj3dbocao5pr' # merge commit ], bzr.commits(:trunk_only => false).map { |c| c.token } end @@ -163,8 +163,8 @@ def test_nested_branches_commits_trunk_only_false 'test@example.com-20110803170648-o0xcbni7lwp97azj', 'test@example.com-20110803170818-v44umypquqg8migo' ], bzr.commits(:trunk_only => false).map { |c| c.token } - end - end + end + end def test_nested_branches_commits_trunk_only_true with_bzr_repository('bzr_with_nested_branches') do |bzr| @@ -177,8 +177,8 @@ def test_nested_branches_commits_trunk_only_true 'obnox@samba.org-20090204004942-73rnw0izen42f154', 'test@example.com-20110803170818-v44umypquqg8migo' ], bzr.commits(:trunk_only => true).map { |c| c.token } - end - end + end + end def test_commits with_bzr_repository('bzr') do |bzr| @@ -345,7 +345,7 @@ def test_committer_and_author_name assert_equal 'Abhay Mujumdar', commits[0].committer_name assert_equal nil, commits[0].author_name assert_equal nil, commits[0].author_email - + assert_equal 'Updated.', commits[1].message assert_equal 'Abhay Mujumdar', commits[1].committer_name assert_equal 'John Doe', commits[1].author_name diff --git a/test/unit/bzr_head_test.rb b/test/unit/bzr_head_test.rb index c718b5d9..47e7a809 100644 --- a/test/unit/bzr_head_test.rb +++ b/test/unit/bzr_head_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class BzrHeadTest < Scm::Test + class BzrHeadTest < OhlohScm::Test def test_head_and_parents with_bzr_repository('bzr') do |bzr| diff --git a/test/unit/bzr_misc_test.rb b/test/unit/bzr_misc_test.rb index acd769aa..ec2fcf6a 100644 --- a/test/unit/bzr_misc_test.rb +++ b/test/unit/bzr_misc_test.rb @@ -2,7 +2,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class BzrMiscTest < Scm::Test + class BzrMiscTest < OhlohScm::Test def test_exist save_bzr = nil @@ -26,7 +26,7 @@ def test_ls_tree def test_export with_bzr_repository('bzr') do |bzr| - Scm::ScratchDir.new do |dir| + OhlohScm::ScratchDir.new do |dir| bzr.export(dir) assert_equal ['.', '..', 'Cédric.txt', 'file1.txt', 'file3.txt', 'file4.txt', 'file5.txt'], Dir.entries(dir).sort end diff --git a/test/unit/bzr_parser_test.rb b/test/unit/bzr_parser_test.rb index b67d4c81..c52ea2df 100644 --- a/test/unit/bzr_parser_test.rb +++ b/test/unit/bzr_parser_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Parsers - class BzrParserTest < Scm::Test + class BzrParserTest < OhlohScm::Test def test_empty_array assert_equal([], BzrParser.parse('')) @@ -305,8 +305,8 @@ def test_rename end def test_remove_dupes_add_remove - diffs = BzrParser.remove_dupes([ Scm::Diff.new(:action => "A", :path => "foo"), - Scm::Diff.new(:action => "D", :path => "foo") ]) + diffs = BzrParser.remove_dupes([ OhlohScm::Diff.new(:action => "A", :path => "foo"), + OhlohScm::Diff.new(:action => "D", :path => "foo") ]) assert_equal 1, diffs.size assert_equal 'M', diffs.first.action assert_equal 'foo', diffs.first.path @@ -378,9 +378,9 @@ def test_comment_that_contains_dashes This is a tricky commit message to confirm fix to Ticket 5. We're including a line of dashes in the message that resembles a log delimiter. - + ------------------------------------------------------------ - + Happy parsing! added: goodbyeworld.c diff --git a/test/unit/bzr_pull_test.rb b/test/unit/bzr_pull_test.rb index 1d05f76d..4f0bbd0c 100644 --- a/test/unit/bzr_pull_test.rb +++ b/test/unit/bzr_pull_test.rb @@ -1,11 +1,11 @@ require_relative '../test_helper' module OhlohScm::Adapters - class BzrPullTest < Scm::Test + class BzrPullTest < OhlohScm::Test def test_pull with_bzr_repository('bzr') do |src| - Scm::ScratchDir.new do |dest_dir| + OhlohScm::ScratchDir.new do |dest_dir| dest = BzrAdapter.new(:url => dest_dir).normalize assert !dest.exist? diff --git a/test/unit/bzr_push_test.rb b/test/unit/bzr_push_test.rb index ef162284..1b1df3d5 100644 --- a/test/unit/bzr_push_test.rb +++ b/test/unit/bzr_push_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class BzrPushTest < Scm::Test + class BzrPushTest < OhlohScm::Test def test_hostname assert !BzrAdapter.new.hostname @@ -36,7 +36,7 @@ def test_bzr_path def test_push with_bzr_repository('bzr') do |src| - Scm::ScratchDir.new do |dest_dir| + OhlohScm::ScratchDir.new do |dest_dir| dest = BzrAdapter.new(:url => dest_dir).normalize assert !dest.exist? diff --git a/test/unit/bzr_validation_test.rb b/test/unit/bzr_validation_test.rb index 10e488dc..c4f2d201 100644 --- a/test/unit/bzr_validation_test.rb +++ b/test/unit/bzr_validation_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class BzrValidationTest < Scm::Test + class BzrValidationTest < OhlohScm::Test def test_rejected_urls [ nil, "", "foo", "http:/", "http:://", "http://", "http://a", "www.selenic.com/repo/hello", # missing a protool prefix @@ -21,8 +21,8 @@ def test_accepted_urls "http://www.selenic.com:80/repo/hello", "https://www.selenic.com/repo/hello", "bzr://www.selenic.com/repo/hello", - "lp:foobar", - "lp:~foobar/bar", + "lp:foobar", + "lp:~foobar/bar", ].each do |url| bzr = BzrAdapter.new(:url => url, :public_urls_only => true) assert !bzr.validate_url diff --git a/test/unit/bzr_xml_parser_test.rb b/test/unit/bzr_xml_parser_test.rb index 9a50e3fc..04049cd8 100644 --- a/test/unit/bzr_xml_parser_test.rb +++ b/test/unit/bzr_xml_parser_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Parsers - class BzrXmlParserTest < Scm::Test + class BzrXmlParserTest < OhlohScm::Test def test_empty_array assert_equal([], BzrXmlParser.parse('')) @@ -10,7 +10,7 @@ def test_empty_array def test_empty_xml assert_equal("\n\n\n", BzrXmlParser.parse('', :writer => XmlWriter.new)) end - + def test_basic_xml xml = <<-XML @@ -31,7 +31,7 @@ def test_basic_xml commits = BzrXmlParser.parse(xml) assert_equal 1, commits.size c = commits.first - assert_equal 0, c.diffs.size + assert_equal 0, c.diffs.size assert_equal "Renamed test1.txt to subdir/test_b.txt, removed test2.txt and added test_a.txt.", c.message assert_equal "test@example.com-20110725174345-brbpkwumeh07aoh8", c.token end @@ -71,7 +71,7 @@ def test_verbose_xml assert_equal "test2.txt", c.diffs[0].path assert_equal "D", c.diffs[0].action - + assert_equal "test_a.txt", c.diffs[1].path assert_equal "A", c.diffs[1].action @@ -83,9 +83,9 @@ def test_verbose_xml end # When an directory is deleted, bzr outputs one delete entry - # per file and one for the directory. For empty dirs, there - # is only one directory remove entry. - # Ohloh keeps file delete entries but ignores directory + # per file and one for the directory. For empty dirs, there + # is only one directory remove entry. + # Ohloh keeps file delete entries but ignores directory # delete entry. def test_ignore_dir_delete_xml xml = <<-XML @@ -114,7 +114,7 @@ def test_ignore_dir_delete_xml XML commits = BzrXmlParser.parse(xml) assert_equal 1, commits.size - + c = commits.first assert_equal 1, c.diffs.size assert_equal "uspace/lib/net/include/nil_interface.h", c.diffs.first.path @@ -243,12 +243,12 @@ def test_different_author_and_committer assert_equal "test", c.committer_name assert_equal "test@example.com", c.committer_email assert_equal nil, c.author_name - assert_equal nil, c.author_email + assert_equal nil, c.author_email end def test_rename xml = <<-XML - + 10 test@example.com-20110725174345-brbpkwumeh07aoh8 @@ -265,7 +265,7 @@ def test_rename - + XML commits = BzrXmlParser.parse(xml) assert_equal 1, commits.size @@ -278,21 +278,21 @@ def test_rename end def test_remove_dupes_add_remove - diffs = BzrXmlParser.remove_dupes([ Scm::Diff.new(:action => "A", :path => "foo"), - Scm::Diff.new(:action => "D", :path => "foo") ]) + diffs = BzrXmlParser.remove_dupes([ OhlohScm::Diff.new(:action => "A", :path => "foo"), + OhlohScm::Diff.new(:action => "D", :path => "foo") ]) assert_equal 1, diffs.size assert_equal 'M', diffs.first.action assert_equal 'foo', diffs.first.path - end + end - # A complex delete/rename/modify test. - # Removed test_a.txt, Renamed test3.txt to test_a.txt, edited test_a.txt - # + # A complex delete/rename/modify test. + # Removed test_a.txt, Renamed test3.txt to test_a.txt, edited test_a.txt + # # This is what Ohloh expects to see: - # - # D test3.txt + # + # D test3.txt # M test_a.txt - # + # def test_complex_rename xml = <<-XML diff --git a/test/unit/bzrlib_cat_file_test.rb b/test/unit/bzrlib_cat_file_test.rb index 2d02329d..3579606b 100644 --- a/test/unit/bzrlib_cat_file_test.rb +++ b/test/unit/bzrlib_cat_file_test.rb @@ -2,7 +2,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class BzrlibCatFileTest < Scm::Test + class BzrlibCatFileTest < OhlohScm::Test def test_cat_file with_bzrlib_repository('bzr') do |bzr| @@ -11,12 +11,12 @@ def test_cat_file second line EXPECTED assert_equal expected, - bzr.cat_file(Scm::Commit::new(:token => 6), - Scm::Diff.new(:path => "file1.txt")) + bzr.cat_file(OhlohScm::Commit::new(:token => 6), + OhlohScm::Diff.new(:path => "file1.txt")) # file2.txt has been removed in commit #5 assert_equal nil, bzr.cat_file(bzr.head, - Scm::Diff.new(:path => "file2.txt")) + OhlohScm::Diff.new(:path => "file2.txt")) end end @@ -27,8 +27,8 @@ def test_cat_file_non_ascii_name second line EXPECTED assert_equal expected, - bzr.cat_file(Scm::Commit::new(:token => 7), - Scm::Diff.new(:path => "Cédric.txt")) + bzr.cat_file(OhlohScm::Commit::new(:token => 7), + OhlohScm::Diff.new(:path => "Cédric.txt")) end end @@ -39,16 +39,16 @@ def test_cat_file_parent second line EXPECTED assert_equal expected, - bzr.cat_file_parent(Scm::Commit::new(:token => 6), - Scm::Diff.new(:path => "file1.txt")) + bzr.cat_file_parent(OhlohScm::Commit::new(:token => 6), + OhlohScm::Diff.new(:path => "file1.txt")) # file2.txt has been removed in commit #5 expected = <<-EXPECTED another file EXPECTED assert_equal expected, - bzr.cat_file_parent(Scm::Commit.new(:token => 5), - Scm::Diff.new(:path => "file2.txt")) + bzr.cat_file_parent(OhlohScm::Commit.new(:token => 5), + OhlohScm::Diff.new(:path => "file2.txt")) end end diff --git a/test/unit/bzrlib_head_test.rb b/test/unit/bzrlib_head_test.rb index a9831dc6..12e4268d 100644 --- a/test/unit/bzrlib_head_test.rb +++ b/test/unit/bzrlib_head_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class BzrBzrlibHeadTest < Scm::Test + class BzrBzrlibHeadTest < OhlohScm::Test def test_head_and_parents with_bzrlib_repository('bzr') do |bzr| diff --git a/test/unit/cvs_branch_number_test.rb b/test/unit/cvs_branch_number_test.rb index 17cf3aea..4b5df6ee 100644 --- a/test/unit/cvs_branch_number_test.rb +++ b/test/unit/cvs_branch_number_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Parsers - class CvsBranchNumberTest < Scm::Test + class CvsBranchNumberTest < OhlohScm::Test def test_basic assert_equal [1,1], BranchNumber.new('1.1').to_a assert_equal [1234,1234], BranchNumber.new('1234.1234').to_a diff --git a/test/unit/cvs_commits_test.rb b/test/unit/cvs_commits_test.rb index 4a2e92f7..b2013804 100644 --- a/test/unit/cvs_commits_test.rb +++ b/test/unit/cvs_commits_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class CvsCommitsTest < Scm::Test + class CvsCommitsTest < OhlohScm::Test def test_commits with_cvs_repository('cvs', 'simple') do |cvs| diff --git a/test/unit/cvs_convert_test.rb b/test/unit/cvs_convert_test.rb index 80550928..4f8550b1 100644 --- a/test/unit/cvs_convert_test.rb +++ b/test/unit/cvs_convert_test.rb @@ -1,11 +1,11 @@ require_relative '../test_helper' module OhlohScm::Adapters - class CvsConvertTest < Scm::Test + class CvsConvertTest < OhlohScm::Test def test_basic_convert with_cvs_repository('cvs', 'simple') do |src| - Scm::ScratchDir.new do |dest_dir| + OhlohScm::ScratchDir.new do |dest_dir| dest = GitAdapter.new(:url => dest_dir).normalize assert !dest.exist? diff --git a/test/unit/cvs_misc_test.rb b/test/unit/cvs_misc_test.rb index fa6d2d03..a2d202ec 100644 --- a/test/unit/cvs_misc_test.rb +++ b/test/unit/cvs_misc_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class CvsMiscTest < Scm::Test + class CvsMiscTest < OhlohScm::Test def test_local_directory_trim r = CvsAdapter.new(:url => "/Users/robin/cvs_repo/", :module_name => "simple") assert_equal "/Users/robin/cvs_repo/simple/foo.rb", r.trim_directory('/Users/robin/cvs_repo/simple/foo.rb') diff --git a/test/unit/cvs_parser_test.rb b/test/unit/cvs_parser_test.rb index 33dc473b..2af1c97d 100644 --- a/test/unit/cvs_parser_test.rb +++ b/test/unit/cvs_parser_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Parsers - class CvsParserTest < Scm::Test + class CvsParserTest < OhlohScm::Test def test_basic assert_convert(CvsParser, DATA_DIR + '/basic.rlog', DATA_DIR + '/basic.ohlog') diff --git a/test/unit/cvs_validation_test.rb b/test/unit/cvs_validation_test.rb index 6d12c43f..1f04a63b 100644 --- a/test/unit/cvs_validation_test.rb +++ b/test/unit/cvs_validation_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class CvsValidationTest < Scm::Test + class CvsValidationTest < OhlohScm::Test def test_rejected_urls [ nil, "", "foo", "http:/", "http:://", "http://", "http://a", ":pserver", # that's not enough diff --git a/test/unit/git_cat_file_test.rb b/test/unit/git_cat_file_test.rb index 7186af27..900c8561 100644 --- a/test/unit/git_cat_file_test.rb +++ b/test/unit/git_cat_file_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class GitCatFileTest < Scm::Test + class GitCatFileTest < OhlohScm::Test def test_cat_file with_git_repository('git') do |git| @@ -13,7 +13,7 @@ def test_cat_file printf("Hello, World!\\n"); } EXPECTED - assert_equal expected, git.cat_file(nil, Scm::Diff.new(:sha1 => '4c734ad53b272c9b3d719f214372ac497ff6c068')) + assert_equal expected, git.cat_file(nil, OhlohScm::Diff.new(:sha1 => '4c734ad53b272c9b3d719f214372ac497ff6c068')) end end diff --git a/test/unit/git_commit_all_test.rb b/test/unit/git_commit_all_test.rb index cf1e766c..e9944eee 100644 --- a/test/unit/git_commit_all_test.rb +++ b/test/unit/git_commit_all_test.rb @@ -1,10 +1,10 @@ require_relative '../test_helper' module OhlohScm::Adapters - class GitCommitAllTest < Scm::Test + class GitCommitAllTest < OhlohScm::Test def test_commit_all - Scm::ScratchDir.new do |dir| + OhlohScm::ScratchDir.new do |dir| git = GitAdapter.new(:url => dir).normalize git.init_db @@ -13,7 +13,7 @@ def test_commit_all File.open(File.join(dir, 'README'), 'w') {} assert git.anything_to_commit? - c = Scm::Commit.new + c = OhlohScm::Commit.new c.author_name = "John Q. Developer" c.message = "Initial checkin." git.commit_all(c) diff --git a/test/unit/git_commits_test.rb b/test/unit/git_commits_test.rb index 96008088..e12f0e22 100644 --- a/test/unit/git_commits_test.rb +++ b/test/unit/git_commits_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class GitCommitsTest < Scm::Test + class GitCommitsTest < OhlohScm::Test def test_commit_count with_git_repository('git') do |git| diff --git a/test/unit/git_head_test.rb b/test/unit/git_head_test.rb index 93c5f44d..e193bd99 100644 --- a/test/unit/git_head_test.rb +++ b/test/unit/git_head_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class GitHeadTest < Scm::Test + class GitHeadTest < OhlohScm::Test def test_head_and_parents with_git_repository('git') do |git| diff --git a/test/unit/git_log_parser_test.rb b/test/unit/git_log_parser_test.rb index 477e1724..f1f3554b 100644 --- a/test/unit/git_log_parser_test.rb +++ b/test/unit/git_log_parser_test.rb @@ -2,7 +2,7 @@ require 'date' module OhlohScm::Parsers - class GitStyledParserTest < Scm::Test + class GitStyledParserTest < OhlohScm::Test def test_basic commits = [] @@ -187,7 +187,7 @@ def test_use_email_when_names_are_missing __BEGIN_COMMIT__ Commit: fa3ee9d4cefc2db81adadf36da9cacbe92ce96f1 -Author: +Author: AuthorEmail: mickeyl@openembedded.org Date: Wed, 11 Jun 2008 00:37:06 +0000 __BEGIN_COMMENT__ diff --git a/test/unit/git_misc_test.rb b/test/unit/git_misc_test.rb index 377949ab..9b74de35 100644 --- a/test/unit/git_misc_test.rb +++ b/test/unit/git_misc_test.rb @@ -1,11 +1,11 @@ require_relative '../test_helper' module OhlohScm::Adapters - class GitMiscTest < Scm::Test + class GitMiscTest < OhlohScm::Test def test_export with_git_repository('git') do |git| - Scm::ScratchDir.new do |dir| + OhlohScm::ScratchDir.new do |dir| git.export(dir) assert_equal ['.','..','.gitignore','COPYING','README','helloworld.c','makefile','ohloh_token'], Dir.entries(dir).sort end @@ -27,8 +27,8 @@ def test_ls_tree def test_is_merge_commit with_git_repository('git_walk') do |git| - assert git.is_merge_commit?(Scm::Commit.new(:token => 'f264fb40c340a415b305ac1f0b8f12502aa2788f')) - assert !git.is_merge_commit?(Scm::Commit.new(:token => 'd067161caae2eeedbd74976aeff5c4d8f1ccc946')) + assert git.is_merge_commit?(OhlohScm::Commit.new(:token => 'f264fb40c340a415b305ac1f0b8f12502aa2788f')) + assert !git.is_merge_commit?(OhlohScm::Commit.new(:token => 'd067161caae2eeedbd74976aeff5c4d8f1ccc946')) end end diff --git a/test/unit/git_parser_test.rb b/test/unit/git_parser_test.rb index d37d04dc..5e029c69 100644 --- a/test/unit/git_parser_test.rb +++ b/test/unit/git_parser_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Parsers - class GitParserTest < Scm::Test + class GitParserTest < OhlohScm::Test def test_empty_array assert_equal([], GitParser.parse('')) diff --git a/test/unit/git_patch_test.rb b/test/unit/git_patch_test.rb index 65d0283c..bdcda499 100644 --- a/test/unit/git_patch_test.rb +++ b/test/unit/git_patch_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class GitPatchTest < Scm::Test + class GitPatchTest < OhlohScm::Test def test_patch_for_commit with_git_repository('git') do |repo| commit = repo.verbose_commit('b6e9220c3cabe53a4ed7f32952aeaeb8a822603d') diff --git a/test/unit/git_pull_test.rb b/test/unit/git_pull_test.rb index 780e7a1b..21d0bfea 100644 --- a/test/unit/git_pull_test.rb +++ b/test/unit/git_pull_test.rb @@ -1,11 +1,11 @@ require_relative '../test_helper' module OhlohScm::Adapters - class GitPullTest < Scm::Test + class GitPullTest < OhlohScm::Test def test_basic_pull with_git_repository('git') do |src| - Scm::ScratchDir.new do |dest_dir| + OhlohScm::ScratchDir.new do |dest_dir| dest = GitAdapter.new(:url => dest_dir).normalize assert !dest.exist? diff --git a/test/unit/git_push_test.rb b/test/unit/git_push_test.rb index 45d58ee6..973992c3 100644 --- a/test/unit/git_push_test.rb +++ b/test/unit/git_push_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class GitPushTest < Scm::Test + class GitPushTest < OhlohScm::Test def test_hostname assert_equal "foo", GitAdapter.new(:url => 'foo:/bar').hostname @@ -23,7 +23,7 @@ def test_local def test_basic_push with_git_repository('git') do |src| - Scm::ScratchDir.new do |dest_dir| + OhlohScm::ScratchDir.new do |dest_dir| dest = GitAdapter.new(:url => dest_dir).normalize assert !dest.exist? @@ -34,7 +34,7 @@ def test_basic_push # Now push again. This tests a different code path! File.open(File.join(src.url, 'foo'), 'w') { } - src.commit_all(Scm::Commit.new) + src.commit_all(OhlohScm::Commit.new) src.push(dest) assert dest.exist? diff --git a/test/unit/git_rev_list_test.rb b/test/unit/git_rev_list_test.rb index 8034026f..e4c6ed77 100644 --- a/test/unit/git_rev_list_test.rb +++ b/test/unit/git_rev_list_test.rb @@ -7,7 +7,7 @@ module OhlohScm::Adapters # / \ \ # A -> B -> C -> D -> master # - class GitRevListTest < Scm::Test + class GitRevListTest < OhlohScm::Test def test_rev_list with_git_repository('git_walk') do |git| diff --git a/test/unit/git_styled_parser_test.rb b/test/unit/git_styled_parser_test.rb index 5d630dc1..afe9fdc6 100644 --- a/test/unit/git_styled_parser_test.rb +++ b/test/unit/git_styled_parser_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Parsers - class GitStyledParserTest < Scm::Test + class GitStyledParserTest < OhlohScm::Test def test_empty_array assert_equal([], GitStyledParser.parse('')) @@ -13,13 +13,13 @@ def test_log_parser_nil_date Commit: 1df547800dcd168e589bb9b26b4039bff3a7f7e4 Author: Jason Allen AuthorEmail: jason@ohloh.net -Date: +Date: __BEGIN_COMMENT__ moving COPYING __END_COMMENT__ SAMPLE - + commits = GitStyledParser.parse(sample_log) assert_equal 1, commits.size assert_equal Time.utc(1970,1,1,0,0,0), commits[0].author_date @@ -37,7 +37,7 @@ def test_log_parser_bogus_date __END_COMMENT__ SAMPLE - + commits = GitStyledParser.parse(sample_log) assert_equal 1, commits.size assert_equal Time.utc(1970,1,1,0,0,0), commits[0].author_date diff --git a/test/unit/git_token_test.rb b/test/unit/git_token_test.rb index 6d5c41bf..5161a4cc 100644 --- a/test/unit/git_token_test.rb +++ b/test/unit/git_token_test.rb @@ -1,10 +1,10 @@ require_relative '../test_helper' module OhlohScm::Adapters - class GitTokenTest < Scm::Test + class GitTokenTest < OhlohScm::Test def test_no_token_returns_nil - Scm::ScratchDir.new do |dir| + OhlohScm::ScratchDir.new do |dir| git = GitAdapter.new(:url => dir).normalize assert !git.read_token git.init_db @@ -13,21 +13,21 @@ def test_no_token_returns_nil end def test_write_and_read_token - Scm::ScratchDir.new do |dir| + OhlohScm::ScratchDir.new do |dir| git = GitAdapter.new(:url => dir).normalize git.init_db git.write_token("FOO") assert !git.read_token # Token not valid until committed - git.commit_all(Scm::Commit.new) + git.commit_all(OhlohScm::Commit.new) assert_equal "FOO", git.read_token end end def test_commit_all_includes_write_token - Scm::ScratchDir.new do |dir| + OhlohScm::ScratchDir.new do |dir| git = GitAdapter.new(:url => dir).normalize git.init_db - c = Scm::Commit.new + c = OhlohScm::Commit.new c.token = "BAR" git.commit_all(c) assert_equal c.token, git.read_token diff --git a/test/unit/git_validation_test.rb b/test/unit/git_validation_test.rb index 8b526f4f..b7492e8d 100644 --- a/test/unit/git_validation_test.rb +++ b/test/unit/git_validation_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class GitValidationTest < Scm::Test + class GitValidationTest < OhlohScm::Test def test_rejected_urls [ nil, "", "foo", "http:/", "http:://", "http://", "http://a", "kernel.org/linux/linux.git", # missing a protocol prefix diff --git a/test/unit/hg_cat_file_test.rb b/test/unit/hg_cat_file_test.rb index c85d6e82..efc374d6 100644 --- a/test/unit/hg_cat_file_test.rb +++ b/test/unit/hg_cat_file_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class HgCatFileTest < Scm::Test + class HgCatFileTest < OhlohScm::Test def test_cat_file with_hg_repository('hg') do |hg| @@ -21,15 +21,15 @@ def test_cat_file EXPECTED # The file was deleted in revision 468336c6671c. Check that it does not exist now, but existed in parent. - assert_equal nil, hg.cat_file(Scm::Commit.new(:token => '75532c1e1f1d'), Scm::Diff.new(:path => 'helloworld.c')) - assert_equal expected, hg.cat_file_parent(Scm::Commit.new(:token => '75532c1e1f1d'), Scm::Diff.new(:path => 'helloworld.c')) - assert_equal expected, hg.cat_file(Scm::Commit.new(:token => '468336c6671c'), Scm::Diff.new(:path => 'helloworld.c')) + assert_equal nil, hg.cat_file(OhlohScm::Commit.new(:token => '75532c1e1f1d'), OhlohScm::Diff.new(:path => 'helloworld.c')) + assert_equal expected, hg.cat_file_parent(OhlohScm::Commit.new(:token => '75532c1e1f1d'), OhlohScm::Diff.new(:path => 'helloworld.c')) + assert_equal expected, hg.cat_file(OhlohScm::Commit.new(:token => '468336c6671c'), OhlohScm::Diff.new(:path => 'helloworld.c')) end end # Ensure that we escape bash-significant characters like ' and & when they appear in the filename def test_funny_file_name_chars - Scm::ScratchDir.new do |dir| + OhlohScm::ScratchDir.new do |dir| # Make a file with a problematic filename funny_name = '#|file_name` $(&\'")#' File.open(File.join(dir, funny_name), 'w') { |f| f.write "contents" } @@ -39,7 +39,7 @@ def test_funny_file_name_chars # Confirm that we can read the file back hg = HgAdapter.new(:url => dir).normalize - assert_equal "contents", hg.cat_file(hg.head, Scm::Diff.new(:path => funny_name)) + assert_equal "contents", hg.cat_file(hg.head, OhlohScm::Diff.new(:path => funny_name)) end end diff --git a/test/unit/hg_commits_test.rb b/test/unit/hg_commits_test.rb index 86fdc4b3..bff9ad3c 100644 --- a/test/unit/hg_commits_test.rb +++ b/test/unit/hg_commits_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class HgCommitsTest < Scm::Test + class HgCommitsTest < OhlohScm::Test def test_commit_count with_hg_repository('hg') do |hg| diff --git a/test/unit/hg_head_test.rb b/test/unit/hg_head_test.rb index cefccbd6..915168ee 100644 --- a/test/unit/hg_head_test.rb +++ b/test/unit/hg_head_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class HgHeadTest < Scm::Test + class HgHeadTest < OhlohScm::Test def test_head_and_parents with_hg_repository('hg') do |hg| diff --git a/test/unit/hg_misc_test.rb b/test/unit/hg_misc_test.rb index 2916e403..53fccf1c 100644 --- a/test/unit/hg_misc_test.rb +++ b/test/unit/hg_misc_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class HgMiscTest < Scm::Test + class HgMiscTest < OhlohScm::Test def test_exist save_hg = nil @@ -20,7 +20,7 @@ def test_ls_tree def test_export with_hg_repository('hg') do |hg| - Scm::ScratchDir.new do |dir| + OhlohScm::ScratchDir.new do |dir| hg.export(dir) assert_equal ['.', '..', 'README', 'makefile'], Dir.entries(dir).sort end diff --git a/test/unit/hg_parser_test.rb b/test/unit/hg_parser_test.rb index f7230ca9..93cdf8e9 100644 --- a/test/unit/hg_parser_test.rb +++ b/test/unit/hg_parser_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Parsers - class HgParserTest < Scm::Test + class HgParserTest < OhlohScm::Test def test_empty_array assert_equal([], HgParser.parse('')) diff --git a/test/unit/hg_patch_test.rb b/test/unit/hg_patch_test.rb index 95745390..8673244f 100644 --- a/test/unit/hg_patch_test.rb +++ b/test/unit/hg_patch_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class HgPatchTest < Scm::Test + class HgPatchTest < OhlohScm::Test def test_patch_for_commit with_hg_repository('hg') do |repo| commit = repo.verbose_commit(1) diff --git a/test/unit/hg_pull_test.rb b/test/unit/hg_pull_test.rb index 475d8ff1..33bafdb2 100644 --- a/test/unit/hg_pull_test.rb +++ b/test/unit/hg_pull_test.rb @@ -1,11 +1,11 @@ require_relative '../test_helper' module OhlohScm::Adapters - class HgPullTest < Scm::Test + class HgPullTest < OhlohScm::Test def test_pull with_hg_repository('hg') do |src| - Scm::ScratchDir.new do |dest_dir| + OhlohScm::ScratchDir.new do |dest_dir| dest = HgAdapter.new(:url => dest_dir).normalize assert !dest.exist? diff --git a/test/unit/hg_push_test.rb b/test/unit/hg_push_test.rb index f2e898b5..65069c84 100644 --- a/test/unit/hg_push_test.rb +++ b/test/unit/hg_push_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class HgPushTest < Scm::Test + class HgPushTest < OhlohScm::Test def test_hostname assert !HgAdapter.new.hostname @@ -36,7 +36,7 @@ def test_hg_path def test_push with_hg_repository('hg') do |src| - Scm::ScratchDir.new do |dest_dir| + OhlohScm::ScratchDir.new do |dest_dir| dest = HgAdapter.new(:url => dest_dir).normalize assert !dest.exist? diff --git a/test/unit/hg_rev_list_test.rb b/test/unit/hg_rev_list_test.rb index 7d699131..6529a74b 100644 --- a/test/unit/hg_rev_list_test.rb +++ b/test/unit/hg_rev_list_test.rb @@ -7,7 +7,7 @@ module OhlohScm::Adapters # / \ \ # A -> B -> C -> D -> tip # - class HgRevListTest < Scm::Test + class HgRevListTest < OhlohScm::Test def test_rev_list with_hg_repository('hg_walk') do |hg| diff --git a/test/unit/hg_validation_test.rb b/test/unit/hg_validation_test.rb index ea257179..517d5490 100644 --- a/test/unit/hg_validation_test.rb +++ b/test/unit/hg_validation_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class HgValidationTest < Scm::Test + class HgValidationTest < OhlohScm::Test def test_rejected_urls [ nil, "", "foo", "http:/", "http:://", "http://", "http://a", "www.selenic.com/repo/hello", # missing a protool prefix diff --git a/test/unit/hglib_cat_file_test.rb b/test/unit/hglib_cat_file_test.rb index dcb194a5..19fa4f08 100644 --- a/test/unit/hglib_cat_file_test.rb +++ b/test/unit/hglib_cat_file_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class HglibCatFileTest < Scm::Test + class HglibCatFileTest < OhlohScm::Test def test_cat_file with_hglib_repository('hg') do |hg| @@ -21,15 +21,15 @@ def test_cat_file EXPECTED # The file was deleted in revision 468336c6671c. Check that it does not exist now, but existed in parent. - assert_equal nil, hg.cat_file(Scm::Commit.new(:token => '75532c1e1f1d'), Scm::Diff.new(:path => 'helloworld.c')) - assert_equal expected, hg.cat_file_parent(Scm::Commit.new(:token => '75532c1e1f1d'), Scm::Diff.new(:path => 'helloworld.c')) - assert_equal expected, hg.cat_file(Scm::Commit.new(:token => '468336c6671c'), Scm::Diff.new(:path => 'helloworld.c')) + assert_equal nil, hg.cat_file(OhlohScm::Commit.new(:token => '75532c1e1f1d'), OhlohScm::Diff.new(:path => 'helloworld.c')) + assert_equal expected, hg.cat_file_parent(OhlohScm::Commit.new(:token => '75532c1e1f1d'), OhlohScm::Diff.new(:path => 'helloworld.c')) + assert_equal expected, hg.cat_file(OhlohScm::Commit.new(:token => '468336c6671c'), OhlohScm::Diff.new(:path => 'helloworld.c')) end end # Ensure that we escape bash-significant characters like ' and & when they appear in the filename def test_funny_file_name_chars - Scm::ScratchDir.new do |dir| + OhlohScm::ScratchDir.new do |dir| # Make a file with a problematic filename funny_name = '#|file_name` $(&\'")#' File.open(File.join(dir, funny_name), 'w') { |f| f.write "contents" } @@ -39,7 +39,7 @@ def test_funny_file_name_chars # Confirm that we can read the file back hg = HglibAdapter.new(:url => dir).normalize - assert_equal "contents", hg.cat_file(hg.head, Scm::Diff.new(:path => funny_name)) + assert_equal "contents", hg.cat_file(hg.head, OhlohScm::Diff.new(:path => funny_name)) end end diff --git a/test/unit/hglib_head_test.rb b/test/unit/hglib_head_test.rb index e7c85541..12aea8a1 100644 --- a/test/unit/hglib_head_test.rb +++ b/test/unit/hglib_head_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class HgHeadTest < Scm::Test + class HgHeadTest < OhlohScm::Test def test_head_and_parents with_hglib_repository('hg') do |hg| diff --git a/test/unit/ohlog_command_line_test.rb b/test/unit/ohlog_command_line_test.rb index 48fa9402..34f3724e 100644 --- a/test/unit/ohlog_command_line_test.rb +++ b/test/unit/ohlog_command_line_test.rb @@ -1,5 +1,5 @@ module OhlohScm::Parsers - class CommandLineTest < Scm::Test + class CommandLineTest < OhlohScm::Test def test_cvs_from_file result = `#{File.dirname(__FILE__) + '/../../bin/ohlog'} --xml --cvs #{DATA_DIR + '/basic.rlog'}` assert_equal 0, $? diff --git a/test/unit/shellout_test.rb b/test/unit/shellout_test.rb index dd8d4f27..c007d9a5 100644 --- a/test/unit/shellout_test.rb +++ b/test/unit/shellout_test.rb @@ -1,6 +1,6 @@ require_relative '../test_helper' -class ShelloutTest < Scm::Test +class ShelloutTest < OhlohScm::Test def test_execute_must_pipe_the_results_accurately status, out, err = Shellout.execute("ruby -e 'puts %[hello world]; STDERR.puts(%[some error])'") diff --git a/test/unit/string_encoder_command_line_test.rb b/test/unit/string_encoder_command_line_test.rb index 5db7538d..adecd81d 100644 --- a/test/unit/string_encoder_command_line_test.rb +++ b/test/unit/string_encoder_command_line_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Parsers - class StringEncoderCommandLineTest < Scm::Test + class StringEncoderCommandLineTest < OhlohScm::Test def test_length_of_content_unchanged file_path = File.expand_path('../../data/sample-content', __FILE__) original_content_length = File.size(file_path) diff --git a/test/unit/svn_cat_file_test.rb b/test/unit/svn_cat_file_test.rb index f65c0ee6..b82cafc9 100644 --- a/test/unit/svn_cat_file_test.rb +++ b/test/unit/svn_cat_file_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class SvnCatFileTest < Scm::Test + class SvnCatFileTest < OhlohScm::Test def test_cat_file with_svn_repository('svn') do |svn| @@ -13,9 +13,9 @@ def test_cat_file printf("Hello, World!\\n"); } EXPECTED - assert_equal expected, svn.cat_file(Scm::Commit.new(:token => 1), Scm::Diff.new(:path => "trunk/helloworld.c")) + assert_equal expected, svn.cat_file(OhlohScm::Commit.new(:token => 1), OhlohScm::Diff.new(:path => "trunk/helloworld.c")) - assert_equal nil, svn.cat_file(Scm::Commit.new(:token => 1), Scm::Diff.new(:path => "file not found")) + assert_equal nil, svn.cat_file(OhlohScm::Commit.new(:token => 1), OhlohScm::Diff.new(:path => "file not found")) end end end diff --git a/test/unit/svn_chain_cat_file_test.rb b/test/unit/svn_chain_cat_file_test.rb index 08e6139c..9dc1137e 100644 --- a/test/unit/svn_chain_cat_file_test.rb +++ b/test/unit/svn_chain_cat_file_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class SvnChainCatFileTest < Scm::Test + class SvnChainCatFileTest < OhlohScm::Test def test_cat_file_with_chaining goodbye = <<-EXPECTED @@ -13,11 +13,11 @@ def test_cat_file_with_chaining EXPECTED with_svn_chain_repository('svn_with_branching', '/trunk') do |svn| # The first case asks for the file on the HEAD, so it should easily be found - assert_equal goodbye, svn.cat_file(Scm::Commit.new(:token => 8), Scm::Diff.new(:path => "goodbyeworld.c")) + assert_equal goodbye, svn.cat_file(OhlohScm::Commit.new(:token => 8), OhlohScm::Diff.new(:path => "goodbyeworld.c")) # The next test asks for the file as it appeared before /branches/development was moved to /trunk, # so this request requires traversal up the chain to the parent SvnAdapter. - assert_equal goodbye, svn.cat_file(Scm::Commit.new(:token => 5), Scm::Diff.new(:path => "goodbyeworld.c")) + assert_equal goodbye, svn.cat_file(OhlohScm::Commit.new(:token => 5), OhlohScm::Diff.new(:path => "goodbyeworld.c")) end end end diff --git a/test/unit/svn_chain_commits_test.rb b/test/unit/svn_chain_commits_test.rb index 52e9d0c7..5a17f7eb 100644 --- a/test/unit/svn_chain_commits_test.rb +++ b/test/unit/svn_chain_commits_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Parsers - class SvnChainTest < Scm::Test + class SvnChainTest < OhlohScm::Test def test_chained_commit_tokens with_svn_chain_repository('svn_with_branching', '/trunk') do |svn| diff --git a/test/unit/svn_chain_test.rb b/test/unit/svn_chain_test.rb index d646e73a..bf15b627 100644 --- a/test/unit/svn_chain_test.rb +++ b/test/unit/svn_chain_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Parsers - class SvnChainTest < Scm::Test + class SvnChainTest < OhlohScm::Test def test_chain with_svn_chain_repository('svn_with_branching', '/trunk') do |svn| @@ -54,7 +54,7 @@ def test_parent_svn def test_parent_branch_name svn = OhlohScm::Adapters::SvnChainAdapter.new(:branch_name => "/trunk") - assert_equal "/branches/b", svn.parent_branch_name(Scm::Diff.new(:action => 'A', + assert_equal "/branches/b", svn.parent_branch_name(OhlohScm::Diff.new(:action => 'A', :path => "/trunk", :from_revision => 1, :from_path => "/branches/b")) end diff --git a/test/unit/svn_commits_test.rb b/test/unit/svn_commits_test.rb index 2deb521d..c6758594 100644 --- a/test/unit/svn_commits_test.rb +++ b/test/unit/svn_commits_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class SvnCommitsTest < Scm::Test + class SvnCommitsTest < OhlohScm::Test def test_commits with_svn_repository('svn') do |svn| @@ -32,8 +32,8 @@ def test_sha1 # Given a commit with diffs, fill in all of the SHA1 values. def test_populate_sha1 with_svn_repository('svn') do |svn| - c = Scm::Commit.new(:token => 3) - c.diffs = [Scm::Diff.new(:path => "/trunk/helloworld.c", :action => "M")] + c = OhlohScm::Commit.new(:token => 3) + c.diffs = [OhlohScm::Diff.new(:path => "/trunk/helloworld.c", :action => "M")] svn.populate_commit_sha1s!(c) assert_equal 'f6adcae4447809b651c787c078d255b2b4e963c5', c.diffs.first.sha1 assert_equal '4c734ad53b272c9b3d719f214372ac497ff6c068', c.diffs.first.parent_sha1 @@ -42,7 +42,7 @@ def test_populate_sha1 def test_strip_commit_branch svn = SvnAdapter.new(:branch_name => "/trunk") - commit = Scm::Commit.new + commit = OhlohScm::Commit.new # nil diffs before => nil diffs after assert !svn.strip_commit_branch(commit).diffs @@ -52,19 +52,19 @@ def test_strip_commit_branch assert_equal [], svn.strip_commit_branch(commit).diffs commit.diffs = [ - Scm::Diff.new(:path => "/trunk"), - Scm::Diff.new(:path => "/trunk/helloworld.c"), - Scm::Diff.new(:path => "/branches/a") + OhlohScm::Diff.new(:path => "/trunk"), + OhlohScm::Diff.new(:path => "/trunk/helloworld.c"), + OhlohScm::Diff.new(:path => "/branches/a") ] assert_equal ['', '/helloworld.c'], svn.strip_commit_branch(commit).diffs.collect { |d| d.path }.sort end def test_strip_diff_branch svn = SvnAdapter.new(:branch_name => "/trunk") - assert !svn.strip_diff_branch(Scm::Diff.new) - assert !svn.strip_diff_branch(Scm::Diff.new(:path => "/branches/b")) - assert_equal '', svn.strip_diff_branch(Scm::Diff.new(:path => "/trunk")).path - assert_equal '/helloworld.c', svn.strip_diff_branch(Scm::Diff.new(:path => "/trunk/helloworld.c")).path + assert !svn.strip_diff_branch(OhlohScm::Diff.new) + assert !svn.strip_diff_branch(OhlohScm::Diff.new(:path => "/branches/b")) + assert_equal '', svn.strip_diff_branch(OhlohScm::Diff.new(:path => "/trunk")).path + assert_equal '/helloworld.c', svn.strip_diff_branch(OhlohScm::Diff.new(:path => "/trunk/helloworld.c")).path end def test_strip_path_branch @@ -88,8 +88,8 @@ def test_strip_path_branch_with_special_chars def test_remove_dupes_add_modify svn = SvnAdapter.new - c = Scm::Commit.new(:diffs => [ Scm::Diff.new(:action => "A", :path => "foo"), - Scm::Diff.new(:action => "M", :path => "foo") ]) + c = OhlohScm::Commit.new(:diffs => [ OhlohScm::Diff.new(:action => "A", :path => "foo"), + OhlohScm::Diff.new(:action => "M", :path => "foo") ]) svn.remove_dupes(c) assert_equal 1, c.diffs.size @@ -98,8 +98,8 @@ def test_remove_dupes_add_modify def test_remove_dupes_add_replace svn = SvnAdapter.new - c = Scm::Commit.new(:diffs => [ Scm::Diff.new(:action => "R", :path => "foo"), - Scm::Diff.new(:action => "A", :path => "foo") ]) + c = OhlohScm::Commit.new(:diffs => [ OhlohScm::Diff.new(:action => "R", :path => "foo"), + OhlohScm::Diff.new(:action => "A", :path => "foo") ]) svn.remove_dupes(c) assert_equal 1, c.diffs.size diff --git a/test/unit/svn_convert_test.rb b/test/unit/svn_convert_test.rb index 08a3fca1..a8153d76 100644 --- a/test/unit/svn_convert_test.rb +++ b/test/unit/svn_convert_test.rb @@ -1,10 +1,10 @@ require_relative '../test_helper' module OhlohScm::Adapters - class SvnConvertTest < Scm::Test + class SvnConvertTest < OhlohScm::Test def test_basic_convert with_svn_repository('svn') do |src| - Scm::ScratchDir.new do |dest_dir| + OhlohScm::ScratchDir.new do |dest_dir| dest = GitAdapter.new(:url => dest_dir).normalize assert !dest.exist? diff --git a/test/unit/svn_head_test.rb b/test/unit/svn_head_test.rb index 30499ff3..2b94e782 100644 --- a/test/unit/svn_head_test.rb +++ b/test/unit/svn_head_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class SvnHeadTest < Scm::Test + class SvnHeadTest < OhlohScm::Test def test_head_and_parents with_svn_repository('svn') do |svn| diff --git a/test/unit/svn_misc_test.rb b/test/unit/svn_misc_test.rb index 3f3cece8..0894f765 100644 --- a/test/unit/svn_misc_test.rb +++ b/test/unit/svn_misc_test.rb @@ -1,11 +1,11 @@ require_relative '../test_helper' module OhlohScm::Adapters - class SvnMiscTest < Scm::Test + class SvnMiscTest < OhlohScm::Test def test_export with_svn_repository('svn') do |svn| - Scm::ScratchDir.new do |dir| + OhlohScm::ScratchDir.new do |dir| svn.export(dir) assert_equal ['.','..','branches','tags','trunk'], Dir.entries(dir).sort end diff --git a/test/unit/svn_parser_test.rb b/test/unit/svn_parser_test.rb index c50cafa6..83609fa4 100644 --- a/test/unit/svn_parser_test.rb +++ b/test/unit/svn_parser_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Parsers - class SvnParserTest < Scm::Test + class SvnParserTest < OhlohScm::Test def test_basic assert_convert(SvnParser, DATA_DIR + '/simple.svn_log', DATA_DIR + '/simple.ohlog') diff --git a/test/unit/svn_patch_test.rb b/test/unit/svn_patch_test.rb index eda5b35e..301aea05 100644 --- a/test/unit/svn_patch_test.rb +++ b/test/unit/svn_patch_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Adapters - class SvnPatchTest < Scm::Test + class SvnPatchTest < OhlohScm::Test def test_patch_for_commit with_svn_repository('svn') do |repo| commit = repo.verbose_commit(2) diff --git a/test/unit/svn_pull_test.rb b/test/unit/svn_pull_test.rb index 7341f21d..91985079 100644 --- a/test/unit/svn_pull_test.rb +++ b/test/unit/svn_pull_test.rb @@ -2,10 +2,10 @@ require 'socket' module OhlohScm::Adapters - class SvnPullTest < Scm::Test + class SvnPullTest < OhlohScm::Test def test_svnadmin_create - Scm::ScratchDir.new do |dir| + OhlohScm::ScratchDir.new do |dir| url = File.join(dir, "my_svn_repo") svn = SvnAdapter.new(:url => url).normalize @@ -22,7 +22,7 @@ def test_svnadmin_create def test_basic_pull_using_svnsync with_svn_repository('svn') do |src| - Scm::ScratchDir.new do |dest_dir| + OhlohScm::ScratchDir.new do |dest_dir| dest = SvnAdapter.new(:url => dest_dir).normalize assert !dest.exist? @@ -36,7 +36,7 @@ def test_basic_pull_using_svnsync end def test_svnadmin_create_local - Scm::ScratchDir.new do |dir| + OhlohScm::ScratchDir.new do |dir| svn = SvnAdapter.new(:url => "file://#{dir}") svn.svnadmin_create_local assert svn.exist? @@ -47,7 +47,7 @@ def test_svnadmin_create_local end def test_svnadmin_create_remote - Scm::ScratchDir.new do |dir| + OhlohScm::ScratchDir.new do |dir| svn = SvnAdapter.new(:url => "svn+ssh://#{Socket.gethostname}#{dir}") svn.svnadmin_create_remote assert svn.exist? diff --git a/test/unit/svn_push_test.rb b/test/unit/svn_push_test.rb index fa59ec99..98594265 100644 --- a/test/unit/svn_push_test.rb +++ b/test/unit/svn_push_test.rb @@ -2,11 +2,11 @@ require 'socket' module OhlohScm::Adapters - class SvnPushTest < Scm::Test + class SvnPushTest < OhlohScm::Test def test_basic_push_using_svnsync with_svn_repository('svn') do |src| - Scm::ScratchDir.new do |dest_dir| + OhlohScm::ScratchDir.new do |dest_dir| dest = SvnAdapter.new(:url => dest_dir).normalize assert !dest.exist? @@ -23,7 +23,7 @@ def test_basic_push_using_svnsync # Simulates pushing to another server in our cluster. def test_ssh_push_using_svnsync with_svn_repository('svn') do |src| - Scm::ScratchDir.new do |dest_dir| + OhlohScm::ScratchDir.new do |dest_dir| dest = SvnAdapter.new(:url => "svn+ssh://#{Socket.gethostname}#{File.expand_path(dest_dir)}").normalize assert !dest.exist? diff --git a/test/unit/svn_validation_test.rb b/test/unit/svn_validation_test.rb index 274b8cfe..f8dc8cf2 100644 --- a/test/unit/svn_validation_test.rb +++ b/test/unit/svn_validation_test.rb @@ -1,13 +1,13 @@ require_relative '../test_helper' module OhlohScm::Adapters - class SvnValidationTest < Scm::Test + class SvnValidationTest < OhlohScm::Test def test_valid_usernames [nil,'','joe_36','a'*32,'robin@ohloh.net'].each do |username| assert !SvnAdapter.new(:username => username).validate_username end end - + def test_for_blank_svn_urls svn = SvnAdapter.new(:url =>"") assert_nil svn.path_to_file_url(svn.url) @@ -167,7 +167,7 @@ def test_strip_trailing_whack_from_branch_name end def test_empty_branch_name_with_file_system - Scm::ScratchDir.new do |dir| + OhlohScm::ScratchDir.new do |dir| svn = SvnAdapter.new(:url => dir).normalize assert_equal '', svn.branch_name end diff --git a/test/unit/svn_xml_parser_test.rb b/test/unit/svn_xml_parser_test.rb index a2bd9f58..ccb9c066 100644 --- a/test/unit/svn_xml_parser_test.rb +++ b/test/unit/svn_xml_parser_test.rb @@ -1,7 +1,7 @@ require_relative '../test_helper' module OhlohScm::Parsers - class SvnXmlParserTest < Scm::Test + class SvnXmlParserTest < OhlohScm::Test def test_basic assert_convert(SvnXmlParser, DATA_DIR + '/simple.svn_xml_log', DATA_DIR + '/simple.ohlog') @@ -14,7 +14,7 @@ def test_empty_array def test_empty_xml assert_equal("\n\n\n", SvnXmlParser.parse('', :writer => XmlWriter.new)) end - + def test_copy_from xml = <<-XML From 7da779e67ba8490de24a64b8ef85af59758f0d4f Mon Sep 17 00:00:00 2001 From: Peter Degen-Portnoy Date: Thu, 16 Oct 2014 11:57:22 +0000 Subject: [PATCH 168/219] Update to version 2.0.1 --- lib/ohloh_scm/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ohloh_scm/version.rb b/lib/ohloh_scm/version.rb index 3e692ad5..37048918 100644 --- a/lib/ohloh_scm/version.rb +++ b/lib/ohloh_scm/version.rb @@ -1,5 +1,5 @@ module OhlohScm module Version - STRING = '2.0.0' + STRING = '2.0.1' end end From 30641e2cfb98db7dc4bfbc868fa6bb394f5d0446 Mon Sep 17 00:00:00 2001 From: santhanakarthikeyan Date: Tue, 12 Apr 2016 00:33:10 +0530 Subject: [PATCH 169/219] Replaced Open3 with Posix-spawn to reduce more process memory usage --- README.md | 7 +++++++ lib/ohloh_scm/shellout.rb | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e9a3adf4..28d9c2a1 100644 --- a/README.md +++ b/README.md @@ -49,10 +49,17 @@ hg 1.1.2 If you are using CVS instead of CVSNT, you can potentially try creating a shell alias or symlink mapping 'cvsnt' to 'cvs'. +Ohloh SCM uses [posix-spawn](https://github.com/rtomayko/posix-spawn) to +execute commands so ensure *posix-spawn* gem is installed + +``gem install posix-spawn`` + + ## Usage with Bundler ``` gem 'ohloh_scm', git: 'https://github.com/blackducksw/ohloh_scm/', require: 'scm' +gem 'posix-spawn' ``` ## Running diff --git a/lib/ohloh_scm/shellout.rb b/lib/ohloh_scm/shellout.rb index 7c49ab38..68fe3775 100644 --- a/lib/ohloh_scm/shellout.rb +++ b/lib/ohloh_scm/shellout.rb @@ -1,6 +1,6 @@ require 'rubygems' require 'stringio' -require 'open3' +require 'posix/spawn' class Shellout @@ -9,9 +9,9 @@ def self.relay src, dst end def self.execute(cmd) - out, err, exit_status = Open3.capture3(cmd) + posix_spawn = POSIX::Spawn::Child.new(cmd) - return exit_status, out, err + return posix_spawn.status, posix_spawn.out, posix_spawn.err end def run(cmd) From 86eb16debec8ce24e459dd8f98b686178c181944 Mon Sep 17 00:00:00 2001 From: santhanakarthikeyan Date: Tue, 12 Apr 2016 19:33:05 +0530 Subject: [PATCH 170/219] Added travis.yml file for installing gem dependencies --- .ruby-version | 1 + .travis.yml | 2 ++ 2 files changed, 3 insertions(+) create mode 100644 .ruby-version create mode 100644 .travis.yml diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 00000000..227cea21 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +2.0.0 diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..bb0275e7 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,2 @@ +language: ruby +install: gem install posix-spawn From bfda2ba1764a2e3a230f6f6b6f01fca9a1077d80 Mon Sep 17 00:00:00 2001 From: santhanakarthikeyan Date: Tue, 12 Apr 2016 19:49:03 +0530 Subject: [PATCH 171/219] Replaced Open4 with posix-spawn gem --- lib/ohloh_scm/adapters/bzrlib/bzrlib_pipe_client.rb | 4 ++-- lib/ohloh_scm/adapters/hglib/client.rb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/ohloh_scm/adapters/bzrlib/bzrlib_pipe_client.rb b/lib/ohloh_scm/adapters/bzrlib/bzrlib_pipe_client.rb index aece32f7..f4ffb2f9 100644 --- a/lib/ohloh_scm/adapters/bzrlib/bzrlib_pipe_client.rb +++ b/lib/ohloh_scm/adapters/bzrlib/bzrlib_pipe_client.rb @@ -1,5 +1,5 @@ require 'rubygems' -require 'open4' +require 'posix/spawn' class BzrPipeClient def initialize(repository_url) @@ -8,7 +8,7 @@ def initialize(repository_url) end def start - @pid, @stdin, @stdout, @stderr = Open4::popen4 "python #{@py_script}" + @pid, @stdin, @stdout, @stderr = POSIX::Spawn::popen4 "python #{@py_script}" open_repository end diff --git a/lib/ohloh_scm/adapters/hglib/client.rb b/lib/ohloh_scm/adapters/hglib/client.rb index 65c414c9..c15a6b9e 100644 --- a/lib/ohloh_scm/adapters/hglib/client.rb +++ b/lib/ohloh_scm/adapters/hglib/client.rb @@ -1,5 +1,5 @@ require 'rubygems' -require 'open4' +require 'posix/spawn' class HglibClient def initialize(repository_url) @@ -8,7 +8,7 @@ def initialize(repository_url) end def start - @pid, @stdin, @stdout, @stderr = Open4::popen4 "python #{@py_script}" + @pid, @stdin, @stdout, @stderr = POSIX::Spawn::popen4 "python #{@py_script}" open_repository end From 8732a56b1a489583a2880dfae7c748e382c95710 Mon Sep 17 00:00:00 2001 From: santhanakarthikeyan Date: Tue, 12 Apr 2016 20:07:30 +0530 Subject: [PATCH 172/219] Added script to install dependencies like xmloutput plugin --- .install_dependencies.sh | 13 +++++++++++++ .travis.yml | 4 +++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100755 .install_dependencies.sh diff --git a/.install_dependencies.sh b/.install_dependencies.sh new file mode 100755 index 00000000..bcec6f01 --- /dev/null +++ b/.install_dependencies.sh @@ -0,0 +1,13 @@ +#/usr/bin/env sh + +bazaar_plugins_path=`bzr --version | awk '/bzrlib:/ {print $2}'` + +cd "$bazaar_plugins_path/plugins" + +sudo bzr branch lp:bzr-xmloutput + +sudo mv bzr-xmloutput xmloutput + +cd xmloutput + +python setup.py build_ext -i diff --git a/.travis.yml b/.travis.yml index bb0275e7..eeac2080 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,2 +1,4 @@ language: ruby -install: gem install posix-spawn +install: + - gem install posix-spawn + - sh .install_dependencies.sh From 26e57ff244488a13f523d97dfea17c56b428d9b6 Mon Sep 17 00:00:00 2001 From: santhanakarthikeyan Date: Wed, 13 Apr 2016 13:20:52 +0530 Subject: [PATCH 173/219] Added posix-spawn gem dependency --- ohloh_scm.gemspec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ohloh_scm.gemspec b/ohloh_scm.gemspec index 0de6e165..74ee9d8a 100644 --- a/ohloh_scm.gemspec +++ b/ohloh_scm.gemspec @@ -16,4 +16,6 @@ Gem::Specification.new do |gem| gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) } gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) gem.require_paths = %w(lib) + + gem.add_runtime_dependency 'posix-spawn', '~> 0.3' end From 581e6f2472ef900d8b558937257099465aa49d6c Mon Sep 17 00:00:00 2001 From: arun Date: Mon, 23 May 2016 21:51:03 +0530 Subject: [PATCH 174/219] Fix for file descriptor leaks --- lib/ohloh_scm/adapters/bzrlib/bzrlib_pipe_client.rb | 6 ++++-- lib/ohloh_scm/adapters/bzrlib_adapter.rb | 8 ++++---- lib/ohloh_scm/adapters/hglib/client.rb | 2 ++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/ohloh_scm/adapters/bzrlib/bzrlib_pipe_client.rb b/lib/ohloh_scm/adapters/bzrlib/bzrlib_pipe_client.rb index f4ffb2f9..d200c056 100644 --- a/lib/ohloh_scm/adapters/bzrlib/bzrlib_pipe_client.rb +++ b/lib/ohloh_scm/adapters/bzrlib/bzrlib_pipe_client.rb @@ -6,7 +6,7 @@ def initialize(repository_url) @repository_url = repository_url @py_script = File.dirname(__FILE__) + '/bzrlib_pipe_server.py' end - + def start @pid, @stdin, @stdout, @stderr = POSIX::Spawn::popen4 "python #{@py_script}" open_repository @@ -27,8 +27,9 @@ def send_command(cmd) # send the command @stdin.puts cmd @stdin.flush + return if cmd == "QUIT" - # get status on stderr, first letter indicates state, + # get status on stderr, first letter indicates state, # remaing value indicates length of the file content status = @stderr.read(10) flag = status[0,1] @@ -46,6 +47,7 @@ def send_command(cmd) def shutdown send_command("QUIT") + [@stdout, @stdin, @stderr].each { |io| io.close unless io.closed? } Process.waitpid(@pid, Process::WNOHANG) end end diff --git a/lib/ohloh_scm/adapters/bzrlib_adapter.rb b/lib/ohloh_scm/adapters/bzrlib_adapter.rb index 512cd937..bde29fa5 100644 --- a/lib/ohloh_scm/adapters/bzrlib_adapter.rb +++ b/lib/ohloh_scm/adapters/bzrlib_adapter.rb @@ -5,13 +5,13 @@ module OhlohScm::Adapters class BzrlibAdapter < BzrAdapter def setup - @bzr_client = BzrPipeClient.new(url) - @bzr_client.start + bzr_client = BzrPipeClient.new(url) + bzr_client.start + bzr_client end def bzr_client - setup unless @bzr_client - return @bzr_client + @bzr_client ||= setup end def cleanup diff --git a/lib/ohloh_scm/adapters/hglib/client.rb b/lib/ohloh_scm/adapters/hglib/client.rb index c15a6b9e..e3d8733b 100644 --- a/lib/ohloh_scm/adapters/hglib/client.rb +++ b/lib/ohloh_scm/adapters/hglib/client.rb @@ -36,6 +36,7 @@ def send_command(cmd) # send the command @stdin.puts cmd @stdin.flush + return if cmd == "QUIT" # get status on stderr, first letter indicates state, # remaing value indicates length of the file content @@ -55,6 +56,7 @@ def send_command(cmd) def shutdown send_command("QUIT") + [@stdout, @stdin, @stderr].each { |io| io.close unless io.closed? } Process.waitpid(@pid, Process::WNOHANG) end end From 1af22dc7ae5da035952761069b267d85259945a6 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Tue, 7 Jun 2016 18:27:28 +0530 Subject: [PATCH 175/219] Version bump --- lib/ohloh_scm/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ohloh_scm/version.rb b/lib/ohloh_scm/version.rb index 37048918..e9f6ffc1 100644 --- a/lib/ohloh_scm/version.rb +++ b/lib/ohloh_scm/version.rb @@ -1,5 +1,5 @@ module OhlohScm module Version - STRING = '2.0.1' + STRING = '2.1.0' end end From 6699a6db7001b3fb5cf49cba606e7b3306ed1c40 Mon Sep 17 00:00:00 2001 From: arun Date: Fri, 10 Jun 2016 20:40:00 +0530 Subject: [PATCH 176/219] OTWO-4267 Workaround to resolve 'git push fails:refusing to update checked out branch' --- lib/ohloh_scm/adapters/git/push.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/ohloh_scm/adapters/git/push.rb b/lib/ohloh_scm/adapters/git/push.rb index bae4e69a..a8c8493a 100644 --- a/lib/ohloh_scm/adapters/git/push.rb +++ b/lib/ohloh_scm/adapters/git/push.rb @@ -10,7 +10,9 @@ def push(to) if to.exist? ENV['GIT_COMMITTER_NAME'] = COMMITTER_NAME + run "cd '#{to.url}' && git checkout -b tmp" run "cd '#{self.url}' && git push '#{to.url}' #{self.branch_name}:#{to.branch_name}" + run "cd '#{to.url}' && git checkout master && git branch -d tmp" else if to.local? # Create a new repo on the same local machine. Just use existing pull code in reverse. From 2ea0d4fc5ccf691d0656d72d1b3456dec82ede27 Mon Sep 17 00:00:00 2001 From: arun Date: Fri, 10 Jun 2016 15:29:16 +0530 Subject: [PATCH 177/219] OTWO-4267 Added dependencies configuration and resolved failing test cases --- .travis.yml | 4 ++++ lib/ohloh_scm/adapters/bzr/misc.rb | 4 +++- lib/ohloh_scm/adapters/hg/cat_file.rb | 4 +++- test/unit/cvs_commits_test.rb | 22 +++++++++++----------- test/unit/hg_cat_file_test.rb | 2 +- test/unit/hglib_cat_file_test.rb | 2 +- test/unit/shellout_test.rb | 1 + 7 files changed, 24 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index eeac2080..f2f095b7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,8 @@ language: ruby +before_install: + - sudo apt-get install -y cvs + - sudo ln -s /usr/bin/cvs /usr/bin/cvsnt + - sudo apt-get install -y subversion install: - gem install posix-spawn - sh .install_dependencies.sh diff --git a/lib/ohloh_scm/adapters/bzr/misc.rb b/lib/ohloh_scm/adapters/bzr/misc.rb index 12f5b9a5..3b24c5fc 100644 --- a/lib/ohloh_scm/adapters/bzr/misc.rb +++ b/lib/ohloh_scm/adapters/bzr/misc.rb @@ -10,7 +10,9 @@ def exist? end def ls_tree(token) - run("cd #{path} && bzr ls -V -r #{to_rev_param(token)}").split("\n") + run("cd #{path} && bzr ls -V -r #{to_rev_param(token)}").split("\n").map!{ |file_name| + file_name.force_encoding(Encoding::UTF_8) + } end def to_rev_param(r=nil) diff --git a/lib/ohloh_scm/adapters/hg/cat_file.rb b/lib/ohloh_scm/adapters/hg/cat_file.rb index e8caf7d6..1620d8eb 100644 --- a/lib/ohloh_scm/adapters/hg/cat_file.rb +++ b/lib/ohloh_scm/adapters/hg/cat_file.rb @@ -1,3 +1,5 @@ +require 'shellwords' + module OhlohScm::Adapters class HgAdapter < AbstractAdapter def cat_file(commit, diff) @@ -20,7 +22,7 @@ def cat(revision, path) # Example: # "Foo Bar & Baz" => "Foo\ Bar\ \&\ Baz" def escape(path) - path.gsub(/[ `'"&()<>|#\$]/) { |c| '\\' + c } + path.shellescape end end end diff --git a/test/unit/cvs_commits_test.rb b/test/unit/cvs_commits_test.rb index b2013804..575bdca4 100644 --- a/test/unit/cvs_commits_test.rb +++ b/test/unit/cvs_commits_test.rb @@ -6,19 +6,19 @@ class CvsCommitsTest < OhlohScm::Test def test_commits with_cvs_repository('cvs', 'simple') do |cvs| - assert_equal ['2006/06/29 16:21:07', - '2006/06/29 18:14:47', - '2006/06/29 18:45:29', - '2006/06/29 18:48:54', - '2006/06/29 18:52:23'], cvs.commits.collect { |c| c.token } - - assert_equal ['2006/06/29 18:48:54', - '2006/06/29 18:52:23'], - cvs.commits(:after => '2006/06/29 18:45:29').collect { |c| c.token } + assert_equal ['2006-06-29 16:21:07', + '2006-06-29 18:14:47', + '2006-06-29 18:45:29', + '2006-06-29 18:48:54', + '2006-06-29 18:52:23'], cvs.commits.collect { |c| c.token } # Make sure we are date format agnostic (2008/01/01 is the same as 2008-01-01) - assert_equal ['2006/06/29 18:48:54', - '2006/06/29 18:52:23'], + assert_equal ['2006-06-29 18:48:54', + '2006-06-29 18:52:23'], + cvs.commits(:after => '2006/06/29 18:45:29').collect { |c| c.token } + + assert_equal ['2006-06-29 18:48:54', + '2006-06-29 18:52:23'], cvs.commits(:after => '2006-06-29 18:45:29').collect { |c| c.token } assert_equal [], cvs.commits(:after => '2006/06/29 18:52:23').collect { |c| c.token } diff --git a/test/unit/hg_cat_file_test.rb b/test/unit/hg_cat_file_test.rb index efc374d6..0b36820e 100644 --- a/test/unit/hg_cat_file_test.rb +++ b/test/unit/hg_cat_file_test.rb @@ -35,7 +35,7 @@ def test_funny_file_name_chars File.open(File.join(dir, funny_name), 'w') { |f| f.write "contents" } # Add it to an hg repository - `cd #{dir} && hg init && hg add * && hg commit -m test` + `cd #{dir} && hg init && hg add * && hg commit -u tester -m test` # Confirm that we can read the file back hg = HgAdapter.new(:url => dir).normalize diff --git a/test/unit/hglib_cat_file_test.rb b/test/unit/hglib_cat_file_test.rb index 19fa4f08..3b0be631 100644 --- a/test/unit/hglib_cat_file_test.rb +++ b/test/unit/hglib_cat_file_test.rb @@ -35,7 +35,7 @@ def test_funny_file_name_chars File.open(File.join(dir, funny_name), 'w') { |f| f.write "contents" } # Add it to an hg repository - `cd #{dir} && hg init && hg add * && hg commit -m test` + `cd #{dir} && hg init && hg add * && hg commit -u tester -m test` # Confirm that we can read the file back hg = HglibAdapter.new(:url => dir).normalize diff --git a/test/unit/shellout_test.rb b/test/unit/shellout_test.rb index c007d9a5..108ebaf2 100644 --- a/test/unit/shellout_test.rb +++ b/test/unit/shellout_test.rb @@ -1,4 +1,5 @@ require_relative '../test_helper' +require 'timeout' class ShelloutTest < OhlohScm::Test def test_execute_must_pipe_the_results_accurately From 83fe15a10c9e3cbd77c32b6600683af7be7e1636 Mon Sep 17 00:00:00 2001 From: Peter Degen-Portnoy Date: Thu, 16 Jun 2016 13:28:33 -0400 Subject: [PATCH 178/219] Add Travis CI badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 28d9c2a1..3d55cd28 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Ohloh SCM on Ohloh](https://www.ohloh.net/p/ohloh_scm/widgets/project_partner_badge.gif)](https://www.ohloh.net/p/ohloh_scm) +[![Ohloh SCM on Ohloh](https://www.ohloh.net/p/ohloh_scm/widgets/project_partner_badge.gif)](https://www.ohloh.net/p/ohloh_scm) [![Build Status](https://travis-ci.org/blackducksoftware/ohloh_scm.svg?branch=master)](https://travis-ci.org/blackducksoftware/ohloh_scm) # Ohloh SCM From 5a66f7d801fac7d6d8ef6bd5eb0a66f03a417a81 Mon Sep 17 00:00:00 2001 From: arun Date: Fri, 10 Jun 2016 20:54:19 +0530 Subject: [PATCH 179/219] OTWO-4267 Configured installation of multiple SCMs in travis builds --- .install_multiple_scms.sh | 8 ++++++++ .travis.yml | 4 +--- lib/ohloh_scm/adapters/hglib_adapter.rb | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 .install_multiple_scms.sh diff --git a/.install_multiple_scms.sh b/.install_multiple_scms.sh new file mode 100644 index 00000000..df06cca9 --- /dev/null +++ b/.install_multiple_scms.sh @@ -0,0 +1,8 @@ +sudo apt-get install -y cvs +sudo ln -s /usr/bin/cvs /usr/bin/cvsnt +sudo apt-get install -y bzr +sudo apt-get install -y mercurial +sudo sh -c 'echo "deb http://opensource.wandisco.com/ubuntu precise svn18" >> /etc/apt/sources.list.d/subversion18.list' +sudo wget -q http://opensource.wandisco.com/wandisco-debian.gpg -O- | sudo apt-key add - +sudo apt-get update +sudo apt-get install -y subversion diff --git a/.travis.yml b/.travis.yml index f2f095b7..d6e8c773 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,6 @@ language: ruby before_install: - - sudo apt-get install -y cvs - - sudo ln -s /usr/bin/cvs /usr/bin/cvsnt - - sudo apt-get install -y subversion + - sh .install_multiple_scms.sh install: - gem install posix-spawn - sh .install_dependencies.sh diff --git a/lib/ohloh_scm/adapters/hglib_adapter.rb b/lib/ohloh_scm/adapters/hglib_adapter.rb index f0eb6ac6..f9dca0e3 100644 --- a/lib/ohloh_scm/adapters/hglib_adapter.rb +++ b/lib/ohloh_scm/adapters/hglib_adapter.rb @@ -21,5 +21,5 @@ def cleanup end end -require_relative 'hglib/cat_file' require_relative 'hglib/head' +require_relative 'hglib/cat_file' From 535d2d50f32a675a597ee0c9ccc41b5fa22fa571 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Tue, 21 Jun 2016 15:02:25 +0530 Subject: [PATCH 180/219] OTWO-4267 Avoid changing encoding for processed data If ohloh_scm changes the encoding, original characters might be lost. Users might be aware of the correct encoding and may wish to handle it accordingly. --- lib/ohloh_scm/adapters/bzr/misc.rb | 4 +--- test/unit/bzr_misc_test.rb | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/ohloh_scm/adapters/bzr/misc.rb b/lib/ohloh_scm/adapters/bzr/misc.rb index 3b24c5fc..5f30aa14 100644 --- a/lib/ohloh_scm/adapters/bzr/misc.rb +++ b/lib/ohloh_scm/adapters/bzr/misc.rb @@ -10,9 +10,7 @@ def exist? end def ls_tree(token) - run("cd #{path} && bzr ls -V -r #{to_rev_param(token)}").split("\n").map!{ |file_name| - file_name.force_encoding(Encoding::UTF_8) - } + run("cd #{path} && bzr ls -V -r #{to_rev_param(token)}").split("\n") end def to_rev_param(r=nil) diff --git a/test/unit/bzr_misc_test.rb b/test/unit/bzr_misc_test.rb index ec2fcf6a..44e788ff 100644 --- a/test/unit/bzr_misc_test.rb +++ b/test/unit/bzr_misc_test.rb @@ -20,7 +20,8 @@ def test_ls_tree 'file3.txt', 'file4.txt', 'file5.txt'], - bzr.ls_tree(bzr.head_token).sort + bzr.ls_tree(bzr.head_token).sort.map { |filename| + filename.force_encoding(Encoding::UTF_8) } end end From 91181b62d87c0f3dbb156f490c5fa021e2c160c8 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Wed, 22 Jun 2016 13:29:22 +0530 Subject: [PATCH 181/219] OTWO-4267 Use a bare git repo for git push test Undid previous lib changes made just to make test pass on travis. --- lib/ohloh_scm/adapters/git/push.rb | 2 -- test/unit/git_push_test.rb | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/ohloh_scm/adapters/git/push.rb b/lib/ohloh_scm/adapters/git/push.rb index a8c8493a..bae4e69a 100644 --- a/lib/ohloh_scm/adapters/git/push.rb +++ b/lib/ohloh_scm/adapters/git/push.rb @@ -10,9 +10,7 @@ def push(to) if to.exist? ENV['GIT_COMMITTER_NAME'] = COMMITTER_NAME - run "cd '#{to.url}' && git checkout -b tmp" run "cd '#{self.url}' && git push '#{to.url}' #{self.branch_name}:#{to.branch_name}" - run "cd '#{to.url}' && git checkout master && git branch -d tmp" else if to.local? # Create a new repo on the same local machine. Just use existing pull code in reverse. diff --git a/test/unit/git_push_test.rb b/test/unit/git_push_test.rb index 973992c3..8f4b5712 100644 --- a/test/unit/git_push_test.rb +++ b/test/unit/git_push_test.rb @@ -24,7 +24,6 @@ def test_local def test_basic_push with_git_repository('git') do |src| OhlohScm::ScratchDir.new do |dest_dir| - dest = GitAdapter.new(:url => dest_dir).normalize assert !dest.exist? @@ -36,10 +35,10 @@ def test_basic_push File.open(File.join(src.url, 'foo'), 'w') { } src.commit_all(OhlohScm::Commit.new) + system("cd #{ dest_dir } && git config --bool core.bare true && git config receive.denyCurrentBranch refuse") src.push(dest) assert dest.exist? assert_equal src.log, dest.log - end end end From 8346b299b9c2d04ece579e36bd4f558df8ae0bdf Mon Sep 17 00:00:00 2001 From: arun Date: Wed, 22 Jun 2016 16:38:37 +0530 Subject: [PATCH 182/219] OTWO-4281 Configured travis ssh setup and its dependencies --- .travis.yml | 10 ++++++++-- .../.install_dependencies.sh | 0 .../.install_multiple_scms.sh | 7 ++----- .travis/.travis_ssh_setup.sh | 3 +++ 4 files changed, 13 insertions(+), 7 deletions(-) rename .install_dependencies.sh => .travis/.install_dependencies.sh (100%) rename .install_multiple_scms.sh => .travis/.install_multiple_scms.sh (68%) create mode 100644 .travis/.travis_ssh_setup.sh diff --git a/.travis.yml b/.travis.yml index d6e8c773..664b1b74 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,12 @@ language: ruby +env: + - TRAVIS_CONFIG_DIR=.travis before_install: - - sh .install_multiple_scms.sh + - cd $TRAVIS_CONFIG_DIR + - sh .travis_ssh_setup.sh install: - - gem install posix-spawn + - sh .install_multiple_scms.sh - sh .install_dependencies.sh + - gem install posix-spawn +before_script: + - cd $TRAVIS_BUILD_DIR diff --git a/.install_dependencies.sh b/.travis/.install_dependencies.sh similarity index 100% rename from .install_dependencies.sh rename to .travis/.install_dependencies.sh diff --git a/.install_multiple_scms.sh b/.travis/.install_multiple_scms.sh similarity index 68% rename from .install_multiple_scms.sh rename to .travis/.install_multiple_scms.sh index df06cca9..2344896e 100644 --- a/.install_multiple_scms.sh +++ b/.travis/.install_multiple_scms.sh @@ -1,8 +1,5 @@ -sudo apt-get install -y cvs -sudo ln -s /usr/bin/cvs /usr/bin/cvsnt -sudo apt-get install -y bzr -sudo apt-get install -y mercurial sudo sh -c 'echo "deb http://opensource.wandisco.com/ubuntu precise svn18" >> /etc/apt/sources.list.d/subversion18.list' sudo wget -q http://opensource.wandisco.com/wandisco-debian.gpg -O- | sudo apt-key add - sudo apt-get update -sudo apt-get install -y subversion +sudo apt-get install -y subversion cvs bzr mercurial +sudo ln -s /usr/bin/cvs /usr/bin/cvsnt diff --git a/.travis/.travis_ssh_setup.sh b/.travis/.travis_ssh_setup.sh new file mode 100644 index 00000000..8b560541 --- /dev/null +++ b/.travis/.travis_ssh_setup.sh @@ -0,0 +1,3 @@ +ssh-keygen -t rsa -f ~/.ssh/id_rsa -N "" -q +cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys +ssh-keyscan -t rsa `hostname` >> ~/.ssh/known_hosts From a5636a464f98de6a7fca4c36bcef2ac58392dff3 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Fri, 22 Jul 2016 17:54:43 +0530 Subject: [PATCH 183/219] Convert hg test repos into tarballs --- test/repositories/hg.tgz | Bin 0 -> 2334 bytes test/repositories/hg/.hg/00changelog.i | Bin 57 -> 0 bytes test/repositories/hg/.hg/branch | 1 - test/repositories/hg/.hg/branch.cache | 2 -- test/repositories/hg/.hg/dirstate | Bin 88 -> 0 bytes test/repositories/hg/.hg/requires | 2 -- test/repositories/hg/.hg/store/00changelog.i | Bin 715 -> 0 bytes test/repositories/hg/.hg/store/00manifest.i | Bin 571 -> 0 bytes .../hg/.hg/store/data/_r_e_a_d_m_e.i | Bin 125 -> 0 bytes .../hg/.hg/store/data/helloworld.c.i | Bin 321 -> 0 bytes test/repositories/hg/.hg/store/data/makefile.i | Bin 106 -> 0 bytes test/repositories/hg/.hg/store/fncache | 3 --- test/repositories/hg/.hg/store/undo | Bin 35 -> 0 bytes test/repositories/hg/.hg/undo.branch | 1 - test/repositories/hg/.hg/undo.dirstate | Bin 117 -> 0 bytes test/repositories/hg_walk.tgz | Bin 0 -> 2260 bytes test/repositories/hg_walk/.hg/00changelog.i | Bin 57 -> 0 bytes test/repositories/hg_walk/.hg/branch | 1 - test/repositories/hg_walk/.hg/branch.cache | 2 -- test/repositories/hg_walk/.hg/dirstate | Bin 63 -> 0 bytes .../69e27356ef629022720d868ab0c0e3394775b6c1 | 1 - test/repositories/hg_walk/.hg/merge/state | Bin 154 -> 0 bytes test/repositories/hg_walk/.hg/requires | 2 -- .../repositories/hg_walk/.hg/store/00changelog.i | Bin 1092 -> 0 bytes test/repositories/hg_walk/.hg/store/00manifest.i | Bin 791 -> 0 bytes .../hg_walk/.hg/store/data/_r_e_a_d_m_e.i | Bin 469 -> 0 bytes test/repositories/hg_walk/.hg/store/fncache | 1 - test/repositories/hg_walk/.hg/store/undo | Bin 53 -> 0 bytes test/repositories/hg_walk/.hg/undo.branch | 1 - test/repositories/hg_walk/.hg/undo.dirstate | Bin 63 -> 0 bytes test/repositories/hg_walk/README | 1 - 31 files changed, 18 deletions(-) create mode 100644 test/repositories/hg.tgz delete mode 100644 test/repositories/hg/.hg/00changelog.i delete mode 100644 test/repositories/hg/.hg/branch delete mode 100644 test/repositories/hg/.hg/branch.cache delete mode 100644 test/repositories/hg/.hg/dirstate delete mode 100644 test/repositories/hg/.hg/requires delete mode 100644 test/repositories/hg/.hg/store/00changelog.i delete mode 100644 test/repositories/hg/.hg/store/00manifest.i delete mode 100644 test/repositories/hg/.hg/store/data/_r_e_a_d_m_e.i delete mode 100644 test/repositories/hg/.hg/store/data/helloworld.c.i delete mode 100644 test/repositories/hg/.hg/store/data/makefile.i delete mode 100644 test/repositories/hg/.hg/store/fncache delete mode 100644 test/repositories/hg/.hg/store/undo delete mode 100644 test/repositories/hg/.hg/undo.branch delete mode 100644 test/repositories/hg/.hg/undo.dirstate create mode 100644 test/repositories/hg_walk.tgz delete mode 100644 test/repositories/hg_walk/.hg/00changelog.i delete mode 100644 test/repositories/hg_walk/.hg/branch delete mode 100644 test/repositories/hg_walk/.hg/branch.cache delete mode 100644 test/repositories/hg_walk/.hg/dirstate delete mode 100644 test/repositories/hg_walk/.hg/merge/69e27356ef629022720d868ab0c0e3394775b6c1 delete mode 100644 test/repositories/hg_walk/.hg/merge/state delete mode 100644 test/repositories/hg_walk/.hg/requires delete mode 100644 test/repositories/hg_walk/.hg/store/00changelog.i delete mode 100644 test/repositories/hg_walk/.hg/store/00manifest.i delete mode 100644 test/repositories/hg_walk/.hg/store/data/_r_e_a_d_m_e.i delete mode 100644 test/repositories/hg_walk/.hg/store/fncache delete mode 100644 test/repositories/hg_walk/.hg/store/undo delete mode 100644 test/repositories/hg_walk/.hg/undo.branch delete mode 100644 test/repositories/hg_walk/.hg/undo.dirstate delete mode 100644 test/repositories/hg_walk/README diff --git a/test/repositories/hg.tgz b/test/repositories/hg.tgz new file mode 100644 index 0000000000000000000000000000000000000000..1e88f1ad4ed068f015c9b5795c7201c725a53ada GIT binary patch literal 2334 zcmV+(3E}o1iwFS950X~^1MQm$ToYFw#{;5biilT11v`r2uoh-AnHf-_!2?Ca19dG` z!AUY9fsjBB#H&CNMXBYoo_JIdQCh*PA6vn73mzN-3N4D>jzP`i^xtOK@!}J z_CvzDoiDtZX;mz(94V z8W=@c|GE7k-S&qtlt}|X1KFd+pS=Bf1Rqz3t7+}NnChBDJcdy(bIM4 z(?5hFI{JrUCQRwy7~cdG6;w z-D{fPbg51;3jrY#NmfXtBAyFZbImNDNQXx9Y#xS(5`3Yk$2%CsA4aWzLrK3Kz50iB z$A2cw!YKV41I2;~qd&5{w{&d8i&p2qf8BCt!M4ITl@qHDZE9$p`q#~-B>tYE);|bx z1-Lkv5J`evggsq{-uXWU>5l&(Le2k;g(<*OgoUjHI(q;hmjK~XB9aix0fkH`CNl&C zAQABZDG@FKMEFXHLf+d}Q}hU0>wgz6&K2~$>()R1v%2XYrsn@f0Yea&$%P1r5Ag^D z;WC*R#7Fr&raRBwjo@<#7=hg}E(?I^Z(Wp%DZD?Z^)Hi4q=ccO!0#Uag)kNs|2GO+ z?GJ)sxLC+1Wbz)J1nTks5QxD#?N7b{DgSR2Ovs-OFfyTc|#OTgPoNK^NGyudZpe?Z;(g;*hD2I+>~rwaiU0 zYyIBRhGnH}3jV27{*Rp&cG`vxEIl@`0JJb;EB82Lj(Zf)FToe9jdA!rCWY6A{%G># z*S$I1p#9!HvP~OLg`ROMSaib?znj~iUX<{>;kUZh!+rfc2BRD1AaTRsl%x4=gJxvr zN^BYi$@Yyp^R_*V;(r(&|8I~efIj~ZL*4v8={zX^Zxmkpf0aXw)MRV?zloLI*U!oh z)$F|RaKFQ~=}lfqeT%wY9+f`4*o*!%Xhl1>Ixxk0%VP&23iv-A7uDFGeiW^Ba~l2RfklC)QjUeIxM5(`y&3D-`xXr@0+2F{1OMs0}|hH$&*UWd}Qd zv{Q}bB)+x|U${=&Xrvgji~%g-@!K0yMtb)o(C|anO*7NQ=XS=dN?g3)vbhbInvgt||69wFa{r|4lOb5r2-btt z8`1gA4{T<%SEFn{CX#6ftz&fQ9AWf5b|G);Mc?+@TCsKx1Q^$@0m(J33z#S zm|$X`R-iU;na6157~CSk({|TTyCG@K)z_C#9T$X&pv>6xhbPNTlRW%h#y)Gjx#;44 zE+cQ*?8hS?95_`Qm-wllvi3>&wXc?LI;(JA$lxX?4EW3L5i=`2Pl!$v!`Wk;+>d=1 z5SUCr-8GX>4l6mnWi@V3v6y{GInNf98c{nAI>os5;2D9J1nHg`dDP{P)1sKB0Hcf0rrq zjGA@Mwx1-psxeetnfPJrVT%o0rLW4fFBJ}||J^3#U3xu*8ZH0N!{xXE7J=`+{$rvj zNUi^jLHG9WI-&2GS%ALy9|G#e{}C3GivJsj*WUM?z9&NnZ2E%uqeu;S_i|FTlwGG{-ZMY+x{K1HR7z3<-93ZhNm6M5MEwX(wCOuU>)6QM8`Dbyt)QcjXCVii@#X> z&$&C+Li^%9u3yPDotY4+Z3?5r%koQb*t*+C&%B@&%-NX2t?CO+Xrdjo__nB|VBWc= z7h7|;m)>vt3bK|x3Eow+|HA4`1GvNX=aqf@bDr#WjAudU`a-r}UfjbHtNfXs$K#F; zy&d?G+jwi&`XA0#3FgLTH`HA3Gxx7U?_@3-v-wo?rz08FhG-Kb(p~?WC%8Sg0?-@( zN0_?ve-uP0{TqeX`X5iGS(;pp{^LTbixk1a?Jlj=H9Q~ZtQ)Rg@m(*EO7|@-I_7^# zRD$~-2%b%r~&A(^TFlFRcqkbxix1_uNgQP)35FW$}3JdBX zAD~zNnC|{R1SX49`Zorz_3uHZ$?Dgp8vU0A+UGbsPa4%+%s&#nu`R&7{$^>{%M}X+ zLK#5*;($yT7A_)y*YigJ4-Xd!xwu>?5xdZRvJV*jB4$Ycw0b#(D{MHlACP0UVB%gjjy E04nYu_y7O^ diff --git a/test/repositories/hg/.hg/requires b/test/repositories/hg/.hg/requires deleted file mode 100644 index 57601b5e..00000000 --- a/test/repositories/hg/.hg/requires +++ /dev/null @@ -1,2 +0,0 @@ -revlogv1 -store diff --git a/test/repositories/hg/.hg/store/00changelog.i b/test/repositories/hg/.hg/store/00changelog.i deleted file mode 100644 index 154a1df5b37d468d26d1d526fbee6f0cd7af46ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 715 zcmZQzWME`~fKnh;24yq+hXO_c*}l)`mfxCn?Byc0Yp!1$`&m!I)PU%UIijZ=xegf! zFdV3knAFIzg~{rjYC|4(@92Xx`X7SPbI1w%JtMc zj8*@L7GJ;9ws&vEfn>EEC<5Qr{NtcI%Y@Zhr?5(bkxCOD_P{~diksDJgAEc1RzljoD}*6;oPT*4h} z&2=!@4J2m*F%uLsf?Vj182mFisSVzsucKN{j-)ldQ$tjE2 zQ_7b`kahQE-+Y6!KDilI%zqW`#l_mnT~|!x>9CWTEi5ZE`TLFA3C=3<<~fGT8t1&+ za-ON**7r~2=TG-Tk1tAA-4pBcR_giUt@oO{?R~G`dw2d?PfXXoQq2(6wpYfe)^S9 b*?E_{#s043X`fc~@BHc$NBCd-l$ZzrN}&{6 diff --git a/test/repositories/hg/.hg/store/00manifest.i b/test/repositories/hg/.hg/store/00manifest.i deleted file mode 100644 index 1716614175f92259a4ab2ffd8a3e370598cd5226..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 571 zcmZQzWME`~0CON^24yq+hk_Ss98X^yopZIDJ>NFQ*?K}@r&0n;4TvtyNX^N~FV8Q^ zNzqGYFgCGFO))YwFf%q!GBPkTN;5GxPBJn#H8-~~O*BiiNH#GsNJ>mHsknIm^R#Yu1v%Grlir0pMiYvkoR-C^CRRg9f=E$D1 zvK6ysq~3bpWoEJj4eg>;_tm%6WmruHdL9;o~G`Q>C%$?o6#&-HV!SZ)4pM;6P^)KnW&Xl~F#Ul$=4J9h(@SfSod)R=7#o_uqwPh-= zBH22;&F?j+{cM<+^51MHa`PfD;W+v0HOUG>B#8`!x{c6@#P{?Xr+ gtiHB_X6=5a%_7DV*X{k!@4jq9zQk+(;sw&X0nCxgF8}}l diff --git a/test/repositories/hg/.hg/store/data/_r_e_a_d_m_e.i b/test/repositories/hg/.hg/store/data/_r_e_a_d_m_e.i deleted file mode 100644 index 888bdb0d9185b24dbe53d47c554879bacc5e1e4d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 125 zcmZQzWME`~09zns17$P)hk|o)%Ih^Xt);)8N?TRm`9G55#r-o-HDIbVBqOs}0f-V6 ziZgQya#9sCQgd?h%kztJQWO#k3UV@&6H7Al^YpkpOF+u9N{dT?YD-d!OZ2z^QTQmF diff --git a/test/repositories/hg/.hg/store/data/helloworld.c.i b/test/repositories/hg/.hg/store/data/helloworld.c.i deleted file mode 100644 index 9214368d72b708de86ede1261c9c06250a35a289..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 321 zcmZQzWME`~0B<1W2W2z-hXRv%mjsfl6_UObZz?TsUAE$g!>)}mH6XfT&gJVtA3V;U zJb68kkztx z7dJ3@bb!>sLB$-^(~f*i1|lsF*X{nsaM-VNV)7MML!B=SOL-QaJbgIez?W~+Hq1El z?0=7;c=5aR*|!!QtM1}V7Fo3Coc5tT#Sa_o4rjL=aq!*K{PMKGUJtuX&Fh38#>rb~ iiR-`Ew(m-Yf8*-cw{A20?-zc&EL5>~YrVac>J0$IIfxSg diff --git a/test/repositories/hg/.hg/store/data/makefile.i b/test/repositories/hg/.hg/store/data/makefile.i deleted file mode 100644 index febd4591285e70c3ee3b3638634900a166a7f594..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 106 zcmZQzWME`~04*Tp1!Xh-hl1v;8z)QCGiT`iy>TnWQ**^#eaBX)8ZcEc$NS95jX@_o o&YnD}e_sET=fg)%8zvt8I%%iH<;jypOFmCz34F@<+DU2}09}3HanIsvnN8iN_DPuv07W!9}RH^EFh18p>YXN+{Uv^ogYZE1-Ux9__`LMDdovX h&B@6x&o9bJ(MyKu@$xKF`vg?Tk(-#EnwFW93IJXm7+3%R diff --git a/test/repositories/hg_walk.tgz b/test/repositories/hg_walk.tgz new file mode 100644 index 0000000000000000000000000000000000000000..b7cdf274302080ed8e99d6747a04ff85c646f443 GIT binary patch literal 2260 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 bzYeD4_ip=B&Cf-uoVR|P2UZOwN?o`B0tsWq diff --git a/test/repositories/hg_walk/.hg/store/fncache b/test/repositories/hg_walk/.hg/store/fncache deleted file mode 100644 index fb1271bb..00000000 --- a/test/repositories/hg_walk/.hg/store/fncache +++ /dev/null @@ -1 +0,0 @@ -data/README.i diff --git a/test/repositories/hg_walk/.hg/store/undo b/test/repositories/hg_walk/.hg/store/undo deleted file mode 100644 index dee7b9315f64ebad167f40ec4ac679233d810f17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53 zcmYdEEJ@T4a&>g^b=AvcFflOVGBC(Z%*#wmEiM5Hn3-Du1(Guo^U_mu^3#DLmPVFb E0GtaB`2YX_ diff --git a/test/repositories/hg_walk/.hg/undo.branch b/test/repositories/hg_walk/.hg/undo.branch deleted file mode 100644 index 331d858c..00000000 --- a/test/repositories/hg_walk/.hg/undo.branch +++ /dev/null @@ -1 +0,0 @@ -default \ No newline at end of file diff --git a/test/repositories/hg_walk/.hg/undo.dirstate b/test/repositories/hg_walk/.hg/undo.dirstate deleted file mode 100644 index 867d35c180e57603c9f7c2e41c10b0e04ec8ba97..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63 zcmb<3-ud@wR-S2DsYS+x{)Ns@UaUNCB{Ee!&SB%pW*6D4zP_Yd?Q2Ebav2yJmoP9e SFnM-KZvxV6L9UK2zODeNwiws| diff --git a/test/repositories/hg_walk/README b/test/repositories/hg_walk/README deleted file mode 100644 index 17848105..00000000 --- a/test/repositories/hg_walk/README +++ /dev/null @@ -1 +0,0 @@ -D From 1f04ab62ef4b20808511f25af69da50538c094d3 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Mon, 25 Jul 2016 03:32:11 +0530 Subject: [PATCH 184/219] OTWO-4327 git and hg must work with branches --- lib/ohloh_scm/adapters/hg/commits.rb | 42 ++++++++++------- lib/ohloh_scm/adapters/hg/head.rb | 3 +- lib/ohloh_scm/adapters/hg/pull.rb | 3 +- test/repositories/git.tgz | Bin 20480 -> 16426 bytes test/repositories/hg.tgz | Bin 2334 -> 3291 bytes test/test_helper.rb | 16 +++---- test/unit/git_commits_test.rb | 14 ++++++ test/unit/git_misc_test.rb | 2 +- test/unit/hg_commits_test.rb | 68 ++++++++++++++++++++------- test/unit/hg_head_test.rb | 12 +++-- test/unit/hg_misc_test.rb | 4 +- test/unit/hg_parser_test.rb | 38 +++++++-------- test/unit/hglib_head_test.rb | 6 +-- 13 files changed, 136 insertions(+), 72 deletions(-) diff --git a/lib/ohloh_scm/adapters/hg/commits.rb b/lib/ohloh_scm/adapters/hg/commits.rb index ac3a9daa..7ec6b821 100644 --- a/lib/ohloh_scm/adapters/hg/commits.rb +++ b/lib/ohloh_scm/adapters/hg/commits.rb @@ -8,13 +8,11 @@ def commit_count(opts={}) # Return the list of commit tokens following +after+. def commit_tokens(opts={}) - after = opts[:after] || 0 - up_to = opts[:up_to] || 'tip' - + hg_log_with_opts, after = hg_command_builder(opts) # We reverse the final result in Ruby, rather than passing the --reverse flag to hg. # That's because the -f (follow) flag doesn't behave the same in both directions. # Basically, we're trying very hard to make this act just like Git. The hg_rev_list_test checks this. - tokens = run("cd '#{self.url}' && hg log -f #{trunk_only(opts)} -r #{up_to || 'tip'}:#{after || 0} --template='{node}\\n'").split("\n").reverse + tokens = run("cd '#{self.url}' && #{ hg_log_with_opts } --template='{node}\\n'").split("\n").reverse # Hg returns everything after *and including* after. # We want to exclude it. @@ -30,9 +28,9 @@ def commit_tokens(opts={}) # If you need all commits including diffs, you should use the each_commit() iterator, which only holds one commit # in memory at a time. def commits(opts={}) - after = opts[:after] || 0 + hg_log_with_opts, after = hg_command_builder(opts) - log = run("cd '#{self.url}' && hg log -f #{trunk_only(opts)} -v -r tip:#{after} --style #{OhlohScm::Parsers::HgStyledParser.style_path}") + log = run("cd '#{self.url}' && #{ hg_log_with_opts } --style #{OhlohScm::Parsers::HgStyledParser.style_path}") a = OhlohScm::Parsers::HgStyledParser.parse(log).reverse if a.any? && a.first.token == after @@ -55,7 +53,8 @@ def verbose_commit(token) def each_commit(opts={}) after = opts[:after] || 0 open_log_file(opts) do |io| - OhlohScm::Parsers::HgStyledParser.parse(io) do |commit| + commits = OhlohScm::Parsers::HgStyledParser.parse(io) + commits.reverse.each do |commit| yield commit if block_given? && commit.token != after end end @@ -63,8 +62,8 @@ def each_commit(opts={}) # Not used by Ohloh proper, but handy for debugging and testing def log(opts={}) - after = opts[:after] || 0 - run "cd '#{url}' && hg log -f #{trunk_only(opts)} -v -r tip:#{after} | #{ string_encoder }" + hg_log_with_opts = hg_command_builder(opts) + run "cd '#{url}' && #{ hg_log_with_opts } | #{ string_encoder }" end # Returns a file handle to the log. @@ -72,13 +71,13 @@ def log(opts={}) # it returns everything after and INCLUDING +after+. Therefore, consumers of this file should check for # and reject the duplicate commit. def open_log_file(opts={}) - after = opts[:after] || 0 + hg_log_with_opts, after = hg_command_builder(opts) begin if after == head_token # There are no new commits # As a time optimization, just create an empty file rather than fetch a log we know will be empty. File.open(log_filename, 'w') { } else - run "cd '#{url}' && hg log --verbose #{trunk_only(opts)} -r #{after || 0}:tip --style #{OhlohScm::Parsers::HgStyledParser.verbose_style_path} | #{ string_encoder } > #{log_filename}" + run "cd '#{url}' && #{ hg_log_with_opts } --style #{OhlohScm::Parsers::HgStyledParser.verbose_style_path} | #{ string_encoder } > #{log_filename}" end File.open(log_filename, 'r') { |io| yield io } ensure @@ -90,13 +89,20 @@ def log_filename File.join('/tmp', (self.url).gsub(/\W/,'') + '.log') end - def trunk_only(opts={}) - if opts[:trunk_only] - '--follow-first' - else - '' - end - end + private + + def hg_command_builder(opts) + after = opts[:after] || 0 + up_to = opts[:up_to] || :tip + + options = if opts[:trunk_only] + "--follow-first -r #{ up_to }:#{ after }" + else + query = "and (branch(#{ branch_name }) or ancestors(#{ branch_name }))" if branch_name && branch_name != 'default' + "-r '#{ up_to }:#{ after } #{ query }'" + end + ["hg log -f -v #{ options }", after] + end end end diff --git a/lib/ohloh_scm/adapters/hg/head.rb b/lib/ohloh_scm/adapters/hg/head.rb index c65f767c..4465d446 100644 --- a/lib/ohloh_scm/adapters/hg/head.rb +++ b/lib/ohloh_scm/adapters/hg/head.rb @@ -3,7 +3,8 @@ class HgAdapter < AbstractAdapter def head_token # This only returns first 12 characters. # How can we make it return the entire hash? - token = run("hg id -q #{url}").strip + branch_opts = "--rev #{branch_name || :default}" + token = run("hg id -q #{url} #{branch_opts}").strip # Recent versions of Hg now somtimes append a '+' char to the token. # I believe this signifies pending changes... but we don't care. diff --git a/lib/ohloh_scm/adapters/hg/pull.rb b/lib/ohloh_scm/adapters/hg/pull.rb index c8a25f11..ab3a4421 100644 --- a/lib/ohloh_scm/adapters/hg/pull.rb +++ b/lib/ohloh_scm/adapters/hg/pull.rb @@ -12,7 +12,8 @@ def pull(from, &block) run "rm -rf '#{self.url}'" run "hg clone -U '#{from.url}' '#{self.url}'" else - run "cd '#{self.url}' && hg revert --all && hg pull -u -y '#{from.url}'" + branch_opts = "-r #{ from.branch_name }" if branch_name + run "cd '#{self.url}' && hg revert --all && hg pull #{ branch_opts } -u -y '#{from.url}'" end yield(1,1) if block_given? # Progress bar callback diff --git a/test/repositories/git.tgz b/test/repositories/git.tgz index 5ff058f5b2aa659fb90e47edd75be665ea02bb64..392318a7f5a41e7f0a4eb43ce0b1c013b949167b 100644 GIT binary patch literal 16426 zcmV(+K;6F|iwFRw`H@!u1MHd!IFxPM$L-k?$`&zXD`EB-JCO(}k|j0GYOFJvA!|z6 zh3sT09*LB#5@pGjkgXz>HKAl5OQrfoz3=mWJxh5e*VWXZgaTDd0p4p#T+0wbVM2m%TO!x?}eAOr+w0Kk6sz?S7kp`u*@ z00y)Z-s4;M{ngL^LuE(juVnXgli>UKBk24=AUJT1|7z%0{!S!2%1=sy74Zkc5l}b~ z3;{#w{K25L`d=M=&EH^`j^2-tu?!dvh5i|T5R4A{U-b`K<`09y7y!T@Ka}6=|2co) z3Izb+2rwuD2?XM>I1n6(hapuk7!?c{j)4LpDi{I*f<_P!cqqUDO(D4e)IVP|0U!_z ztO7zpAuxa<5CH^ouK4$W@hT8F9EU@o5lA=zhk?Kd^lgDaAb_w)JQ@hY!ayo;BnAY~ zp_2jZArW0Z$8{l5mr*%@lGW2$|ps~ z0)=B#&`2NwkH*2l1hfiNg}zM_z!)R~1H@twNcyL+*zcVb6b$|6q)5)r_Vg*~;BcR( zWbcFrkX-PbD~`P4l={9QLg~BIH`o0iYq`9vUy_FN@2=+W*Vp^ME1vKZOu+Z|e+ZC% z`&$2B1^oekBE8yvXcny8|HGjO*mD1e(!0hQ|JBf+^8d%?_9J3^_J8m{^?yJZ=vV$Q z`q`h(AGT}>*ZkiqXvO~T=bIahE7}E1R0Zg|;?Yz*?n{qd_F(@BX65hZ`0wgZ>;H?R z`5`g>;`|2$!9l<2|1bz_?fkbYTJ`ha-#y_qeWgFBe^;J2v)$acsSSPw& zR{dh`l`SZES9-#cF!VelyOJF6SSmg5h)yJ;GSnM_fpCn8mu9{*o2F!Xc6t{I6R zqF?J@*VM$s@BnI;p5Xx#^W8r*#^?I~#`zxz{_Xi60*0*B|ElP}j5 z-J>%a9_g*V&*B+17au;^1?Yzg$Xv5YbmqBip!u#^GutYPxeUVZR@6AhNi4pOobM5}wUM9(k4X6SB5XQ0Ogs~?H7IU^ zFEZGPwkOw!?+#kRRzG(*{B#S|n$>ILELStj-qOE&rT#nhyZR@iv5r5u1APDU9|#P* z*8f*Uf6RaRiy{yUM&b|{G!_ges6cTlXfPHA#UmjgJQk0`fM7Tz458C&V+TVXxMf-Ggjp!F9`ino6%OfSAQH_%c#Cvi;Gdq!sJ?Z{laR6Kp zlX){fCbf3m8~x7Fw*tyX=W6ctC74yQS~Lw^_t;<5{x*edAgvNTB8`f)XLk@UiY;Z1 z8@gk;ohUVOHWIF_9u?@4UOANKUXjkN(ia#+$@ne;1VJRL~jjoa|Db zP??$Z^gSGP)LT7uAt?1N1NQzE{2oCa>mRzyi8HLFvEKq?Yq<3nTt_|Q^@F?ka;f1 zXIT(im57@lx<5Z4VL2l`xp!MHvq5pVM} zvdLXz%L(6;97v@HjpFkfWn5t^yqg4xQpXUc*gEA4$?ctfOpv%%Kf^ZU7HSUQGrH5!Da zme507&0YF)jE*n2Hx|d!@Y1j&I-gD&Ha1>$YN8-}4Nx;HOIYnE(Y!$uANgccDHtxx^Ih z5poN(oEL2B2xuxV&dw=ro%Dt)7c|bk|LA?Fzgyxx>eZwW@5`w{>()-s;X5T0V}hhh z0>m8!#&4rB>rn%R_&#B8%7W*jJ@QreCeb(}%cr>ohVcT*@WS)79OLa7j1q&uR;{O0 znRN>-&g#T>gWTdi+d0KBucFho3^+&1ED3p%$3mTl3zjJ7G+ta*w!bkvD=+s(_9AS` z&}I-);+n;L=+1{|A!X0Lh?!tHji-K=k8W;vjI`Xsr_VKYq+Y2#USIshd)(tD)wHQ9fnJ~m~O%Bei zB^r`6c>ofhgNnUoCfR$*b39~ZkJXIrFVbEpwZ0M|H#{okuyiSK3ZV)}wYwigyX{k` z6sG#GU~ zd)8UN&5hWQKIz6>;}KYVO)-VH_@c7;$XQ|H6=`?t9k0(eT}i8(buZjIBPSnkqF^Kb zT7JH6ej$}ST0y-}NK-M3uy!14(;{}U#p-Is3DG7y-qN-SaVm6t9FplSbU!a3T(Se6 z2X;ImUJKzs+CDCs$J|RcmldZKipMP4PBcmvFU*M@I)6xmy}@L*QRk)Sm2A~*8<*bH zMpfJp@U>%lK4`2d63yK+kBD3cO155 zT+C&^_Tj3Ew=FD$zDu*ams#w9en;ZBQWpB+Ey3 zW6-CmLkT{TEIdXwOp&z zfPtFSGrky=3$1Cn6S1awoPpyU4pZS*Pq*$KvPqvyzS>Y(N=p*VX<}7eZ_1%46{w-| z#0Fm-w$ElsxO`9RcpE_bt9SMe9A_lS=xZKIZBYW+n+}Baq$*sI&T1PdSp=tMTiay44kF?QE~{*BPmB>0jQemN zlXT6%H%XvtvD(+9!3fd5H0oM$B#+NJ?q&bur{}sw0;PR0^CIpqQv$t16HRkoOI+Vt zXQq;Pt45Eofob-rhFQwU0x+n4|IJ z<(-$@=S}3{)=`|^@6Jk5x@+kE}GlTv1!>tZ>i{97=U#rVt(f> zxg%z5RoPwrx3cmTLW|qfX0E=`5sm@7%S>7|hVWJStM0>{IVM|8lXdNo?C?p_%x+2! zE~-n}65`a+FR~XRMl~mE-Mi>^oBN}_u&Y1@7L_VX^?$^QA-qIKkfLQyiQI0m&DiA6 z>IDE*mO4tRUAdIoDH^6617S-eD6i~@-6d$o8w19EBg`IsIZN&IB|0I!?vnW>R=ImO zXYz_n9+wsu^$6k(7#MZJ`P+tgsZ2AIg^i2-uIHcJk?zwOu?tD!zG=OcBBSla+{(VY zfGN!T0oQfO(+j%}D#KnWIdr&b+k8+(=z!;?dq13s8i}$kwPCw`3s=e_e-tu3&rZ+zXD?KBg7!Aj#YC%&?-G1l!w zm6uy1-gHm<&!zo(yP~(DeB~> z6!UxRkaC$g+1h<YU<_1#TMm8$i+5C@}xIw z#3do)2b>;s1g4>RyN84Lct?wPLaTOjM3^jq3=e9TnPeHI2VUO1&G1r9zr`_b+i|ZE zv{=&X8^RQWE}R^rhuUG8{V7)e!`_#`L)E>Hk4iD2Qd$&UTL^=hu|`?4W>2Xs88dgx zWXw!6V_%|DQd;n~kya_Gv$t+u2RZ79nB-aBJS-nZWOSH9o>_w{@}=QDH9 zJ?A;+JllEBa?hbv=auc7?LVzf6`i%(m@H|4^D60H&Yt#ELj$WM^~R2{{u7IqWtbIoM4mKeDRd{#~(o{wNXNHs!#5Em6Vyn6dJ?TKaCgb;xbIv=9e%GtF# ztidHn*af6mDG243zNo9C)VUu`uv=lFduO$ggIq+_vxq`z^N(F0DTd>>P|u9Bk3Q)l zU9r1SMO%HGkD|_}n2lo&Ek>(+j%zj%ZZk455WYd1Cb7eFN8r_sGs-5pm4?^|R!XmH z;U9PJ#pYGvW#w0y_ogdnWZjxRH#cyG<+~#9=`+rzG1SCOU3W)xncQ7z<2$iCA#0ER z!Gcp41==`WK6Uq9zbK#Hs6cXh0-myC3t>^-SI6b+inK(}6L_CwxzlgOld1Ce-Wt^5 zHw)CQdwDTVbX#i1pa< zycjEeR$yjeH9lz0o)aBv^17m{8&^ax$s8ALX&R~W=FsNs4Ig(UmXCLP`((Uc=yAQ& znB4|m8>Ckn>Cukprx4ek&eHb`FT1z1^!UZ*of%Jdb!DGE`NFDLI3)MA;sIODDNgO0 zS0qc+^YhKu#C*1~Q|~r3=~hvBR&_|uYvVDyr)akVjt;>8EPal2Kw?-JYSYQ1rgCe= zvZcy*XIZ26X_!q^-27~;&BCS?NkNu(VBv^Py zTF!i6Pc{>Dv>#IfIu;AG#4SSeGoRbroHUuAeLy%MtFdKE#zpe!S-#YMT|{b)lgXBwmLY*b3v+W$&)B~wx7Va<%R|zEp`u~EdxhMZuO&1t+L>Fg(Q3)|2=|Xt@C1WX!uRpZ zo?CZz(#Jcy1dlR5Di<0o!F;tMY)kh}(o3s2KdptqhbrlIM~!>4i~2QYGMg$;M>9htb5#{3dhap|07uYFnkH zw-#>fqD+~eic?DRzPG*zb4uTH-j>dMX<>f# zy#_{6ZOf^NmZ$%CrySze!`w$tI%>uDaATLr&7@WG#QVl#@06E#JS$5SNWL2W?BJG` zjjh|B>h8{%=$`J!OuX-sk#A;i{Az7gal>=>r7x)l-aWO7Nv#f;sy}j%>UaX18aek? z-I(_&ddl_j;>9mMINF#`TX%TMQL95+*n zQ!g%FZb}F`GW|}(b4=&tMyClBsZ|Gn{nt+`tAzvFs_P&4T z>V%`U?YreNL~5)Y->5JTh49gFGn?|;O^UUj#uL-dH^`l|Fzm_*U1gS|U%fqZnvRyU ztaZ7a#l-@*Oa+heKEkPA+NR@nPPdRUzoSvmn-PiW(lAw#P$n#1Y7z9fMn#OJ6JB9A z_ff#OWhde-_~%jb)3L43R=k)b`QYov$A#-0R$Fj(2ANn`6Ao3lo7&6D8Tx)sG%LVH zON<{sb>s8nb`35`zwyc~VMBnHHCAnyGS0pOpisS)Kb8Booc< z88Q`5Xz4$-AZ~jlCJ~nHbahenn1)j(9XQ1|c6n>dDbcSFQtU6wG(_=0%-JI~DgT^1bW2?wYyY;NXiX!_; z3#%w?`slQrsqj~W8L9Ch_9m^gPD>nqo85^Z%PF%ivNBVaym9gwZ-bxUwe=-~7E4QE zFPm^ZPyipVF++<2+S{l6g(oi=cq^K`*;{&U&#o^?3^OIc*Df~UTQm>w zp~n=|t~<5I*5&ThouXiJ1zXeL$h5UC{*O;Ir2kn@AtL8ZnJ;Sl* zSV(+X*XJu(*5UWI9|Bz}Ri{MLaL(9(D@=&w7wca-GHjwyAB zjB1#(NK@X^T;gNQ`sGVSJfzlb2+n2NS2iC4B6?k~Y}8z!u+| zA-i^O4QzPewRLm6{K{81T(1V>x2!p)Fzd5o-Qg1|=d?0Y#>Qoy*tz9$lE}*wOIZ)^ z$pxj!XlR)qzt>f?XiK$OrF@RWsY6DK9DS0jahRG2L;cg$7InaB-&$d;OYv^`(kt<2 zrxsIQaHd2YzMCA2=e$UEa7yI}U9e7DAU(b8sn^R>^W>`KZKb6`l^SLlc3*ahk>9kk zdsmY}?3ZHm?EyzJMfP6umw0^KB7gOXh}En~F~_?_%vnpOUUa3;G`G1?8Tqnws|)%` zqJ(_uCFLUtDts&I_mo_UT*Zj@Rh?uXa!r{vB~0XA-kpG|JD)XP356Sqv>os;H1;}l z*2mQH*tUcC_o6SyYlue4xXn-`-guB$eREBU)-3dsh?H)ITN6q-(^{jLQ**LLf5#u6DZ%S&ClIvbrXGz+*iBA8rgXZa)X&>fsiZRB z>@u^_eRt$l>14MYyr8_F-dQL8t2!sM{i&DdUMEc`%K|%;EaW8Nu&&Ydqr${ z(Xp2~wV5J7Q$m8__3sY zUohq{EIqf@xHm}UFWzWdn7P6Cn)MP%=Sko^+fAn!1s?^DOwNckozZ@y!Z07}`xeW* z>5QKmSMmJNlBJF5vs^YiJGcu~JDq%DF1>M^*PQ)59{$p2wb)MS?+;69JzrB2b>U;S z=Oj_VwSSZw95Ah&%6f8Ofq{Is=GKOt5@dXBeSo7u>zJ2nveR`p7MrADt%N!0=rQ!$ zAIv3+rub-U2R$sCJn!}PbM9v?(!IzlqQc(iDaFN0CO^M_Kxmfh=fiWa6ZaZMr*1fR zBezGe^v0In=w!R>jyB!tS0|*HRA!i2&3m5pHur^)er~5`>~hNe#o@>2&bpHMw65og z@7V{hbXM0LIz>^#GPEV}CZL1Gap*7nVF_{qUU^4gz2q=QL@BW8)+Q|}pu>ZUy#Hn)_O&^L92vN{RaE{a*DnphBcRzB}=_LcNKS{n*C6LuuV3$<+V zSJ}TSdiwRHem(Eo4_>JAC%0{m-Es7R&?#5F+T1Vt)91Q85@~IHhRe|DX>Mu{B`qTOo1NJ>>mbZNA=H7jpAo_-<68vbqBC zvxyTERV4+Q_Ds4wc1}HkwN6XI;mf8KktWyM3n`x`E!Zm#zCJr?16hhW!z*~sHr17O zLFH{JZd{xHSwlq<>np6O`V)uLRs0D8tUX; zNLWd>aYZRt7OlBAS(mUm?>V8m^&~E>IG+saEIC zi_mzR7HV2>efQiPY=Pl1tL5GEzM8K|o~4x}LzZnrjTP9b_T65SQS2TO)(KxB=Q*0uF&mTEDCBOJ#e7jm{ z=h_`xa>^wqu5J|BW70G}sz_)Ipm*g!M=I(`-XGn*_xGClQxx6u&SvhsaUH|yo|ShH z&wMt{e__q}KORp{;CrheV*Bo`p%+!Rz11}8m3xec;n(P{!nVy@!Xx<@sCy@j<(8E0 z3QFy&%@&#}m&&gv_I2Xf>TI_!TKgAw@h@l>o%V6ohaTzfk`I@sZhUlBrtST6U!vKa z^`Q^%60n9VCFXYO`Br8eDC&@Sbl>V#wn$v<)@iJBdNkHU%{>1ZAe91LSqcsoozC1LMNqiFdpe|heFeRt1 z*1LI)h5VM_kMABlj_RIYi>7uq#e`-%_Jv2iUAdYVgU zXys47eCQnJGGfC!aUu5X-VX0B325AP@}f`t#NNP&#gp#F25@HVn=56k=bS@DK7!z#h3KDdU~*cp02&{=?Q+Q;izI@3S<9cyNsSa56X zhBQ;v&VcM{b+P^H-+Ee`2*-apaN?X+Vf|L62V=ilKR18zT!)LV zO$2=?ch`$oHPX5|E%9RFQ#a*(3Y-@ZBDm~P&@{_1oc~3oC+hQ0b(0nHU(_F7FKbgL zR}{Hv!Q&;*GMORI3(jV#-CkFnPXOQdqH@26oVq&JKVf2Ff%0l2C^Z^jh$=;>ohMR%T0t*940R2x%OFRG70?b|43a7oBNVcGU8 zBJ1rY^LuqFiQGp?weyKPD?}bHyMNz>AgHynQ`AjR{p*!Oe^gV+So!Fk7b3T=WoK7O z9*I+k7MOxLEm5|Dka~)~xQYBG^A<6@oZmy~UO2J6Y%LgFaGnsao4)OJu*t1E*;C>w ziAnZ7LgQAh+$hMx;r3hTe_r0XTxs8$TWe=}y^85rY)jM-Xfe5R=CZD4c&}f_nNa^j zS|O+{JlRN66 zy@(o|X*>#rN8wKj{+*@iJN@-3UqWtI?8sVk`V8)2Iy2`8yIj2VGh+hw&`Z|T3rj1p zY=>F*UVRl-xDUu>o<3oX!FGTEGq4c%Ee-nk5P-4-Q`Cen>S+}+}trJ6b^-ZJ|>LepAcWT zLRZRBYLSfmBAFc7MGG``NYQ4UDmo%utK256QB8>Y5fqzIC|C3?D2n2zj2k4?6 zpo|yE@eO)RL(O+gzOPzk%XOXH~w~G1J6nrL#6ku5@kLHhGRk z5kxn=^cHC$y;DuPHZ|`R9nPG|I3ew>58=Off8N5DP5f~cVP3*tW`CLCuyx{*V-TMF zMuVmTqZL#zx!dnaE#?k|pfqi!H?b;heTxK>`HFxqI6;NkoZDSn-H-eLn@?_5XO>f5Z1* zYPiw;|04p!@n1{JgG?Zj$R0$Znl>Is#u2a@SP#e>)YS065%D;64>b=Q;pfZv(f40C zoZ8UuzwlVxsQ)(-;LoR|XlcDn4SUgD?dQhLVJYYl-LjoGb#toBn^AuK&Nlclr-%{%7sK z8jkz@uhyvj9|;(a|2iZPtK;E;C8?7%@i@GPwg*;+074ujkhFKEo z|H$`WgZYnzhW~1#_J1V6pKr;XLR$wlcN9u6jj#PbU7b-FVfaq}sdO^qzu@~{-01xu zBLe;WCxL7ti^}9s8T4OW2F&2UI{!`WyYt_0c)0%`wg0~#meJ`1Z;%AAKqiAt8Jf90{S{qXngKUNDj z>i>@j^z;AsT>XRqV*mg0{6DQB_dls?XpP$c5djuR)&;&h_I=d2|68D6|EYA+?-KAI z=|B8`K>x9@{l}`0p8q)_u-L-E7{y&rAMdoQB~g}Nt-S9Sg%aRH&2xa79exaj8vBA9 zP>I8?=b>RKqI%L9EU*u^)2^;5V~D#ceZM?>e&6D=AP&2(H^JD}Zl#5d8G>indIb)t zm)@}JXyYBAj?LNx_2+nkhTzE`Zru$fL;-0uh984PBVmYr?Hd+f@DO~K!>%6+coV!p z*uVZ$It2{D!#C_Y=S1YVy_}(3l-5xN#?iN?E3z)!W6eNe>$<#um3~_ zolN!o4HEX_@gE+iG1ULV;YauXj0iXrA%%5C3l5C`pfR2|f#VCZ*i;4`&Xh9DG3w|IIXl&?-#_%N2Xpj@(!z2+nAiFP_GxsEUK$?4!yfjpd4~qu9 z{Xd=iEl37AL<)pOX^`78Uw62p>*u4Lxx*Sjn(Nm{BP~TLr4Miup#{A`mM8rDuk?cY z_5b%={fEFm82_oOkFNiZ2z<+b4&irP0{su>f7S4#PG~Axc;Xx z^!`UYUTt*#cSPW4uXP&L|Nl++R{wwb)sG1L1OHz`bJYJI5g4BTzwGKq1pYq%HPkdl z_y3Ft{3ZW?(VFlN`+xj*{KspJ&i{@G46OeSd+q0FxBov5f2se!Xdv+S{eMlY*69B4 z5rI+v|KAOR_J92HecyfXPu73bG)Dcuk$`Xc5Bd{nJ|ytR+5Q&%$o}IrzZ?HSe@E^A zNPrBypIe2-R)N>}*?@`)gF^vX@E@KmsK7UM>whOAXc@qYN{4cAC)#m$PflzsQ{C}fjkmA8&L3}^GbkGcmq^25Ww&O{0MLa1Mp#kNW7vh zlzBeJnL%)c|AdZqV?&@{|7{&C%vS%NO~8L+{Rgj!(}e9m9y>b!J0dXZ|NXn6U;il# zhSzV}0Q3+1KdjcM|2HBqg#SzysKNq02<%_!1OB!Dr>=&@YYtui!)lEBe3}yg}>Pg`M3PeQ!3$YEb^r2H3fH7cB@Fvh1P%1Rj$Ad;?Q}pSeKL-tq z3U`mCzO<~mG#c{5;H{g0w5*IYpbuctkQYWr3vw7tDp6m0&?2)eRvHZ=+ef+Y+#w+Z z*a6-i3>uXP$siekoe_65nTkdep+X>x17#`8BAKKiClbw_q*5M)deI`)`HE=41q;yd z59kjeRs$Bu0Dd4qVgPgo2g(LzVfip2?-Fr$F-U5VO(3EnD%ddm;Iyz8O9BZr#4&|k zTLOTT3h?%ndVug7uC|b%Yz#X59`aWKZj~?qV8MpJnzUU4yQJKN(DNd=4CoCP8QF&h zIm5^vR1%zwn|Bc!s^)4ceKq$Hp$w)A2Lx1*39@K_3JAzU=)D5~UQ6@=Swjc2<<4rZ z3wZI~Y)_c5^ZQaz2yA3^S2!h@Ts=6sS ztEuP^RLHJMihwGdUQj_+9nfD0s4K!xApo06qjD5fUFfRHyy~gDBCp`@q2W4$G-wE_ z(2sHmP6f<-MOiLlL1!*zSuE1NVR2(!6&1O7AW=||f=JJXnkqY}{y|8ADhnYhh47Lh zX<=IRJqt2f5C?&!j*Cqk91tpUD}Cu;ed3) zRg(VR%YaKwMvOpp{D*_1=mEQNHi22iU z`;9dbq5*`KKqq}uLVso8qM_oT^dyL<9FT-TEG%qZ=^$5UJbb8-Eg0y&sK^uwk->s% z0p|w^EE*Ly)sQ3-yg;@xR2w?z_g#&MkTyak03HDdU10hW5Crfn4~L2%hyV6f4yp>m zPQ>KEvq&r|LIgTU1leo?D*&-eycWRUOCjAU2=xL`WuPj0fglrZ2@8O*z~8O_Y$_}m zT(UVq#uDja2DcS4tq_rU!obZVW&;igN5m9AG{#Ya;gM^49*k3Ga4=dLYbNK~P!QvM7)SBTfoh z0sB`}MF=|7R9Zgj_l5Aag_Z zVIjryR8E;kS)PN*D;zc+g9=iBTm=e&$>usVa6B76j|5g8MTmDS5K<__0zz9` z1EfS-fgE`@K!f`W0`F`So`yoQFDMA*VW_C6{4nr@9?7A~a}WD|zxxlTf+Gk}PB?e~ zhQlUO9TGQ8nnAH}AVS#s17P%hO4UJO09?LHI5?dLQbpr$Qu5NN0)LHC6`}gi5O9Ey zeO>|@ZKw=20oHJ1WXScc5#gG0LquO7hY}!D{UIaIQ%OH4lBYS4-59V*NFF0351C3w zG#2jlIDevbyu5v#He3~+HHO;-KT=^8fK`NRtNVIVq#R=eD{KLV+D2H^AP*Zh#o!RD z%XPesdH8rXNg3XV1Fu{daxET6hrDza!4pIqeOIs}+(COYeIR=PnQmB!haJVZajA(6 z)rU{P10)4^@BvXBwhNGED+2>A_n-zsehZv@pm~EUgZ;iTyx}m0+qd!x;dc9=Hjp4Kt1iQhk5j4B(H}f3>uq;rs5+#wk^DQqcy=uofBoi9R?s=(KYAV!2hB!W!Xksts_9M`Xd z7n29RKOZpC+|S8*rW)FNw=b+qw#buvLi zQwOg}A`wZN1gsjMsZG`*c#!cR^d5`VR@2hf)*-`ZWUJwEAd&R{+Pm83rjaE4Ir|I-oXi`vH@bEX$5|ZAn;CLP+x8ub=LbHL{%-C=;#jm z4tytQ0*$q*ZPiKR8NEVUJv+nD?LhcqTYsn6hWYkvZ|e9H%Ua}rnesK$*e(3Ov$u5q z!_LF<{FnPlcjA92ACu7iJ0_xZ0@4J;7;wfK`S1Xzlc9iEk7uM32m~NHfFS_{M9;XF z!;bl2L89EQO^hmEh*3qVgj6pZx~wdqKU-o5=SLHIpFB5BI1@EkaZje3(FTk&U^VMTy8?_kE2tVqh>cjAf+5Fg z6p`Ad8|21Nf3dKtJz&YZzbuiPSd>#wtoa?yLLClS zsu8p9s7qzX>O);rK}bI{+KwnNa>mq!c3zhd!UjA>8*r``=8ZmN(iUfIo>3p`QdWOnA0V>q3`EdSJCMdmKKhxLC&{D%X1&dA=H+PKaB+k3FP zxc`g(O8xIX(p~kxQ&R9oq`3fnhqrkUriling!M#$A}uT@A5kmd46$Kts41K}W3R1^ z#;gs&teNClLkz;e{_M>{L=`7#tZhj@j#KfiP+@9=M9$0y zR^dPEHUe*r|L-p0Kf8N-CI8lhnZ^ z4hRXgTN^zx)YYYxhY!Mii6FcY z0=bR{&Jc&zKF)8`D}_at-@(!~BYHi~9sxC}kc6M^U zCD{;3`1JU(C82tG7dQ$J<%@B3Es3UE@c>aYI#?zIB$~#N@A_e?V=Neui+k4=&mR<~ zp-VTfq;o4qO(UAm&UGDDFM~Xj(aNehG^QG@F4lx;Qw^R-J;hC_u$XaPOHb#LPtJ;_ zulP!QLY&(8b)P$q0ZuQEnDlHLz=hL6)TJ79`rX>)d~h|hw_QCJxK{Fc>Kr|Ns_g#Z zrs{7t`oqm;Coe7i;j+qB*OgaGB{nx#W{o>X{mstxx!sd+8tLy`bw932?v0Ej8d+qt z-p~%oHlx{P^;w5u8`FRI`gd_{s#Bt7NRWefZ~yiBkK>omU%YyYeQR(s2dWO8lQiS~ zezV=GbqaO&RKMGa>P@O{OzOR|KgQUfMpa{TPq(5jFO~Sj1-=3Su8RfV-D14Yk z6IgTJiXkAbS9Z|JuDJ%cSU+0mP+d1n`XV;o(Kyn;|EO#?8xh%moul_^<3p>9YiC$* zaz8JO{f*CW?nma0yZRxO%~kmSx&gr3^uO($CH$|%|L-Z?P5x`t&lMprBGyrH>SCYP zD4om&Cvr`l;n#}7o_ZCs7yd_N#qW|b{xAOLw)Ljl&i~oo*;_pSXQ%xC&-ats@o8W^ z`|qLEYX9ZT=$i0#{25>Q`q__g!yh3_H0G;^kHHiVq5$6$eoR+!-oAlmcZcQ<=(CrZSbOOlwd71N(dFO%%fi G1_l5mQ(-Lt literal 20480 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 diff --git a/test/repositories/hg.tgz b/test/repositories/hg.tgz index 1e88f1ad4ed068f015c9b5795c7201c725a53ada..a08852fa60deedd8ab8ec9029d0eed88dc44454b 100644 GIT binary patch literal 3291 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 ZzW)!U=l^MFXlSg;{{Xrdv?~C3003HgyQ%;H literal 2334 zcmV+(3E}o1iwFS950X~^1MQm$ToYFw#{;5biilT11v`r2uoh-AnHf-_!2?Ca19dG` z!AUY9fsjBB#H&CNMXBYoo_JIdQCh*PA6vn73mzN-3N4D>jzP`i^xtOK@!}J z_CvzDoiDtZX;mz(94V z8W=@c|GE7k-S&qtlt}|X1KFd+pS=Bf1Rqz3t7+}NnChBDJcdy(bIM4 z(?5hFI{JrUCQRwy7~cdG6;w z-D{fPbg51;3jrY#NmfXtBAyFZbImNDNQXx9Y#xS(5`3Yk$2%CsA4aWzLrK3Kz50iB z$A2cw!YKV41I2;~qd&5{w{&d8i&p2qf8BCt!M4ITl@qHDZE9$p`q#~-B>tYE);|bx z1-Lkv5J`evggsq{-uXWU>5l&(Le2k;g(<*OgoUjHI(q;hmjK~XB9aix0fkH`CNl&C zAQABZDG@FKMEFXHLf+d}Q}hU0>wgz6&K2~$>()R1v%2XYrsn@f0Yea&$%P1r5Ag^D z;WC*R#7Fr&raRBwjo@<#7=hg}E(?I^Z(Wp%DZD?Z^)Hi4q=ccO!0#Uag)kNs|2GO+ z?GJ)sxLC+1Wbz)J1nTks5QxD#?N7b{DgSR2Ovs-OFfyTc|#OTgPoNK^NGyudZpe?Z;(g;*hD2I+>~rwaiU0 zYyIBRhGnH}3jV27{*Rp&cG`vxEIl@`0JJb;EB82Lj(Zf)FToe9jdA!rCWY6A{%G># z*S$I1p#9!HvP~OLg`ROMSaib?znj~iUX<{>;kUZh!+rfc2BRD1AaTRsl%x4=gJxvr zN^BYi$@Yyp^R_*V;(r(&|8I~efIj~ZL*4v8={zX^Zxmkpf0aXw)MRV?zloLI*U!oh z)$F|RaKFQ~=}lfqeT%wY9+f`4*o*!%Xhl1>Ixxk0%VP&23iv-A7uDFGeiW^Ba~l2RfklC)QjUeIxM5(`y&3D-`xXr@0+2F{1OMs0}|hH$&*UWd}Qd zv{Q}bB)+x|U${=&Xrvgji~%g-@!K0yMtb)o(C|anO*7NQ=XS=dN?g3)vbhbInvgt||69wFa{r|4lOb5r2-btt z8`1gA4{T<%SEFn{CX#6ftz&fQ9AWf5b|G);Mc?+@TCsKx1Q^$@0m(J33z#S zm|$X`R-iU;na6157~CSk({|TTyCG@K)z_C#9T$X&pv>6xhbPNTlRW%h#y)Gjx#;44 zE+cQ*?8hS?95_`Qm-wllvi3>&wXc?LI;(JA$lxX?4EW3L5i=`2Pl!$v!`Wk;+>d=1 z5SUCr-8GX>4l6mnWi@V3v6y{GInNf98c{nAI>os5;2D9J1nHg`dDP{P)1sKB0Hcf0rrq zjGA@Mwx1-psxeetnfPJrVT%o0rLW4fFBJ}||J^3#U3xu*8ZH0N!{xXE7J=`+{$rvj zNUi^jLHG9WI-&2GS%ALy9|G#e{}C3GivJsj*WUM?z9&NnZ2E%uqeu;S_i|FTlwGG{-ZMY+x{K1HR7z3<-93ZhNm6M5MEwX(wCOuU>)6QM8`Dbyt)QcjXCVii@#X> z&$&C+Li^%9u3yPDotY4+Z3?5r%koQb*t*+C&%B@&%-NX2t?CO+Xrdjo__nB|VBWc= z7h7|;m)>vt3bK|x3Eow+|HA4`1GvNX=aqf@bDr#WjAudU`a-r}UfjbHtNfXs$K#F; zy&d?G+jwi&`XA0#3FgLTH`HA3Gxx7U?_@3-v-wo?rz08FhG-Kb(p~?WC%8Sg0?-@( zN0_?ve-uP0{TqeX`X5iGS(;pp{^LTbixk1a?Jlj=H9Q~ZtQ)Rg@m(*EO7|@-I_7^# zRD$~-2%b%r~&A(^TFlFRcqkbxix1_uNgQP)35FW$}3JdBX zAD~zNnC|{R1SX49`Zorz_3uHZ$?Dgp8vU0A+UGbsPa4%+%s&#nu`R&7{$^>{%M}X+ zLK#5*;($yT7A_)y*YigJ4-Xd!xwu>?5xdZRvJ File.join(dir, name)).normalize + yield type.new(:url => File.join(dir, name), branch_name: branch_name).normalize end end @@ -101,13 +101,13 @@ def with_cvs_repository(name, module_name='') end end - def with_git_repository(name) - with_repository(OhlohScm::Adapters::GitAdapter, name) { |git| yield git } - end + def with_git_repository(name, branch_name = nil) + with_repository(OhlohScm::Adapters::GitAdapter, name, branch_name) { |git| yield git } + end - def with_hg_repository(name) - with_repository(OhlohScm::Adapters::HgAdapter, name) { |hg| yield hg } - end + def with_hg_repository(name, branch_name = nil) + with_repository(OhlohScm::Adapters::HgAdapter, name, branch_name) { |hg| yield hg } + end def with_hglib_repository(name) with_repository(OhlohScm::Adapters::HglibAdapter, name) { |hg| yield hg } diff --git a/test/unit/git_commits_test.rb b/test/unit/git_commits_test.rb index e12f0e22..3b1f9b71 100644 --- a/test/unit/git_commits_test.rb +++ b/test/unit/git_commits_test.rb @@ -39,6 +39,20 @@ def test_commits end end + def test_commits_with_branch + with_git_repository('git', 'develop') do |git| + assert_equal ['089c527c61235bd0793c49109b5bd34d439848c6', + 'b6e9220c3cabe53a4ed7f32952aeaeb8a822603d', + '2e9366dd7a786fdb35f211fff1c8ea05c51968b1', + 'b4046b9a80fead62fa949232f2b87b0cb78fffcc'], git.commits.map(&:token) + + assert_equal ['b4046b9a80fead62fa949232f2b87b0cb78fffcc'], + git.commits(:after => '2e9366dd7a786fdb35f211fff1c8ea05c51968b1').map(&:token) + + assert_equal [], git.commits(:after => 'b4046b9a80fead62fa949232f2b87b0cb78fffcc') + end + end + def test_trunk_only_commit_count with_git_repository('git_dupe_delete') do |git| assert_equal 4, git.commit_count(:trunk_only => false) diff --git a/test/unit/git_misc_test.rb b/test/unit/git_misc_test.rb index 9b74de35..9dda2811 100644 --- a/test/unit/git_misc_test.rb +++ b/test/unit/git_misc_test.rb @@ -14,7 +14,7 @@ def test_export def test_branches with_git_repository('git') do |git| - assert_equal ['master'], git.branches + assert_equal ['develop', 'master'], git.branches assert git.has_branch?('master') end end diff --git a/test/unit/hg_commits_test.rb b/test/unit/hg_commits_test.rb index bff9ad3c..9c1eb29b 100644 --- a/test/unit/hg_commits_test.rb +++ b/test/unit/hg_commits_test.rb @@ -5,9 +5,9 @@ class HgCommitsTest < OhlohScm::Test def test_commit_count with_hg_repository('hg') do |hg| - assert_equal 4, hg.commit_count - assert_equal 2, hg.commit_count(:after => 'b14fa4692f949940bd1e28da6fb4617de2615484') - assert_equal 0, hg.commit_count(:after => '75532c1e1f1de55c2271f6fd29d98efbe35397c4') + assert_equal 5, hg.commit_count + assert_equal 3, hg.commit_count(:after => 'b14fa4692f949940bd1e28da6fb4617de2615484') + assert_equal 0, hg.commit_count(:after => '655f04cf6ad708ab58c7b941672dce09dd369a18') end end @@ -16,12 +16,13 @@ def test_commit_tokens assert_equal ['01101d8ef3cea7da9ac6e9a226d645f4418f05c9', 'b14fa4692f949940bd1e28da6fb4617de2615484', '468336c6671cbc58237a259d1b7326866afc2817', - '75532c1e1f1de55c2271f6fd29d98efbe35397c4'], hg.commit_tokens + '75532c1e1f1de55c2271f6fd29d98efbe35397c4', + '655f04cf6ad708ab58c7b941672dce09dd369a18'], hg.commit_tokens - assert_equal ['75532c1e1f1de55c2271f6fd29d98efbe35397c4'], - hg.commit_tokens(:after => '468336c6671cbc58237a259d1b7326866afc2817') + assert_equal ['655f04cf6ad708ab58c7b941672dce09dd369a18'], + hg.commit_tokens(:after => '75532c1e1f1de55c2271f6fd29d98efbe35397c4') - assert_equal [], hg.commit_tokens(:after => '75532c1e1f1de55c2271f6fd29d98efbe35397c4') + assert_equal [], hg.commit_tokens(:after => '655f04cf6ad708ab58c7b941672dce09dd369a18') end end @@ -30,15 +31,34 @@ def test_commits assert_equal ['01101d8ef3cea7da9ac6e9a226d645f4418f05c9', 'b14fa4692f949940bd1e28da6fb4617de2615484', '468336c6671cbc58237a259d1b7326866afc2817', - '75532c1e1f1de55c2271f6fd29d98efbe35397c4'], hg.commits.collect { |c| c.token } + '75532c1e1f1de55c2271f6fd29d98efbe35397c4', + '655f04cf6ad708ab58c7b941672dce09dd369a18'], hg.commits.collect { |c| c.token } - assert_equal ['75532c1e1f1de55c2271f6fd29d98efbe35397c4'], - hg.commits(:after => '468336c6671cbc58237a259d1b7326866afc2817').collect { |c| c.token } + assert_equal ['655f04cf6ad708ab58c7b941672dce09dd369a18'], + hg.commits(:after => '75532c1e1f1de55c2271f6fd29d98efbe35397c4').collect { |c| c.token } # Check that the diffs are not populated - assert_equal [], hg.commits(:after => '468336c6671cbc58237a259d1b7326866afc2817').first.diffs + assert_equal [], hg.commits(:after => '75532c1e1f1de55c2271f6fd29d98efbe35397c4').first.diffs - assert_equal [], hg.commits(:after => '75532c1e1f1de55c2271f6fd29d98efbe35397c4') + assert_equal [], hg.commits(:after => '655f04cf6ad708ab58c7b941672dce09dd369a18') + end + end + + def test_commits_with_branch + with_hg_repository('hg', 'develop') do |hg| + assert_equal ['01101d8ef3cea7da9ac6e9a226d645f4418f05c9', + 'b14fa4692f949940bd1e28da6fb4617de2615484', + '468336c6671cbc58237a259d1b7326866afc2817', + '75532c1e1f1de55c2271f6fd29d98efbe35397c4', + '4d54c3f0526a1ec89214a70615a6b1c6129c665c'], hg.commits.collect { |c| c.token } + + assert_equal ['4d54c3f0526a1ec89214a70615a6b1c6129c665c'], + hg.commits(:after => '75532c1e1f1de55c2271f6fd29d98efbe35397c4').collect { |c| c.token } + + # Check that the diffs are not populated + assert_equal [], hg.commits(:after => '75532c1e1f1de55c2271f6fd29d98efbe35397c4').first.diffs + + assert_equal [], hg.commits(:after => '4d54c3f0526a1ec89214a70615a6b1c6129c665c') end end @@ -129,18 +149,34 @@ def test_each_commit assert_equal ['01101d8ef3cea7da9ac6e9a226d645f4418f05c9', 'b14fa4692f949940bd1e28da6fb4617de2615484', '468336c6671cbc58237a259d1b7326866afc2817', - '75532c1e1f1de55c2271f6fd29d98efbe35397c4'], commits.collect { |c| c.token } + '75532c1e1f1de55c2271f6fd29d98efbe35397c4', + '655f04cf6ad708ab58c7b941672dce09dd369a18'], commits.collect { |c| c.token } end end + def test_each_commit_for_branch + commits = [] + + with_hg_repository('hg', 'develop') do |hg| + commits = hg.each_commit + end + + assert_equal ['01101d8ef3cea7da9ac6e9a226d645f4418f05c9', + 'b14fa4692f949940bd1e28da6fb4617de2615484', + '468336c6671cbc58237a259d1b7326866afc2817', + '75532c1e1f1de55c2271f6fd29d98efbe35397c4', + '4d54c3f0526a1ec89214a70615a6b1c6129c665c'], commits.collect { |c| c.token } + end + + def test_each_commit_after commits = [] with_hg_repository('hg') do |hg| - hg.each_commit(:after => 'b14fa4692f949940bd1e28da6fb4617de2615484') do |c| + hg.each_commit(:after => '468336c6671cbc58237a259d1b7326866afc2817') do |c| commits << c end - assert_equal ['468336c6671cbc58237a259d1b7326866afc2817', - '75532c1e1f1de55c2271f6fd29d98efbe35397c4'], commits.collect { |c| c.token } + assert_equal ['75532c1e1f1de55c2271f6fd29d98efbe35397c4', + '655f04cf6ad708ab58c7b941672dce09dd369a18'], commits.collect { |c| c.token } end end diff --git a/test/unit/hg_head_test.rb b/test/unit/hg_head_test.rb index 915168ee..bca86f9d 100644 --- a/test/unit/hg_head_test.rb +++ b/test/unit/hg_head_test.rb @@ -5,14 +5,20 @@ class HgHeadTest < OhlohScm::Test def test_head_and_parents with_hg_repository('hg') do |hg| - assert_equal '75532c1e1f1d', hg.head_token - assert_equal '75532c1e1f1de55c2271f6fd29d98efbe35397c4', hg.head.token + assert_equal '655f04cf6ad7', hg.head_token + assert_equal '655f04cf6ad708ab58c7b941672dce09dd369a18', hg.head.token assert hg.head.diffs.any? # diffs should be populated - assert_equal '468336c6671cbc58237a259d1b7326866afc2817', hg.parents(hg.head).first.token + assert_equal '75532c1e1f1de55c2271f6fd29d98efbe35397c4', hg.parents(hg.head).first.token assert hg.parents(hg.head).first.diffs.any? end end + def test_head_with_branch + with_hg_repository('hg', 'develop') do |hg| + assert_equal '4d54c3f0526a1ec89214a70615a6b1c6129c665c', hg.head.token + assert hg.head.diffs.any? + end + end end end diff --git a/test/unit/hg_misc_test.rb b/test/unit/hg_misc_test.rb index 53fccf1c..38192482 100644 --- a/test/unit/hg_misc_test.rb +++ b/test/unit/hg_misc_test.rb @@ -14,7 +14,7 @@ def test_exist def test_ls_tree with_hg_repository('hg') do |hg| - assert_equal ['README','makefile'], hg.ls_tree(hg.head_token).sort + assert_equal ['README','makefile', 'two'], hg.ls_tree(hg.head_token).sort end end @@ -22,7 +22,7 @@ def test_export with_hg_repository('hg') do |hg| OhlohScm::ScratchDir.new do |dir| hg.export(dir) - assert_equal ['.', '..', 'README', 'makefile'], Dir.entries(dir).sort + assert_equal ['.', '..', 'README', 'makefile', 'two'], Dir.entries(dir).sort end end end diff --git a/test/unit/hg_parser_test.rb b/test/unit/hg_parser_test.rb index 93cdf8e9..ae10c700 100644 --- a/test/unit/hg_parser_test.rb +++ b/test/unit/hg_parser_test.rb @@ -137,12 +137,12 @@ def test_log_parser_verbose def test_styled_parser with_hg_repository('hg') do |hg| assert FileTest.exist?(HgStyledParser.style_path) - log = hg.run("cd #{hg.url} && hg log --style #{OhlohScm::Parsers::HgStyledParser.style_path}") + log = hg.run("cd #{hg.url} && hg log -f --style #{OhlohScm::Parsers::HgStyledParser.style_path}") commits = OhlohScm::Parsers::HgStyledParser.parse(log) assert_styled_commits(commits, false) assert FileTest.exist?(HgStyledParser.verbose_style_path) - log = hg.run("cd #{hg.url} && hg log --style #{OhlohScm::Parsers::HgStyledParser.verbose_style_path}") + log = hg.run("cd #{hg.url} && hg log -f --style #{OhlohScm::Parsers::HgStyledParser.verbose_style_path}") commits = OhlohScm::Parsers::HgStyledParser.parse(log) assert_styled_commits(commits, true) end @@ -151,31 +151,31 @@ def test_styled_parser protected def assert_styled_commits(commits, with_diffs=false) - assert_equal 4, commits.size + assert_equal 5, commits.size - assert_equal '75532c1e1f1de55c2271f6fd29d98efbe35397c4', commits[0].token - assert_equal 'Robin Luckey', commits[0].committer_name - assert_equal 'robin@ohloh.net', commits[0].committer_email - assert Time.utc(2009,1,20,19,34,53) - commits[0].committer_date < 1 # Don't care about milliseconds - assert_equal "deleted helloworld.c\n", commits[0].message + assert_equal '75532c1e1f1de55c2271f6fd29d98efbe35397c4', commits[1].token + assert_equal 'Robin Luckey', commits[1].committer_name + assert_equal 'robin@ohloh.net', commits[1].committer_email + assert Time.utc(2009,1,20,19,34,53) - commits[1].committer_date < 1 # Don't care about milliseconds + assert_equal "deleted helloworld.c\n", commits[1].message if with_diffs - assert_equal 1, commits[0].diffs.size - assert_equal 'D', commits[0].diffs[0].action - assert_equal 'helloworld.c', commits[0].diffs[0].path + assert_equal 1, commits[1].diffs.size + assert_equal 'D', commits[1].diffs[0].action + assert_equal 'helloworld.c', commits[1].diffs[0].path else - assert_equal [], commits[0].diffs + assert_equal [], commits[1].diffs end - assert_equal '468336c6671cbc58237a259d1b7326866afc2817', commits[1].token - assert Time.utc(2009, 1,20,19,34,04) - commits[1].committer_date < 1 + assert_equal '468336c6671cbc58237a259d1b7326866afc2817', commits[2].token + assert Time.utc(2009, 1,20,19,34,04) - commits[2].committer_date < 1 if with_diffs - assert_equal 2, commits[1].diffs.size - assert_equal 'M', commits[1].diffs[0].action - assert_equal 'helloworld.c', commits[1].diffs[0].path - assert_equal 'A', commits[1].diffs[1].action - assert_equal 'README', commits[1].diffs[1].path + assert_equal 2, commits[2].diffs.size + assert_equal 'M', commits[2].diffs[0].action + assert_equal 'helloworld.c', commits[2].diffs[0].path + assert_equal 'A', commits[2].diffs[1].action + assert_equal 'README', commits[2].diffs[1].path else assert_equal [], commits[0].diffs end diff --git a/test/unit/hglib_head_test.rb b/test/unit/hglib_head_test.rb index 12aea8a1..5704984f 100644 --- a/test/unit/hglib_head_test.rb +++ b/test/unit/hglib_head_test.rb @@ -5,11 +5,11 @@ class HgHeadTest < OhlohScm::Test def test_head_and_parents with_hglib_repository('hg') do |hg| - assert_equal '75532c1e1f1d', hg.head_token - assert_equal '75532c1e1f1de55c2271f6fd29d98efbe35397c4', hg.head.token + assert_equal '655f04cf6ad7', hg.head_token + assert_equal '655f04cf6ad708ab58c7b941672dce09dd369a18', hg.head.token assert hg.head.diffs.any? # diffs should be populated - assert_equal '468336c6671cbc58237a259d1b7326866afc2817', hg.parents(hg.head).first.token + assert_equal '75532c1e1f1de55c2271f6fd29d98efbe35397c4', hg.parents(hg.head).first.token assert hg.parents(hg.head).first.diffs.any? end end From 20b3cce64accb4fadaa0e23e6d4f74323c7b201c Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Wed, 10 Aug 2016 16:12:01 +0530 Subject: [PATCH 185/219] OTWO-4332 Detect tags for all SCMs --- lib/ohloh_scm/adapters/bzr/misc.rb | 7 +++++++ lib/ohloh_scm/adapters/cvs/misc.rb | 8 ++++++++ lib/ohloh_scm/adapters/git/misc.rb | 9 +++++++++ lib/ohloh_scm/adapters/hg/misc.rb | 9 +++++++++ lib/ohloh_scm/adapters/svn/misc.rb | 13 +++++++++++++ test/repositories/bzr/.bzr/branch/tags | 1 + test/repositories/git.tgz | Bin 16426 -> 16744 bytes test/unit/bzr_misc_test.rb | 5 +++++ test/unit/cvs_misc_test.rb | 6 ++++++ test/unit/git_misc_test.rb | 7 +++++++ test/unit/hg_misc_test.rb | 6 ++++++ test/unit/svn_misc_test.rb | 13 +++++++++++++ 12 files changed, 84 insertions(+) diff --git a/lib/ohloh_scm/adapters/bzr/misc.rb b/lib/ohloh_scm/adapters/bzr/misc.rb index 5f30aa14..4e786168 100644 --- a/lib/ohloh_scm/adapters/bzr/misc.rb +++ b/lib/ohloh_scm/adapters/bzr/misc.rb @@ -38,5 +38,12 @@ def export(dest_dir, token=head_token) run "cd '#{url}' && bzr export --format=dir -r #{to_rev_param(token)} '#{dest_dir}'" end + + def tags + tag_strings = run("cd '#{url}' && bzr tags").split(/\n/) + tag_strings.map do |tag_string| + tag_string.split(/\s+/) + end + end end end diff --git a/lib/ohloh_scm/adapters/cvs/misc.rb b/lib/ohloh_scm/adapters/cvs/misc.rb index c53b9a7e..856e65bc 100644 --- a/lib/ohloh_scm/adapters/cvs/misc.rb +++ b/lib/ohloh_scm/adapters/cvs/misc.rb @@ -187,5 +187,13 @@ def ensure_host_key stdout, stderr = run_with_err(cmd) end end + + def tags + tag_strings = run("cvs -Q -d #{ url } rlog -h #{ module_name } | awk -F\"[.:]\" '/^\\t/&&$(NF-1)!=0'").split(/\n/) + tag_strings.map do |tag_string| + tag_name, version = tag_string.split(':') + [tag_name.gsub(/\t/, ''), version.strip] + end + end end end diff --git a/lib/ohloh_scm/adapters/git/misc.rb b/lib/ohloh_scm/adapters/git/misc.rb index 1e99df3e..50323856 100644 --- a/lib/ohloh_scm/adapters/git/misc.rb +++ b/lib/ohloh_scm/adapters/git/misc.rb @@ -69,5 +69,14 @@ def create_tracking_branch(name) def is_merge_commit?(commit) parent_tokens(commit).size > 1 end + + def tags + tag_strings = run("cd #{url} && git show-ref --tags").split(/\n/) + tag_strings.map do |tag_string| + commit_hash, tag_path = tag_string.split(/\s/) + tag_name = tag_path.gsub('refs/tags/', '') + [tag_name, commit_hash] + end + end end end diff --git a/lib/ohloh_scm/adapters/hg/misc.rb b/lib/ohloh_scm/adapters/hg/misc.rb index 72624ea0..649fb531 100644 --- a/lib/ohloh_scm/adapters/hg/misc.rb +++ b/lib/ohloh_scm/adapters/hg/misc.rb @@ -18,5 +18,14 @@ def export(dest_dir, token='tip') # Hg leaves a little cookie crumb in the export directory. Remove it. File.delete(File.join(dest_dir, '.hg_archival.txt')) if File.exist?(File.join(dest_dir, '.hg_archival.txt')) end + + def tags + tag_strings = run("cd '#{path}' && hg tags").split(/\n/) + tag_strings.map do |tag_string| + tag_name, rev_number_and_hash = tag_string.split(/\s+/) + rev_number = rev_number_and_hash.slice(/\A\d+/) + [tag_name, rev_number] + end + end end end diff --git a/lib/ohloh_scm/adapters/svn/misc.rb b/lib/ohloh_scm/adapters/svn/misc.rb index ad8eebc1..11dfc3fe 100644 --- a/lib/ohloh_scm/adapters/svn/misc.rb +++ b/lib/ohloh_scm/adapters/svn/misc.rb @@ -133,6 +133,19 @@ def opt_auth " #{opt_password} --no-auth-cache " end + # Svn root is not usable here since several projects are nested in subfolders. + # e.g. https://svn.apache.org/repos/asf/openoffice/ooo-site/trunk/ + # http://svn.apache.org/repos/asf/httpd/httpd/trunk + # http://svn.apache.org/repos/asf/maven/plugin-testing/trunk + # all have the same root value(https://svn.apache.org/repos/asf) + def tags + base_url = url.sub(/(.*)(branches|trunk|tags)(.*)/, '\1').chomp('/') + tag_strings = `svn log -v #{ base_url }/tags | grep 'tags.\\+(from.\\+:[0-9]\\+)$'`.split(/\n/) + tag_strings.map do |tag_string| + tag_string.match(/\/tags\/(.+) \(from .+:(\d+)\)\Z/)[1..2] + end + end + class << self def has_conflicts?(working_copy_url) system("cd '#{ working_copy_url }' && svn status | grep 'Summary of conflicts'") diff --git a/test/repositories/bzr/.bzr/branch/tags b/test/repositories/bzr/.bzr/branch/tags index e69de29b..e845266f 100644 --- a/test/repositories/bzr/.bzr/branch/tags +++ b/test/repositories/bzr/.bzr/branch/tags @@ -0,0 +1 @@ +d6:v1.0.047:obnox@samba.org-20090204002540-gmana8tk5f9gboq96:v2.0.048:test@example.com-20111222183733-y91if5npo3pe8ifse \ No newline at end of file diff --git a/test/repositories/git.tgz b/test/repositories/git.tgz index 392318a7f5a41e7f0a4eb43ce0b1c013b949167b..e5c12a536e158c5b999645f928e0dfc342bccef9 100644 GIT binary patch literal 16744 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 G1_l5mQ(-Lt diff --git a/test/unit/bzr_misc_test.rb b/test/unit/bzr_misc_test.rb index 44e788ff..113f6ce6 100644 --- a/test/unit/bzr_misc_test.rb +++ b/test/unit/bzr_misc_test.rb @@ -34,5 +34,10 @@ def test_export end end + def test_tags + with_bzr_repository('bzr') do |bzr| + assert_equal bzr.tags, [['v1.0.0', '5'], ['v2.0.0','7']] + end + end end end diff --git a/test/unit/cvs_misc_test.rb b/test/unit/cvs_misc_test.rb index a2d202ec..d11dd4cc 100644 --- a/test/unit/cvs_misc_test.rb +++ b/test/unit/cvs_misc_test.rb @@ -62,5 +62,11 @@ def test_log_encoding assert_equal true, cvs.log.valid_encoding? end end + + def test_tags + with_cvs_repository('cvs', 'simple') do |cvs| + assert_equal([['simple_release_tag', '1.1.1.1'], ['simple_vendor_tag', '1.1.1']], cvs.tags) + end + end end end diff --git a/test/unit/git_misc_test.rb b/test/unit/git_misc_test.rb index 9dda2811..2f54c099 100644 --- a/test/unit/git_misc_test.rb +++ b/test/unit/git_misc_test.rb @@ -44,5 +44,12 @@ def test_ls_tree_encoding assert_equal true, git.ls_tree.all? { |filename| filename.valid_encoding? } end end + + def test_tags + with_git_repository('git') do |git| + assert_equal git.tags, [['v1.0.0', 'f6e5a894ac4173f8f2a200f2c36df38a1e61121a'], + ['v2.1.0', '1df547800dcd168e589bb9b26b4039bff3a7f7e4']] + end + end end end diff --git a/test/unit/hg_misc_test.rb b/test/unit/hg_misc_test.rb index 38192482..137fe791 100644 --- a/test/unit/hg_misc_test.rb +++ b/test/unit/hg_misc_test.rb @@ -36,5 +36,11 @@ def test_ls_tree_encoding end end end + + def test_tags + with_hg_repository('hg') do |hg| + assert_equal hg.tags, [['tip', '5']] + end + end end end diff --git a/test/unit/svn_misc_test.rb b/test/unit/svn_misc_test.rb index 0894f765..8fb93306 100644 --- a/test/unit/svn_misc_test.rb +++ b/test/unit/svn_misc_test.rb @@ -85,5 +85,18 @@ def test_restrict_url_to_trunk assert_equal "/trunk", svn.branch_name end end + + def test_tags + with_svn_repository('svn', 'trunk') do |source_scm| + OhlohScm::ScratchDir.new do |svn_working_folder| + folder_name = source_scm.root.slice(/[^\/]+\/?\Z/) + system "cd #{ svn_working_folder } && svn co #{ source_scm.root } && cd #{ folder_name } && + mkdir -p #{ source_scm.root.gsub(/^file:../, '') }/db/transactions + svn copy trunk tags/2.0 && svn commit -m 'v2.0' && svn update" + + assert_equal([['2.0', source_scm.head_token.to_s]], source_scm.tags) + end + end + end end end From 7d4747af2acde648e48b30d701cb99b98bdcc3e7 Mon Sep 17 00:00:00 2001 From: santhanakarthikeyan Date: Wed, 10 Aug 2016 21:42:09 +0530 Subject: [PATCH 186/219] OTWO-4365: Add export tags feature for SVN and CVS repository --- lib/ohloh_scm/adapters/cvs/misc.rb | 4 ++++ lib/ohloh_scm/adapters/svn/misc.rb | 15 +++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/ohloh_scm/adapters/cvs/misc.rb b/lib/ohloh_scm/adapters/cvs/misc.rb index 856e65bc..3c256e8a 100644 --- a/lib/ohloh_scm/adapters/cvs/misc.rb +++ b/lib/ohloh_scm/adapters/cvs/misc.rb @@ -70,6 +70,10 @@ def log(most_recent_token=nil) run "cvsnt -d #{self.url} rlog #{opt_branch} #{opt_time(most_recent_token)} '#{self.module_name}' | #{ string_encoder }" end + def export_tag(dest_dir, tag_name = 'HEAD') + run "cvsnt -d #{self.url} export -d'#{dest_dir}' -r #{tag_name} '#{self.module_name}'" + end + def checkout(r, local_directory) opt_D = r.token ? "-D'#{r.token}Z'" : "" diff --git a/lib/ohloh_scm/adapters/svn/misc.rb b/lib/ohloh_scm/adapters/svn/misc.rb index 11dfc3fe..21849379 100644 --- a/lib/ohloh_scm/adapters/svn/misc.rb +++ b/lib/ohloh_scm/adapters/svn/misc.rb @@ -123,6 +123,11 @@ def export(dest_dir, commit_id = final_token || 'HEAD') run "svn export --trust-server-cert --non-interactive --ignore-externals --force -r #{commit_id} '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}' '#{dest_dir}'" end + def export_tag(dest_dir, tag_name) + tag_url = "#{base_path}/tags/#{tag_name}" + run "svn export --trust-server-cert --non-interactive --ignore-externals --force '#{tag_url}' '#{dest_dir}'" + end + def ls_tree(token) run("svn ls --trust-server-cert --non-interactive -R -r #{token} '#{SvnAdapter.uri_encode(File.join(root, branch_name.to_s))}@#{token}'").split("\n") end @@ -139,8 +144,7 @@ def opt_auth # http://svn.apache.org/repos/asf/maven/plugin-testing/trunk # all have the same root value(https://svn.apache.org/repos/asf) def tags - base_url = url.sub(/(.*)(branches|trunk|tags)(.*)/, '\1').chomp('/') - tag_strings = `svn log -v #{ base_url }/tags | grep 'tags.\\+(from.\\+:[0-9]\\+)$'`.split(/\n/) + tag_strings = `svn log -v #{ base_path}/tags | grep 'tags.\\+(from.\\+:[0-9]\\+)$'`.split(/\n/) tag_strings.map do |tag_string| tag_string.match(/\/tags\/(.+) \(from .+:(\d+)\)\Z/)[1..2] end @@ -151,5 +155,12 @@ def has_conflicts?(working_copy_url) system("cd '#{ working_copy_url }' && svn status | grep 'Summary of conflicts'") end end + + private + + def base_path + url.sub(/(.*)(branches|trunk|tags)(.*)/, '\1').chomp('/') + end + end end From c6d4461414a3051d1f3dcb2f2f7ab561b3b59cc4 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Thu, 11 Aug 2016 16:55:35 +0530 Subject: [PATCH 187/219] OTWO-4365 Add tests for export_tag --- test/unit/cvs_misc_test.rb | 10 ++++++++++ test/unit/svn_misc_test.rb | 17 +++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/test/unit/cvs_misc_test.rb b/test/unit/cvs_misc_test.rb index d11dd4cc..9603f071 100644 --- a/test/unit/cvs_misc_test.rb +++ b/test/unit/cvs_misc_test.rb @@ -68,5 +68,15 @@ def test_tags assert_equal([['simple_release_tag', '1.1.1.1'], ['simple_vendor_tag', '1.1.1']], cvs.tags) end end + + def test_export_tag + with_cvs_repository('cvs', 'simple') do |cvs| + OhlohScm::ScratchDir.new do |dir| + cvs.export_tag(dir, 'simple_release_tag') + + assert_equal ['.','..','foo.rb'], Dir.entries(dir).sort + end + end + end end end diff --git a/test/unit/svn_misc_test.rb b/test/unit/svn_misc_test.rb index 8fb93306..8b3b16bf 100644 --- a/test/unit/svn_misc_test.rb +++ b/test/unit/svn_misc_test.rb @@ -12,6 +12,23 @@ def test_export end end + def test_export_tag + with_svn_repository('svn', 'trunk') do |source_scm| + OhlohScm::ScratchDir.new do |svn_working_folder| + OhlohScm::ScratchDir.new do |dir| + folder_name = source_scm.root.slice(/[^\/]+\/?\Z/) + system "cd #{ svn_working_folder } && svn co #{ source_scm.root } && cd #{ folder_name } && + mkdir -p #{ source_scm.root.gsub(/^file:../, '') }/db/transactions + svn copy trunk tags/2.0 && svn commit -m 'v2.0' && svn update" + + source_scm.export_tag(dir, '2.0') + + assert_equal ['.','..','COPYING','README','helloworld.c', 'makefile'], Dir.entries(dir).sort + end + end + end + end + def test_ls_tree with_svn_repository('svn') do |svn| assert_equal ['branches/','tags/','trunk/','trunk/helloworld.c','trunk/makefile'], svn.ls_tree(2).sort From 2b44fbb13bdb37d17521b6a6ba8b037fed5b0d2d Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Fri, 12 Aug 2016 00:59:46 +0530 Subject: [PATCH 188/219] Version bump --- lib/ohloh_scm/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ohloh_scm/version.rb b/lib/ohloh_scm/version.rb index e9f6ffc1..f5b3a5c4 100644 --- a/lib/ohloh_scm/version.rb +++ b/lib/ohloh_scm/version.rb @@ -1,5 +1,5 @@ module OhlohScm module Version - STRING = '2.1.0' + STRING = '2.2.0' end end From 0c8fce9c091d37bac84f6f8f88f16ca8b6185153 Mon Sep 17 00:00:00 2001 From: santhanakarthikeyan Date: Tue, 16 Aug 2016 13:43:10 +0530 Subject: [PATCH 189/219] Fetch SVN tags using ls instead of log --- lib/ohloh_scm/adapters/svn/misc.rb | 6 +++--- test/unit/svn_misc_test.rb | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/ohloh_scm/adapters/svn/misc.rb b/lib/ohloh_scm/adapters/svn/misc.rb index 21849379..6e4924df 100644 --- a/lib/ohloh_scm/adapters/svn/misc.rb +++ b/lib/ohloh_scm/adapters/svn/misc.rb @@ -144,10 +144,10 @@ def opt_auth # http://svn.apache.org/repos/asf/maven/plugin-testing/trunk # all have the same root value(https://svn.apache.org/repos/asf) def tags - tag_strings = `svn log -v #{ base_path}/tags | grep 'tags.\\+(from.\\+:[0-9]\\+)$'`.split(/\n/) + tag_strings = `svn ls -v #{ base_path}/tags`.split(/\n/) tag_strings.map do |tag_string| - tag_string.match(/\/tags\/(.+) \(from .+:(\d+)\)\Z/)[1..2] - end + tag_string.split(' ').values_at(-1, 0).map { |v| v.chomp('/') } + end[1..-1] end class << self diff --git a/test/unit/svn_misc_test.rb b/test/unit/svn_misc_test.rb index 8b3b16bf..551a785f 100644 --- a/test/unit/svn_misc_test.rb +++ b/test/unit/svn_misc_test.rb @@ -111,7 +111,7 @@ def test_tags mkdir -p #{ source_scm.root.gsub(/^file:../, '') }/db/transactions svn copy trunk tags/2.0 && svn commit -m 'v2.0' && svn update" - assert_equal([['2.0', source_scm.head_token.to_s]], source_scm.tags) + assert_equal([['2.0', '6']], source_scm.tags) end end end From 08337cb7d21f7e324b335da9ee3838ab1383ad74 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Tue, 23 Aug 2016 15:33:23 +0530 Subject: [PATCH 190/219] Version bump --- lib/ohloh_scm/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ohloh_scm/version.rb b/lib/ohloh_scm/version.rb index f5b3a5c4..342d4f34 100644 --- a/lib/ohloh_scm/version.rb +++ b/lib/ohloh_scm/version.rb @@ -1,5 +1,5 @@ module OhlohScm module Version - STRING = '2.2.0' + STRING = '2.2.1' end end From 88883873169c9a7b1a568609490f2bea2dca01b7 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Thu, 8 Sep 2016 15:22:21 +0530 Subject: [PATCH 191/219] OTWO-4394 Fix git tags for repository without tags --- lib/ohloh_scm/adapters/git/misc.rb | 5 +++++ test/unit/git_misc_test.rb | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/lib/ohloh_scm/adapters/git/misc.rb b/lib/ohloh_scm/adapters/git/misc.rb index 50323856..1dec1961 100644 --- a/lib/ohloh_scm/adapters/git/misc.rb +++ b/lib/ohloh_scm/adapters/git/misc.rb @@ -70,7 +70,12 @@ def is_merge_commit?(commit) parent_tokens(commit).size > 1 end + def no_tags? + run("cd #{ url } && git tag | head -1").empty? + end + def tags + return [] if no_tags? tag_strings = run("cd #{url} && git show-ref --tags").split(/\n/) tag_strings.map do |tag_string| commit_hash, tag_path = tag_string.split(/\s/) diff --git a/test/unit/git_misc_test.rb b/test/unit/git_misc_test.rb index 2f54c099..1b65cc71 100644 --- a/test/unit/git_misc_test.rb +++ b/test/unit/git_misc_test.rb @@ -51,5 +51,11 @@ def test_tags ['v2.1.0', '1df547800dcd168e589bb9b26b4039bff3a7f7e4']] end end + + def test_tags_with_non_tagged_repository + with_git_repository('git_walk') do |git| + assert_equal git.tags, [] + end + end end end From 51fda5996f9ffb13c65348eb5695052196f1a46e Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Tue, 13 Sep 2016 12:32:19 +0530 Subject: [PATCH 192/219] Version bump --- lib/ohloh_scm/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ohloh_scm/version.rb b/lib/ohloh_scm/version.rb index 342d4f34..8a172e52 100644 --- a/lib/ohloh_scm/version.rb +++ b/lib/ohloh_scm/version.rb @@ -1,5 +1,5 @@ module OhlohScm module Version - STRING = '2.2.1' + STRING = '2.2.2' end end From e64b9d7a9bad8477b8525137b832221b66af99ef Mon Sep 17 00:00:00 2001 From: santhanakarthikeyan Date: Mon, 3 Oct 2016 16:16:18 +0530 Subject: [PATCH 193/219] OTWO-4382: Accept configurable directory for temporary file creation --- lib/ohloh_scm/adapters/abstract_adapter.rb | 4 ++++ lib/ohloh_scm/adapters/bzr/commits.rb | 2 +- lib/ohloh_scm/adapters/cvs/commits.rb | 2 +- lib/ohloh_scm/adapters/git/commits.rb | 2 +- lib/ohloh_scm/adapters/hg/commits.rb | 2 +- lib/ohloh_scm/adapters/svn/commits.rb | 2 +- 6 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/ohloh_scm/adapters/abstract_adapter.rb b/lib/ohloh_scm/adapters/abstract_adapter.rb index 47d468d4..f14e2d68 100644 --- a/lib/ohloh_scm/adapters/abstract_adapter.rb +++ b/lib/ohloh_scm/adapters/abstract_adapter.rb @@ -1,6 +1,7 @@ module OhlohScm::Adapters class AbstractAdapter attr_accessor :url, :branch_name, :username, :password, :errors, :public_urls_only + attr_writer :temp_folder def initialize(params={}) params.each { |k,v| send(k.to_s + '=', v) if respond_to?(k.to_s + '=') } @@ -19,6 +20,9 @@ def string_encoder File.expand_path('../../../../bin/string_encoder', __FILE__) end + def temp_folder + @temp_folder || '/tmp' + end end end diff --git a/lib/ohloh_scm/adapters/bzr/commits.rb b/lib/ohloh_scm/adapters/bzr/commits.rb index 2426fecc..25fda009 100644 --- a/lib/ohloh_scm/adapters/bzr/commits.rb +++ b/lib/ohloh_scm/adapters/bzr/commits.rb @@ -86,7 +86,7 @@ def open_log_file(opts={}) end def log_filename - File.join('/tmp', (self.url).gsub(/\W/,'') + '.log') + File.join(temp_folder, (self.url).gsub(/\W/,'') + '.log') end # Uses xmllog command for output to be used by BzrXmlParser. diff --git a/lib/ohloh_scm/adapters/cvs/commits.rb b/lib/ohloh_scm/adapters/cvs/commits.rb index 51aa3fd7..a3174183 100644 --- a/lib/ohloh_scm/adapters/cvs/commits.rb +++ b/lib/ohloh_scm/adapters/cvs/commits.rb @@ -82,7 +82,7 @@ def opt_time(after=nil) end def rlog_filename - File.join('/tmp', (self.url + self.module_name.to_s + self.branch_name.to_s).gsub(/\W/,'') + '.rlog') + File.join(temp_folder, (self.url + self.module_name.to_s + self.branch_name.to_s).gsub(/\W/,'') + '.rlog') end # Converts a CVS time string to a Ruby Time object diff --git a/lib/ohloh_scm/adapters/git/commits.rb b/lib/ohloh_scm/adapters/git/commits.rb index 9b79d808..a132009a 100644 --- a/lib/ohloh_scm/adapters/git/commits.rb +++ b/lib/ohloh_scm/adapters/git/commits.rb @@ -108,7 +108,7 @@ def open_log_file(opts={}) end def log_filename - File.join('/tmp', (self.url).gsub(/\W/,'') + '.log') + File.join(temp_folder, (self.url).gsub(/\W/,'') + '.log') end def rev_list_command(opts={}) diff --git a/lib/ohloh_scm/adapters/hg/commits.rb b/lib/ohloh_scm/adapters/hg/commits.rb index 7ec6b821..fcadbbc2 100644 --- a/lib/ohloh_scm/adapters/hg/commits.rb +++ b/lib/ohloh_scm/adapters/hg/commits.rb @@ -86,7 +86,7 @@ def open_log_file(opts={}) end def log_filename - File.join('/tmp', (self.url).gsub(/\W/,'') + '.log') + File.join(temp_folder, (self.url).gsub(/\W/,'') + '.log') end private diff --git a/lib/ohloh_scm/adapters/svn/commits.rb b/lib/ohloh_scm/adapters/svn/commits.rb index 216497ad..2b08f58e 100644 --- a/lib/ohloh_scm/adapters/svn/commits.rb +++ b/lib/ohloh_scm/adapters/svn/commits.rb @@ -163,7 +163,7 @@ def open_log_file(opts={}) end def log_filename - File.join('/tmp', (self.url).gsub(/\W/,'') + '.log') + File.join(temp_folder, (self.url).gsub(/\W/,'') + '.log') end # Returns one commit with the exact revision number provided From 0877a792693ccfd8e9882ad29b01b60952591c40 Mon Sep 17 00:00:00 2001 From: Peter Degen-Portnoy Date: Wed, 26 Oct 2016 13:26:44 -0400 Subject: [PATCH 194/219] Update version to 2.2.3 --- lib/ohloh_scm/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ohloh_scm/version.rb b/lib/ohloh_scm/version.rb index 8a172e52..16673b04 100644 --- a/lib/ohloh_scm/version.rb +++ b/lib/ohloh_scm/version.rb @@ -1,5 +1,5 @@ module OhlohScm module Version - STRING = '2.2.2' + STRING = '2.2.3' end end From 00d37f4ecfb75ef95ce78eabd22ffc13b758ed54 Mon Sep 17 00:00:00 2001 From: Peter Degen-Portnoy Date: Wed, 26 Oct 2016 13:46:11 -0400 Subject: [PATCH 195/219] Update ruby version to specific patch --- .ruby-version | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.ruby-version b/.ruby-version index 227cea21..f211840f 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1,2 @@ -2.0.0 +2.0.0-p648 + From e1ef92e82e4c768bc9582530f2f19600f9eb1853 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Mon, 19 Dec 2016 20:28:15 +0530 Subject: [PATCH 196/219] OTWO-4470 Return timestamp for tags --- .travis/.install_multiple_scms.sh | 3 ++- lib/ohloh_scm/adapters/bzr/misc.rb | 7 +++++-- lib/ohloh_scm/adapters/git/misc.rb | 7 ++++--- lib/ohloh_scm/adapters/hg/misc.rb | 5 +++-- lib/ohloh_scm/adapters/svn/misc.rb | 4 +++- test/unit/bzr_misc_test.rb | 19 ++++++++++++++++++- test/unit/git_misc_test.rb | 4 ++-- test/unit/hg_misc_test.rb | 3 ++- test/unit/svn_misc_test.rb | 4 +++- 9 files changed, 42 insertions(+), 14 deletions(-) diff --git a/.travis/.install_multiple_scms.sh b/.travis/.install_multiple_scms.sh index 2344896e..3fd09e34 100644 --- a/.travis/.install_multiple_scms.sh +++ b/.travis/.install_multiple_scms.sh @@ -1,5 +1,6 @@ sudo sh -c 'echo "deb http://opensource.wandisco.com/ubuntu precise svn18" >> /etc/apt/sources.list.d/subversion18.list' sudo wget -q http://opensource.wandisco.com/wandisco-debian.gpg -O- | sudo apt-key add - +sudo apt-add-repository -y ppa:git-core/ppa sudo apt-get update -sudo apt-get install -y subversion cvs bzr mercurial +sudo apt-get install -y git subversion cvs bzr mercurial sudo ln -s /usr/bin/cvs /usr/bin/cvsnt diff --git a/lib/ohloh_scm/adapters/bzr/misc.rb b/lib/ohloh_scm/adapters/bzr/misc.rb index 4e786168..c9eb65ed 100644 --- a/lib/ohloh_scm/adapters/bzr/misc.rb +++ b/lib/ohloh_scm/adapters/bzr/misc.rb @@ -42,8 +42,11 @@ def export(dest_dir, token=head_token) def tags tag_strings = run("cd '#{url}' && bzr tags").split(/\n/) tag_strings.map do |tag_string| - tag_string.split(/\s+/) - end + tag_name, rev = tag_string.split(/\s+/) + next if rev == '?' || tag_name == '....' + time_string = run("cd '#{ url }' && bzr log -r #{ rev } | grep 'timestamp:' | sed 's/timestamp://'") + [tag_name, rev, Time.parse(time_string)] + end.compact end end end diff --git a/lib/ohloh_scm/adapters/git/misc.rb b/lib/ohloh_scm/adapters/git/misc.rb index 1dec1961..280ad254 100644 --- a/lib/ohloh_scm/adapters/git/misc.rb +++ b/lib/ohloh_scm/adapters/git/misc.rb @@ -76,11 +76,12 @@ def no_tags? def tags return [] if no_tags? - tag_strings = run("cd #{url} && git show-ref --tags").split(/\n/) + tag_strings = run("cd #{url} && git tag --format='%(creatordate:iso-strict) %(objectname) %(refname)'").split(/\n/) tag_strings.map do |tag_string| - commit_hash, tag_path = tag_string.split(/\s/) + timestamp_string, commit_hash, tag_path = tag_string.split(/\s/) + timestamp = Time.parse(timestamp_string) tag_name = tag_path.gsub('refs/tags/', '') - [tag_name, commit_hash] + [tag_name, commit_hash, timestamp] end end end diff --git a/lib/ohloh_scm/adapters/hg/misc.rb b/lib/ohloh_scm/adapters/hg/misc.rb index 649fb531..1f25463e 100644 --- a/lib/ohloh_scm/adapters/hg/misc.rb +++ b/lib/ohloh_scm/adapters/hg/misc.rb @@ -23,8 +23,9 @@ def tags tag_strings = run("cd '#{path}' && hg tags").split(/\n/) tag_strings.map do |tag_string| tag_name, rev_number_and_hash = tag_string.split(/\s+/) - rev_number = rev_number_and_hash.slice(/\A\d+/) - [tag_name, rev_number] + rev = rev_number_and_hash.slice(/\A\d+/) + time_string = run("cd '#{ path }' && hg log -r #{ rev } | grep 'date:' | sed 's/date://'") + [tag_name, rev, Time.parse(time_string)] end end end diff --git a/lib/ohloh_scm/adapters/svn/misc.rb b/lib/ohloh_scm/adapters/svn/misc.rb index 6e4924df..88b6b857 100644 --- a/lib/ohloh_scm/adapters/svn/misc.rb +++ b/lib/ohloh_scm/adapters/svn/misc.rb @@ -146,7 +146,9 @@ def opt_auth def tags tag_strings = `svn ls -v #{ base_path}/tags`.split(/\n/) tag_strings.map do |tag_string| - tag_string.split(' ').values_at(-1, 0).map { |v| v.chomp('/') } + date_string = tag_string.split(' ').values_at(-4, -3, -2).join(' ') + folder_and_rev = tag_string.split(' ').values_at(-1, 0).map { |v| v.chomp('/') } + folder_and_rev << Time.parse(date_string) end[1..-1] end diff --git a/test/unit/bzr_misc_test.rb b/test/unit/bzr_misc_test.rb index 113f6ce6..8e7b9786 100644 --- a/test/unit/bzr_misc_test.rb +++ b/test/unit/bzr_misc_test.rb @@ -36,7 +36,24 @@ def test_export def test_tags with_bzr_repository('bzr') do |bzr| - assert_equal bzr.tags, [['v1.0.0', '5'], ['v2.0.0','7']] + time_1 = Time.parse('2009-02-04 00:25:40 +0000') + time_2 = Time.parse('2011-12-22 18:37:33 +0000') + monkey_patch_run_method_to_match_tag_patterns + assert_equal [['v1.0.0', '5', time_1], ['v2.0.0','7', time_2]], bzr.tags + end + end + + private + + def monkey_patch_run_method_to_match_tag_patterns + original_method = AbstractAdapter.method(:run) + AbstractAdapter.send :define_method, :run do |command| + if command =~ /bzr tags/ + # The output of `bzr tags` sometimes has tags referring to ? while sometimes has dotted separators. + "0.11-1.1 ?\n0.14-1 ?\n....\n#{ original_method.call(command) }" + else + original_method.call(command) + end end end end diff --git a/test/unit/git_misc_test.rb b/test/unit/git_misc_test.rb index 1b65cc71..ab2464c6 100644 --- a/test/unit/git_misc_test.rb +++ b/test/unit/git_misc_test.rb @@ -47,8 +47,8 @@ def test_ls_tree_encoding def test_tags with_git_repository('git') do |git| - assert_equal git.tags, [['v1.0.0', 'f6e5a894ac4173f8f2a200f2c36df38a1e61121a'], - ['v2.1.0', '1df547800dcd168e589bb9b26b4039bff3a7f7e4']] + assert_equal git.tags, [['v1.0.0', 'f6e5a894ac4173f8f2a200f2c36df38a1e61121a', Time.parse('2016-07-31T07:58:30+05:30')], + ['v2.1.0', '1df547800dcd168e589bb9b26b4039bff3a7f7e4', Time.parse('2006-07-14T16:07:15-07:00')]] end end diff --git a/test/unit/hg_misc_test.rb b/test/unit/hg_misc_test.rb index 137fe791..5dab6f01 100644 --- a/test/unit/hg_misc_test.rb +++ b/test/unit/hg_misc_test.rb @@ -39,7 +39,8 @@ def test_ls_tree_encoding def test_tags with_hg_repository('hg') do |hg| - assert_equal hg.tags, [['tip', '5']] + time = Time.parse('Fri Jul 22 18:00:18 2016 +0530') + assert_equal [['tip', '5', time]], hg.tags end end end diff --git a/test/unit/svn_misc_test.rb b/test/unit/svn_misc_test.rb index 551a785f..5be326ba 100644 --- a/test/unit/svn_misc_test.rb +++ b/test/unit/svn_misc_test.rb @@ -111,7 +111,9 @@ def test_tags mkdir -p #{ source_scm.root.gsub(/^file:../, '') }/db/transactions svn copy trunk tags/2.0 && svn commit -m 'v2.0' && svn update" - assert_equal([['2.0', '6']], source_scm.tags) + assert_equal(['2.0', '6'], source_scm.tags.first[0..1]) + # Avoid millisecond comparision. + assert_equal(Time.now.strftime('%F %R'), source_scm.tags.first[-1].strftime('%F %R')) end end end From 4474205aef6399f1789bbcb857e2096c9de3886a Mon Sep 17 00:00:00 2001 From: Priya Rani Date: Tue, 27 Dec 2016 16:10:00 +0530 Subject: [PATCH 197/219] OTWO-4466 Set the branch_name as nil if empty string --- lib/ohloh_scm/adapters/hg_adapter.rb | 15 ++++++++++----- test/unit/hg_commits_test.rb | 10 ++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/lib/ohloh_scm/adapters/hg_adapter.rb b/lib/ohloh_scm/adapters/hg_adapter.rb index 427668b1..eab19467 100644 --- a/lib/ohloh_scm/adapters/hg_adapter.rb +++ b/lib/ohloh_scm/adapters/hg_adapter.rb @@ -1,9 +1,14 @@ module OhlohScm::Adapters - class HgAdapter < AbstractAdapter - def english_name - "Mercurial" - end - end + class HgAdapter < AbstractAdapter + def english_name + "Mercurial" + end + + def branch_name=(branch_name) + branch_name = nil if branch_name.to_s.empty? + super + end + end end require_relative 'hg/validation' diff --git a/test/unit/hg_commits_test.rb b/test/unit/hg_commits_test.rb index 9c1eb29b..f2b09b6f 100644 --- a/test/unit/hg_commits_test.rb +++ b/test/unit/hg_commits_test.rb @@ -11,6 +11,16 @@ def test_commit_count end end + def test_commit_count_with_empty_branch + with_hg_repository('hg', '') do |hg| + assert_equal nil, hg.branch_name + assert_equal 5, hg.commit_count + assert_equal 3, hg.commit_count(:after => 'b14fa4692f949940bd1e28da6fb4617de2615484') + assert_equal 0, hg.commit_count(:after => '655f04cf6ad708ab58c7b941672dce09dd369a18') + end + end + + def test_commit_tokens with_hg_repository('hg') do |hg| assert_equal ['01101d8ef3cea7da9ac6e9a226d645f4418f05c9', From fef90852ee8b94e60bf0490ed38d0abadaa73f7b Mon Sep 17 00:00:00 2001 From: Priya Rani Date: Wed, 28 Dec 2016 18:24:16 +0530 Subject: [PATCH 198/219] OTWO-4466 Update version to 2.2.5 --- lib/ohloh_scm/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ohloh_scm/version.rb b/lib/ohloh_scm/version.rb index 16673b04..ed50eee1 100644 --- a/lib/ohloh_scm/version.rb +++ b/lib/ohloh_scm/version.rb @@ -1,5 +1,5 @@ module OhlohScm module Version - STRING = '2.2.3' + STRING = '2.2.5' end end From 60f796ec5b95850d6289acf732970ade723e5b97 Mon Sep 17 00:00:00 2001 From: Peter Degen-Portnoy Date: Wed, 11 Jan 2017 16:07:45 -0500 Subject: [PATCH 199/219] Add tags method to AbstractAdapter for api consistency --- .gitignore | 1 + lib/ohloh_scm/adapters/abstract/misc.rb | 14 +++++++++----- lib/ohloh_scm/version.rb | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index d411dd7f..b28b67a1 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ *.pyc pkg/ *.cache +.byebug* diff --git a/lib/ohloh_scm/adapters/abstract/misc.rb b/lib/ohloh_scm/adapters/abstract/misc.rb index 357ac0c3..a312ab15 100644 --- a/lib/ohloh_scm/adapters/abstract/misc.rb +++ b/lib/ohloh_scm/adapters/abstract/misc.rb @@ -1,9 +1,13 @@ module OhlohScm::Adapters - class AbstractAdapter + class AbstractAdapter - def is_merge_commit?(commit) - false - end + def is_merge_commit?(commit) + false + end - end + def tags + [] + end + + end end diff --git a/lib/ohloh_scm/version.rb b/lib/ohloh_scm/version.rb index ed50eee1..ea44a152 100644 --- a/lib/ohloh_scm/version.rb +++ b/lib/ohloh_scm/version.rb @@ -1,5 +1,5 @@ module OhlohScm module Version - STRING = '2.2.5' + STRING = '2.2.6' end end From 9acff30b46e560ed327d1213a49ee44b12090261 Mon Sep 17 00:00:00 2001 From: Priya Rani Date: Mon, 16 Jan 2017 15:54:03 +0530 Subject: [PATCH 200/219] OTWO-4588 Return empty svn tags if it is non-tagged repository --- lib/ohloh_scm/adapters/svn/misc.rb | 2 +- lib/ohloh_scm/version.rb | 2 +- test/unit/svn_misc_test.rb | 8 +++++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/ohloh_scm/adapters/svn/misc.rb b/lib/ohloh_scm/adapters/svn/misc.rb index 88b6b857..8fb77caa 100644 --- a/lib/ohloh_scm/adapters/svn/misc.rb +++ b/lib/ohloh_scm/adapters/svn/misc.rb @@ -149,7 +149,7 @@ def tags date_string = tag_string.split(' ').values_at(-4, -3, -2).join(' ') folder_and_rev = tag_string.split(' ').values_at(-1, 0).map { |v| v.chomp('/') } folder_and_rev << Time.parse(date_string) - end[1..-1] + end.drop(1) end class << self diff --git a/lib/ohloh_scm/version.rb b/lib/ohloh_scm/version.rb index ea44a152..42f8a836 100644 --- a/lib/ohloh_scm/version.rb +++ b/lib/ohloh_scm/version.rb @@ -1,5 +1,5 @@ module OhlohScm module Version - STRING = '2.2.6' + STRING = '2.2.7' end end diff --git a/test/unit/svn_misc_test.rb b/test/unit/svn_misc_test.rb index 5be326ba..f7f09753 100644 --- a/test/unit/svn_misc_test.rb +++ b/test/unit/svn_misc_test.rb @@ -117,5 +117,11 @@ def test_tags end end end - end + + def test_tags_with_non_tagged_repository + with_svn_repository('svn') do |svn| + assert_equal svn.tags, [] + end + end + end end From d26cc66c0cdc9e8ec5e13f91a2ce08b77babea35 Mon Sep 17 00:00:00 2001 From: Paddy Date: Mon, 16 Jan 2017 18:34:47 +0530 Subject: [PATCH 201/219] Set the default EPOCH timestamp when tag timestamp is empty --- lib/ohloh_scm/adapters/git/misc.rb | 1 + lib/ohloh_scm/version.rb | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ohloh_scm/adapters/git/misc.rb b/lib/ohloh_scm/adapters/git/misc.rb index 280ad254..dd61fb21 100644 --- a/lib/ohloh_scm/adapters/git/misc.rb +++ b/lib/ohloh_scm/adapters/git/misc.rb @@ -79,6 +79,7 @@ def tags tag_strings = run("cd #{url} && git tag --format='%(creatordate:iso-strict) %(objectname) %(refname)'").split(/\n/) tag_strings.map do |tag_string| timestamp_string, commit_hash, tag_path = tag_string.split(/\s/) + timestamp_string = '1970-01-01' if timestamp_string.strip.empty? timestamp = Time.parse(timestamp_string) tag_name = tag_path.gsub('refs/tags/', '') [tag_name, commit_hash, timestamp] diff --git a/lib/ohloh_scm/version.rb b/lib/ohloh_scm/version.rb index 42f8a836..fe13f47b 100644 --- a/lib/ohloh_scm/version.rb +++ b/lib/ohloh_scm/version.rb @@ -1,5 +1,5 @@ module OhlohScm module Version - STRING = '2.2.7' + STRING = '2.2.8' end end From 3a012f07786d790d94dc6265633723f948c8d2ec Mon Sep 17 00:00:00 2001 From: Daniel Rubio Date: Thu, 2 Feb 2017 16:44:33 +0000 Subject: [PATCH 202/219] Add UTF-8 enforcing for recurse_files --- lib/ohloh_scm/adapters/svn/commits.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ohloh_scm/adapters/svn/commits.rb b/lib/ohloh_scm/adapters/svn/commits.rb index 2b08f58e..1ce64079 100644 --- a/lib/ohloh_scm/adapters/svn/commits.rb +++ b/lib/ohloh_scm/adapters/svn/commits.rb @@ -186,7 +186,7 @@ def recurse_files(path=nil, revision=final_token || 'HEAD') files = [] stdout.each_line do |s| - s.chomp! + s.chomp!.force_encoding('UTF-8') files << s if s.length > 0 and s !~ /CVSROOT\// and s[-1..-1] != '/' end files.sort From 78d442e36a39c8350d093da59deedd3ff6cb4aad Mon Sep 17 00:00:00 2001 From: Daniel Rubio Date: Mon, 6 Feb 2017 20:58:21 +0000 Subject: [PATCH 203/219] Increment ohloh_scm version to 2.2.9 --- lib/ohloh_scm/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ohloh_scm/version.rb b/lib/ohloh_scm/version.rb index fe13f47b..eea79bae 100644 --- a/lib/ohloh_scm/version.rb +++ b/lib/ohloh_scm/version.rb @@ -1,5 +1,5 @@ module OhlohScm module Version - STRING = '2.2.8' + STRING = '2.2.9' end end From b95b1669251feb6950b53f211a4053c7343ba367 Mon Sep 17 00:00:00 2001 From: Priya Rani Date: Mon, 13 Feb 2017 15:39:22 +0530 Subject: [PATCH 204/219] OTWO-4616 Fetch SVN tags in xml format --- .travis.yml | 1 + lib/ohloh_scm/adapters/svn/misc.rb | 14 ++++++++------ ohloh_scm.gemspec | 1 + 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 664b1b74..b844736e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,5 +8,6 @@ install: - sh .install_multiple_scms.sh - sh .install_dependencies.sh - gem install posix-spawn + - gem install nokogiri -v 1.6.8 before_script: - cd $TRAVIS_BUILD_DIR diff --git a/lib/ohloh_scm/adapters/svn/misc.rb b/lib/ohloh_scm/adapters/svn/misc.rb index 8fb77caa..40069bd2 100644 --- a/lib/ohloh_scm/adapters/svn/misc.rb +++ b/lib/ohloh_scm/adapters/svn/misc.rb @@ -1,4 +1,5 @@ require 'open-uri' +require 'nokogiri' module OhlohScm::Adapters class SvnAdapter < AbstractAdapter @@ -144,12 +145,13 @@ def opt_auth # http://svn.apache.org/repos/asf/maven/plugin-testing/trunk # all have the same root value(https://svn.apache.org/repos/asf) def tags - tag_strings = `svn ls -v #{ base_path}/tags`.split(/\n/) - tag_strings.map do |tag_string| - date_string = tag_string.split(' ').values_at(-4, -3, -2).join(' ') - folder_and_rev = tag_string.split(' ').values_at(-1, 0).map { |v| v.chomp('/') } - folder_and_rev << Time.parse(date_string) - end.drop(1) + doc = Nokogiri::XML(`svn ls --xml #{ base_path}/tags`) + doc.xpath('//lists/list/entry').map do |entry| + tag_name = entry.xpath('name').text + revision = entry.xpath('commit').attr('revision').text + date_string = Time.parse(entry.xpath("commit/date").text) + [tag_name, revision, date_string] + end end class << self diff --git a/ohloh_scm.gemspec b/ohloh_scm.gemspec index 74ee9d8a..03fe35c2 100644 --- a/ohloh_scm.gemspec +++ b/ohloh_scm.gemspec @@ -18,4 +18,5 @@ Gem::Specification.new do |gem| gem.require_paths = %w(lib) gem.add_runtime_dependency 'posix-spawn', '~> 0.3' + gem.add_runtime_dependency 'nokogiri', '~> 1.6.8' end From 619e93f6cbf844d2652df67f6aec0278c5e6c0ce Mon Sep 17 00:00:00 2001 From: Priya Rani Date: Mon, 13 Feb 2017 19:02:57 +0530 Subject: [PATCH 205/219] OTWO-4616 Update version to 2.2.10 --- lib/ohloh_scm/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ohloh_scm/version.rb b/lib/ohloh_scm/version.rb index eea79bae..91a6c53d 100644 --- a/lib/ohloh_scm/version.rb +++ b/lib/ohloh_scm/version.rb @@ -1,5 +1,5 @@ module OhlohScm module Version - STRING = '2.2.9' + STRING = '2.2.10' end end From 8007795a51ae8a22f9cd3d375da38c8ded2d805b Mon Sep 17 00:00:00 2001 From: Priya Rani Date: Tue, 14 Feb 2017 10:38:53 +0530 Subject: [PATCH 206/219] OTWO-4616 Make dependency on nokogiri to not be overly strict --- ohloh_scm.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ohloh_scm.gemspec b/ohloh_scm.gemspec index 03fe35c2..f8caa14e 100644 --- a/ohloh_scm.gemspec +++ b/ohloh_scm.gemspec @@ -18,5 +18,5 @@ Gem::Specification.new do |gem| gem.require_paths = %w(lib) gem.add_runtime_dependency 'posix-spawn', '~> 0.3' - gem.add_runtime_dependency 'nokogiri', '~> 1.6.8' + gem.add_runtime_dependency 'nokogiri', '~> 1.6', '>= 1.6.8' end From 0e56c7b404e548882344c65b2a1ab38596623e2d Mon Sep 17 00:00:00 2001 From: Priya Rani Date: Wed, 15 Feb 2017 14:00:25 +0530 Subject: [PATCH 207/219] OTWO-4616 Add test case for fetching svn tags with whitespaces --- ...pre-revprop-change.tmpl => pre-revprop-change} | 3 ++- test/unit/svn_misc_test.rb | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) rename test/repositories/svn/hooks/{pre-revprop-change.tmpl => pre-revprop-change} (95%) mode change 100644 => 100755 diff --git a/test/repositories/svn/hooks/pre-revprop-change.tmpl b/test/repositories/svn/hooks/pre-revprop-change old mode 100644 new mode 100755 similarity index 95% rename from test/repositories/svn/hooks/pre-revprop-change.tmpl rename to test/repositories/svn/hooks/pre-revprop-change index 2f2de984..4768dd4c --- a/test/repositories/svn/hooks/pre-revprop-change.tmpl +++ b/test/repositories/svn/hooks/pre-revprop-change @@ -61,6 +61,7 @@ PROPNAME="$4" ACTION="$5" if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:log" ]; then exit 0; fi +if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:date" ]; then exit 0; fi -echo "Changing revision properties other than svn:log is prohibited" >&2 +echo "Only svn:log and svn:date revision properties can be changed" >&2 exit 1 diff --git a/test/unit/svn_misc_test.rb b/test/unit/svn_misc_test.rb index f7f09753..afdad09b 100644 --- a/test/unit/svn_misc_test.rb +++ b/test/unit/svn_misc_test.rb @@ -118,6 +118,21 @@ def test_tags end end + def test_tags_with_whitespaces + with_svn_repository('svn', 'trunk') do |source_scm| + OhlohScm::ScratchDir.new do |svn_working_folder| + folder_name = source_scm.root.slice(/[^\/]+\/?\Z/) + system "cd #{ svn_working_folder } && svn co #{ source_scm.root } && cd #{ folder_name } && + mkdir -p #{ source_scm.root.gsub(/^file:../, '') }/db/transactions + svn copy trunk tags/'HL7 engine' && svn commit -m 'v2.0' && svn update && svn propset svn:date --revprop -r 'HEAD' 2016-02-12T00:44:04.921324Z" + + assert_equal(['HL7 engine', '6'], source_scm.tags.first[0..1]) + # Avoid millisecond comparision. + assert_equal('2016-02-12', source_scm.tags.first[-1].strftime('%F')) + end + end + end + def test_tags_with_non_tagged_repository with_svn_repository('svn') do |svn| assert_equal svn.tags, [] From 4314ebe7738b7d27818187a23739cbe5bb6c8881 Mon Sep 17 00:00:00 2001 From: Paddy Date: Tue, 11 Apr 2017 09:37:42 +0530 Subject: [PATCH 208/219] OTWO-4722 Implment Export Tag Method for Bzr Repo --- lib/ohloh_scm/adapters/bzr/misc.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/ohloh_scm/adapters/bzr/misc.rb b/lib/ohloh_scm/adapters/bzr/misc.rb index c9eb65ed..bf9cac1d 100644 --- a/lib/ohloh_scm/adapters/bzr/misc.rb +++ b/lib/ohloh_scm/adapters/bzr/misc.rb @@ -30,6 +30,10 @@ def is_merge_commit?(commit) parent_tokens(commit).size > 1 end + def export_tag(dest_dir, tag_name) + run "cd '#{path}' && bzr export -r tag:#{tag_name} #{dest_dir}" + end + def export(dest_dir, token=head_token) # Unlike other SCMs, Bzr doesn't simply place the contents into dest_dir. # It actually *creates* dest_dir. Since it should already exist at this point, From f8e7412046cc89c51763bebdb552683fe4591856 Mon Sep 17 00:00:00 2001 From: Paddy Date: Tue, 11 Apr 2017 14:55:48 +0530 Subject: [PATCH 209/219] Updated the version to 2.2.11 --- lib/ohloh_scm/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ohloh_scm/version.rb b/lib/ohloh_scm/version.rb index 91a6c53d..e847bd35 100644 --- a/lib/ohloh_scm/version.rb +++ b/lib/ohloh_scm/version.rb @@ -1,5 +1,5 @@ module OhlohScm module Version - STRING = '2.2.10' + STRING = '2.2.11' end end From 33b807753bd1b6cb7ac3340b0c7ff3014ebe6a3b Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Wed, 19 Apr 2017 13:27:07 +0530 Subject: [PATCH 210/219] OTWO-4428 Archive svn branching test repo --- test/repositories/svn_with_branching.tgz | Bin 0 -> 7704 bytes .../svn_with_branching/README.txt | 5 -- .../svn_with_branching/conf/authz | 21 ------ .../svn_with_branching/conf/passwd | 8 -- .../svn_with_branching/conf/svnserve.conf | 30 -------- .../svn_with_branching/db/current | 1 - .../repositories/svn_with_branching/db/format | 1 - .../svn_with_branching/db/fs-type | 1 - .../svn_with_branching/db/revprops/0 | 5 -- .../svn_with_branching/db/revprops/1 | 13 ---- .../svn_with_branching/db/revprops/2 | 13 ---- .../svn_with_branching/db/revprops/3 | 13 ---- .../svn_with_branching/db/revprops/4 | 13 ---- .../svn_with_branching/db/revprops/5 | 13 ---- .../svn_with_branching/db/revprops/6 | 13 ---- .../svn_with_branching/db/revprops/7 | 13 ---- .../svn_with_branching/db/revprops/8 | 13 ---- .../svn_with_branching/db/revprops/9 | 13 ---- .../repositories/svn_with_branching/db/revs/0 | 11 --- .../repositories/svn_with_branching/db/revs/1 | 49 ------------ .../repositories/svn_with_branching/db/revs/2 | Bin 681 -> 0 bytes .../repositories/svn_with_branching/db/revs/3 | 23 ------ .../repositories/svn_with_branching/db/revs/4 | 35 --------- .../repositories/svn_with_branching/db/revs/5 | Bin 1041 -> 0 bytes .../repositories/svn_with_branching/db/revs/6 | 54 -------------- .../repositories/svn_with_branching/db/revs/7 | 23 ------ .../repositories/svn_with_branching/db/revs/8 | 35 --------- .../repositories/svn_with_branching/db/revs/9 | Bin 781 -> 0 bytes test/repositories/svn_with_branching/db/uuid | 1 - .../svn_with_branching/db/write-lock | 0 test/repositories/svn_with_branching/format | 1 - .../svn_with_branching/hooks/post-commit.tmpl | 51 ------------- .../svn_with_branching/hooks/post-lock.tmpl | 44 ----------- .../hooks/post-revprop-change.tmpl | 56 -------------- .../svn_with_branching/hooks/post-unlock.tmpl | 42 ----------- .../svn_with_branching/hooks/pre-commit.tmpl | 70 ------------------ .../svn_with_branching/hooks/pre-lock.tmpl | 64 ---------------- .../hooks/pre-revprop-change.tmpl | 66 ----------------- .../svn_with_branching/hooks/pre-unlock.tmpl | 60 --------------- .../hooks/start-commit.tmpl | 54 -------------- .../svn_with_branching/locks/db-logs.lock | 3 - .../svn_with_branching/locks/db.lock | 3 - 42 files changed, 934 deletions(-) create mode 100644 test/repositories/svn_with_branching.tgz delete mode 100644 test/repositories/svn_with_branching/README.txt delete mode 100644 test/repositories/svn_with_branching/conf/authz delete mode 100644 test/repositories/svn_with_branching/conf/passwd delete mode 100644 test/repositories/svn_with_branching/conf/svnserve.conf delete mode 100644 test/repositories/svn_with_branching/db/current delete mode 100644 test/repositories/svn_with_branching/db/format delete mode 100644 test/repositories/svn_with_branching/db/fs-type delete mode 100644 test/repositories/svn_with_branching/db/revprops/0 delete mode 100644 test/repositories/svn_with_branching/db/revprops/1 delete mode 100644 test/repositories/svn_with_branching/db/revprops/2 delete mode 100644 test/repositories/svn_with_branching/db/revprops/3 delete mode 100644 test/repositories/svn_with_branching/db/revprops/4 delete mode 100644 test/repositories/svn_with_branching/db/revprops/5 delete mode 100644 test/repositories/svn_with_branching/db/revprops/6 delete mode 100644 test/repositories/svn_with_branching/db/revprops/7 delete mode 100644 test/repositories/svn_with_branching/db/revprops/8 delete mode 100644 test/repositories/svn_with_branching/db/revprops/9 delete mode 100644 test/repositories/svn_with_branching/db/revs/0 delete mode 100644 test/repositories/svn_with_branching/db/revs/1 delete mode 100644 test/repositories/svn_with_branching/db/revs/2 delete mode 100644 test/repositories/svn_with_branching/db/revs/3 delete mode 100644 test/repositories/svn_with_branching/db/revs/4 delete mode 100644 test/repositories/svn_with_branching/db/revs/5 delete mode 100644 test/repositories/svn_with_branching/db/revs/6 delete mode 100644 test/repositories/svn_with_branching/db/revs/7 delete mode 100644 test/repositories/svn_with_branching/db/revs/8 delete mode 100644 test/repositories/svn_with_branching/db/revs/9 delete mode 100644 test/repositories/svn_with_branching/db/uuid delete mode 100644 test/repositories/svn_with_branching/db/write-lock delete mode 100644 test/repositories/svn_with_branching/format delete mode 100644 test/repositories/svn_with_branching/hooks/post-commit.tmpl delete mode 100644 test/repositories/svn_with_branching/hooks/post-lock.tmpl delete mode 100644 test/repositories/svn_with_branching/hooks/post-revprop-change.tmpl delete mode 100644 test/repositories/svn_with_branching/hooks/post-unlock.tmpl delete mode 100644 test/repositories/svn_with_branching/hooks/pre-commit.tmpl delete mode 100644 test/repositories/svn_with_branching/hooks/pre-lock.tmpl delete mode 100644 test/repositories/svn_with_branching/hooks/pre-revprop-change.tmpl delete mode 100644 test/repositories/svn_with_branching/hooks/pre-unlock.tmpl delete mode 100644 test/repositories/svn_with_branching/hooks/start-commit.tmpl delete mode 100644 test/repositories/svn_with_branching/locks/db-logs.lock delete mode 100644 test/repositories/svn_with_branching/locks/db.lock diff --git a/test/repositories/svn_with_branching.tgz b/test/repositories/svn_with_branching.tgz new file mode 100644 index 0000000000000000000000000000000000000000..29e46f103891d7a3da6106d223f626629106acaa GIT binary patch literal 7704 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 DE>$Z8 diff --git a/test/repositories/svn_with_branching/db/revs/6 b/test/repositories/svn_with_branching/db/revs/6 deleted file mode 100644 index 3350b67b..00000000 --- a/test/repositories/svn_with_branching/db/revs/6 +++ /dev/null @@ -1,54 +0,0 @@ -id: 5.3.r6/0 -type: file -pred: 5.2.r5/85 -count: 1 -text: 5 0 72 60 d032627b99a6bcef7d6061d4142e5257 -cpath: /trunk/goodbyeworld.c -copyfrom: 5 /branches/development/goodbyeworld.c - -PLAIN -K 14 -goodbyeworld.c -V 13 -file 5.3.r6/0 -K 12 -helloworld.c -V 14 -file 4.0.r2/83 -END -ENDREP -id: 3.1.r6/271 -type: dir -pred: 3.1.r4/0 -count: 3 -text: 6 177 81 81 2e2ef6d7c38eb0716e6983a582e3b7ae -cpath: /trunk -copyroot: 4 /trunk - -PLAIN -K 8 -branches -V 14 -dir 1.0.r5/545 -K 4 -tags -V 14 -dir 2.0.r1/126 -K 5 -trunk -V 14 -dir 3.1.r6/271 -END -ENDREP -id: 0.0.r6/514 -type: dir -pred: 0.0.r5/785 -count: 6 -text: 6 405 96 96 2809ce963ca9b8638c46c1ef54b172e2 -cpath: / -copyroot: 0 / - -5._0.t5-1 add false false /trunk/goodbyeworld.c -5 /branches/development/goodbyeworld.c - -514 640 diff --git a/test/repositories/svn_with_branching/db/revs/7 b/test/repositories/svn_with_branching/db/revs/7 deleted file mode 100644 index 194fae0c..00000000 --- a/test/repositories/svn_with_branching/db/revs/7 +++ /dev/null @@ -1,23 +0,0 @@ -PLAIN -K 8 -branches -V 14 -dir 1.0.r5/545 -K 4 -tags -V 14 -dir 2.0.r1/126 -END -ENDREP -id: 0.0.r7/79 -type: dir -pred: 0.0.r6/514 -count: 7 -text: 7 0 66 66 2a73fc9e7df4b41d10d586d73b249c73 -cpath: / -copyroot: 0 / - -3.1.r6/271 delete false false /trunk - - -79 202 diff --git a/test/repositories/svn_with_branching/db/revs/8 b/test/repositories/svn_with_branching/db/revs/8 deleted file mode 100644 index 6a380351..00000000 --- a/test/repositories/svn_with_branching/db/revs/8 +++ /dev/null @@ -1,35 +0,0 @@ -id: 3.4.r8/0 -type: dir -pred: 3.2.r5/342 -count: 4 -text: 5 247 82 82 c485e5f340786ada064a13ca1c86ea5c -cpath: /trunk -copyfrom: 7 /branches/development - -PLAIN -K 8 -branches -V 14 -dir 1.0.r5/545 -K 4 -tags -V 14 -dir 2.0.r1/126 -K 5 -trunk -V 12 -dir 3.4.r8/0 -END -ENDREP -id: 0.0.r8/256 -type: dir -pred: 0.0.r7/79 -count: 8 -text: 8 149 94 94 a404e0a35955f83c7cf610ed21dc7e2b -cpath: / -copyroot: 0 / - -3._0.t7-1 add false false /trunk -7 /branches/development - -256 381 diff --git a/test/repositories/svn_with_branching/db/revs/9 b/test/repositories/svn_with_branching/db/revs/9 deleted file mode 100644 index 10a052795877107c151a52d71c4b1b2e31308569..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 781 zcmaLVU2EGg6b9gZT1KeNrr*FQ45l7O(2oHaq9>-F9$wmsIb85WKGH zErw;#cI&lo2UwfBJw1aT@M6=~?NFYcT>7TzUgNi}Z`{i-?aA3&_zAQ5#i!X4YFA*I zq)D#{V;qM4#ur%DjfYL|$BZUDCrW_rcI{9ggTa3fPaP_1j=4saQp!_jwcuQq)_P{L z%qlKe?sAc>z;4V?6-b7D*M22cY%_LAY&dkY@4GIXrw%#5^6LD<96lmT;kN7CYVVKJ zH}PF8hce+wFNuDrf!<4+An!o~gN*4EIA?1PW>i!@eBSq*D93~E6E(2D?#hh|w zX_cbRGnHp~=E~eCD_2fXrp;sWf0YVWy=iUbw=nWT5oAfYbV+0yc_|F$b`tU!GQxNk z!cZ<=>hG-+*dJsX_h}-v`ine9ig1}7(fR?MDvdge%Tv#U){L1l71Rr@sCP=_mNAi= nQa_+4UWx=DeuhE4VYu#GUG6bd_E?%`>;L&r0ECX1^AvsoHNM%3 diff --git a/test/repositories/svn_with_branching/db/uuid b/test/repositories/svn_with_branching/db/uuid deleted file mode 100644 index 5a6a233a..00000000 --- a/test/repositories/svn_with_branching/db/uuid +++ /dev/null @@ -1 +0,0 @@ -150330a3-0ae1-4e76-adb7-e1f1a37d4ad8 diff --git a/test/repositories/svn_with_branching/db/write-lock b/test/repositories/svn_with_branching/db/write-lock deleted file mode 100644 index e69de29b..00000000 diff --git a/test/repositories/svn_with_branching/format b/test/repositories/svn_with_branching/format deleted file mode 100644 index 7ed6ff82..00000000 --- a/test/repositories/svn_with_branching/format +++ /dev/null @@ -1 +0,0 @@ -5 diff --git a/test/repositories/svn_with_branching/hooks/post-commit.tmpl b/test/repositories/svn_with_branching/hooks/post-commit.tmpl deleted file mode 100644 index b8345c6f..00000000 --- a/test/repositories/svn_with_branching/hooks/post-commit.tmpl +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/sh - -# POST-COMMIT HOOK -# -# The post-commit hook is invoked after a commit. Subversion runs -# this hook by invoking a program (script, executable, binary, etc.) -# named 'post-commit' (for which this file is a template) with the -# following ordered arguments: -# -# [1] REPOS-PATH (the path to this repository) -# [2] REV (the number of the revision just committed) -# -# The default working directory for the invocation is undefined, so -# the program should set one explicitly if it cares. -# -# Because the commit has already completed and cannot be undone, -# the exit code of the hook program is ignored. The hook program -# can use the 'svnlook' utility to help it examine the -# newly-committed tree. -# -# On a Unix system, the normal procedure is to have 'post-commit' -# invoke other programs to do the real work, though it may do the -# work itself too. -# -# Note that 'post-commit' must be executable by the user(s) who will -# invoke it (typically the user httpd runs as), and that user must -# have filesystem-level permission to access the repository. -# -# On a Windows system, you should name the hook program -# 'post-commit.bat' or 'post-commit.exe', -# but the basic idea is the same. -# -# The hook program typically does not inherit the environment of -# its parent process. For example, a common problem is for the -# PATH environment variable to not be set to its usual value, so -# that subprograms fail to launch unless invoked via absolute path. -# If you're having unexpected problems with a hook program, the -# culprit may be unusual (or missing) environment variables. -# -# Here is an example hook script, for a Unix /bin/sh interpreter. -# For more examples and pre-written hooks, see those in -# the Subversion repository at -# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and -# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/ - - -REPOS="$1" -REV="$2" - -commit-email.pl "$REPOS" "$REV" commit-watchers@example.org -log-commit.py --repository "$REPOS" --revision "$REV" diff --git a/test/repositories/svn_with_branching/hooks/post-lock.tmpl b/test/repositories/svn_with_branching/hooks/post-lock.tmpl deleted file mode 100644 index c779f11d..00000000 --- a/test/repositories/svn_with_branching/hooks/post-lock.tmpl +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/sh - -# POST-LOCK HOOK -# -# The post-lock hook is run after a path is locked. Subversion runs -# this hook by invoking a program (script, executable, binary, etc.) -# named 'post-lock' (for which this file is a template) with the -# following ordered arguments: -# -# [1] REPOS-PATH (the path to this repository) -# [2] USER (the user who created the lock) -# -# The paths that were just locked are passed to the hook via STDIN (as -# of Subversion 1.2, only one path is passed per invocation, but the -# plan is to pass all locked paths at once, so the hook program -# should be written accordingly). -# -# The default working directory for the invocation is undefined, so -# the program should set one explicitly if it cares. -# -# Because the lock has already been created and cannot be undone, -# the exit code of the hook program is ignored. The hook program -# can use the 'svnlook' utility to help it examine the -# newly-created lock. -# -# On a Unix system, the normal procedure is to have 'post-lock' -# invoke other programs to do the real work, though it may do the -# work itself too. -# -# Note that 'post-lock' must be executable by the user(s) who will -# invoke it (typically the user httpd runs as), and that user must -# have filesystem-level permission to access the repository. -# -# On a Windows system, you should name the hook program -# 'post-lock.bat' or 'post-lock.exe', -# but the basic idea is the same. -# -# Here is an example hook script, for a Unix /bin/sh interpreter: - -REPOS="$1" -USER="$2" - -# Send email to interested parties, let them know a lock was created: -mailer.py lock "$REPOS" "$USER" /path/to/mailer.conf diff --git a/test/repositories/svn_with_branching/hooks/post-revprop-change.tmpl b/test/repositories/svn_with_branching/hooks/post-revprop-change.tmpl deleted file mode 100644 index 2ed8b9ab..00000000 --- a/test/repositories/svn_with_branching/hooks/post-revprop-change.tmpl +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/sh - -# POST-REVPROP-CHANGE HOOK -# -# The post-revprop-change hook is invoked after a revision property -# has been added, modified or deleted. Subversion runs this hook by -# invoking a program (script, executable, binary, etc.) named -# 'post-revprop-change' (for which this file is a template), with the -# following ordered arguments: -# -# [1] REPOS-PATH (the path to this repository) -# [2] REV (the revision that was tweaked) -# [3] USER (the username of the person tweaking the property) -# [4] PROPNAME (the property that was changed) -# [5] ACTION (the property was 'A'dded, 'M'odified, or 'D'eleted) -# -# [STDIN] PROPVAL ** the old property value is passed via STDIN. -# -# Because the propchange has already completed and cannot be undone, -# the exit code of the hook program is ignored. The hook program -# can use the 'svnlook' utility to help it examine the -# new property value. -# -# On a Unix system, the normal procedure is to have 'post-revprop-change' -# invoke other programs to do the real work, though it may do the -# work itself too. -# -# Note that 'post-revprop-change' must be executable by the user(s) who will -# invoke it (typically the user httpd runs as), and that user must -# have filesystem-level permission to access the repository. -# -# On a Windows system, you should name the hook program -# 'post-revprop-change.bat' or 'post-revprop-change.exe', -# but the basic idea is the same. -# -# The hook program typically does not inherit the environment of -# its parent process. For example, a common problem is for the -# PATH environment variable to not be set to its usual value, so -# that subprograms fail to launch unless invoked via absolute path. -# If you're having unexpected problems with a hook program, the -# culprit may be unusual (or missing) environment variables. -# -# Here is an example hook script, for a Unix /bin/sh interpreter. -# For more examples and pre-written hooks, see those in -# the Subversion repository at -# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and -# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/ - - -REPOS="$1" -REV="$2" -USER="$3" -PROPNAME="$4" -ACTION="$5" - -propchange-email.pl "$REPOS" "$REV" "$USER" "$PROPNAME" watchers@example.org diff --git a/test/repositories/svn_with_branching/hooks/post-unlock.tmpl b/test/repositories/svn_with_branching/hooks/post-unlock.tmpl deleted file mode 100644 index ae95c4bd..00000000 --- a/test/repositories/svn_with_branching/hooks/post-unlock.tmpl +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/sh - -# POST-UNLOCK HOOK -# -# The post-unlock hook runs after a path is unlocked. Subversion runs -# this hook by invoking a program (script, executable, binary, etc.) -# named 'post-unlock' (for which this file is a template) with the -# following ordered arguments: -# -# [1] REPOS-PATH (the path to this repository) -# [2] USER (the user who destroyed the lock) -# -# The paths that were just unlocked are passed to the hook via STDIN -# (as of Subversion 1.2, only one path is passed per invocation, but -# the plan is to pass all unlocked paths at once, so the hook program -# should be written accordingly). -# -# The default working directory for the invocation is undefined, so -# the program should set one explicitly if it cares. -# -# Because the lock has already been destroyed and cannot be undone, -# the exit code of the hook program is ignored. -# -# On a Unix system, the normal procedure is to have 'post-unlock' -# invoke other programs to do the real work, though it may do the -# work itself too. -# -# Note that 'post-unlock' must be executable by the user(s) who will -# invoke it (typically the user httpd runs as), and that user must -# have filesystem-level permission to access the repository. -# -# On a Windows system, you should name the hook program -# 'post-unlock.bat' or 'post-unlock.exe', -# but the basic idea is the same. -# -# Here is an example hook script, for a Unix /bin/sh interpreter: - -REPOS="$1" -USER="$2" - -# Send email to interested parties, let them know a lock was removed: -mailer.py unlock "$REPOS" "$USER" /path/to/mailer.conf diff --git a/test/repositories/svn_with_branching/hooks/pre-commit.tmpl b/test/repositories/svn_with_branching/hooks/pre-commit.tmpl deleted file mode 100644 index ffecfa88..00000000 --- a/test/repositories/svn_with_branching/hooks/pre-commit.tmpl +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/sh - -# PRE-COMMIT HOOK -# -# The pre-commit hook is invoked before a Subversion txn is -# committed. Subversion runs this hook by invoking a program -# (script, executable, binary, etc.) named 'pre-commit' (for which -# this file is a template), with the following ordered arguments: -# -# [1] REPOS-PATH (the path to this repository) -# [2] TXN-NAME (the name of the txn about to be committed) -# -# The default working directory for the invocation is undefined, so -# the program should set one explicitly if it cares. -# -# If the hook program exits with success, the txn is committed; but -# if it exits with failure (non-zero), the txn is aborted, no commit -# takes place, and STDERR is returned to the client. The hook -# program can use the 'svnlook' utility to help it examine the txn. -# -# On a Unix system, the normal procedure is to have 'pre-commit' -# invoke other programs to do the real work, though it may do the -# work itself too. -# -# *** NOTE: THE HOOK PROGRAM MUST NOT MODIFY THE TXN, EXCEPT *** -# *** FOR REVISION PROPERTIES (like svn:log or svn:author). *** -# -# This is why we recommend using the read-only 'svnlook' utility. -# In the future, Subversion may enforce the rule that pre-commit -# hooks should not modify the versioned data in txns, or else come -# up with a mechanism to make it safe to do so (by informing the -# committing client of the changes). However, right now neither -# mechanism is implemented, so hook writers just have to be careful. -# -# Note that 'pre-commit' must be executable by the user(s) who will -# invoke it (typically the user httpd runs as), and that user must -# have filesystem-level permission to access the repository. -# -# On a Windows system, you should name the hook program -# 'pre-commit.bat' or 'pre-commit.exe', -# but the basic idea is the same. -# -# The hook program typically does not inherit the environment of -# its parent process. For example, a common problem is for the -# PATH environment variable to not be set to its usual value, so -# that subprograms fail to launch unless invoked via absolute path. -# If you're having unexpected problems with a hook program, the -# culprit may be unusual (or missing) environment variables. -# -# Here is an example hook script, for a Unix /bin/sh interpreter. -# For more examples and pre-written hooks, see those in -# the Subversion repository at -# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and -# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/ - - -REPOS="$1" -TXN="$2" - -# Make sure that the log message contains some text. -SVNLOOK=/usr/local/bin/svnlook -$SVNLOOK log -t "$TXN" "$REPOS" | \ - grep "[a-zA-Z0-9]" > /dev/null || exit 1 - -# Check that the author of this commit has the rights to perform -# the commit on the files and directories being modified. -commit-access-control.pl "$REPOS" "$TXN" commit-access-control.cfg || exit 1 - -# All checks passed, so allow the commit. -exit 0 diff --git a/test/repositories/svn_with_branching/hooks/pre-lock.tmpl b/test/repositories/svn_with_branching/hooks/pre-lock.tmpl deleted file mode 100644 index b0d67a92..00000000 --- a/test/repositories/svn_with_branching/hooks/pre-lock.tmpl +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/sh - -# PRE-LOCK HOOK -# -# The pre-lock hook is invoked before an exclusive lock is -# created. Subversion runs this hook by invoking a program -# (script, executable, binary, etc.) named 'pre-lock' (for which -# this file is a template), with the following ordered arguments: -# -# [1] REPOS-PATH (the path to this repository) -# [2] PATH (the path in the repository about to be locked) -# [3] USER (the user creating the lock) -# -# The default working directory for the invocation is undefined, so -# the program should set one explicitly if it cares. -# -# If the hook program exits with success, the lock is created; but -# if it exits with failure (non-zero), the lock action is aborted -# and STDERR is returned to the client. - -# On a Unix system, the normal procedure is to have 'pre-lock' -# invoke other programs to do the real work, though it may do the -# work itself too. -# -# Note that 'pre-lock' must be executable by the user(s) who will -# invoke it (typically the user httpd runs as), and that user must -# have filesystem-level permission to access the repository. -# -# On a Windows system, you should name the hook program -# 'pre-lock.bat' or 'pre-lock.exe', -# but the basic idea is the same. -# -# Here is an example hook script, for a Unix /bin/sh interpreter: - -REPOS="$1" -PATH="$2" -USER="$3" - -# If a lock exists and is owned by a different person, don't allow it -# to be stolen (e.g., with 'svn lock --force ...'). - -# (Maybe this script could send email to the lock owner?) -SVNLOOK=/usr/local/bin/svnlook -GREP=/bin/grep -SED=/bin/sed - -LOCK_OWNER=`$SVNLOOK lock "$REPOS" "$PATH" | \ - $GREP '^Owner: ' | $SED 's/Owner: //'` - -# If we get no result from svnlook, there's no lock, allow the lock to -# happen: -if [ "$LOCK_OWNER" = "" ]; then - exit 0 -fi - -# If the person locking matches the lock's owner, allow the lock to -# happen: -if [ "$LOCK_OWNER" = "$USER" ]; then - exit 0 -fi - -# Otherwise, we've got an owner mismatch, so return failure: -echo "Error: $PATH already locked by ${LOCK_OWNER}." 1>&2 -exit 1 diff --git a/test/repositories/svn_with_branching/hooks/pre-revprop-change.tmpl b/test/repositories/svn_with_branching/hooks/pre-revprop-change.tmpl deleted file mode 100644 index 2f2de984..00000000 --- a/test/repositories/svn_with_branching/hooks/pre-revprop-change.tmpl +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/sh - -# PRE-REVPROP-CHANGE HOOK -# -# The pre-revprop-change hook is invoked before a revision property -# is added, modified or deleted. Subversion runs this hook by invoking -# a program (script, executable, binary, etc.) named 'pre-revprop-change' -# (for which this file is a template), with the following ordered -# arguments: -# -# [1] REPOS-PATH (the path to this repository) -# [2] REVISION (the revision being tweaked) -# [3] USER (the username of the person tweaking the property) -# [4] PROPNAME (the property being set on the revision) -# [5] ACTION (the property is being 'A'dded, 'M'odified, or 'D'eleted) -# -# [STDIN] PROPVAL ** the new property value is passed via STDIN. -# -# If the hook program exits with success, the propchange happens; but -# if it exits with failure (non-zero), the propchange doesn't happen. -# The hook program can use the 'svnlook' utility to examine the -# existing value of the revision property. -# -# WARNING: unlike other hooks, this hook MUST exist for revision -# properties to be changed. If the hook does not exist, Subversion -# will behave as if the hook were present, but failed. The reason -# for this is that revision properties are UNVERSIONED, meaning that -# a successful propchange is destructive; the old value is gone -# forever. We recommend the hook back up the old value somewhere. -# -# On a Unix system, the normal procedure is to have 'pre-revprop-change' -# invoke other programs to do the real work, though it may do the -# work itself too. -# -# Note that 'pre-revprop-change' must be executable by the user(s) who will -# invoke it (typically the user httpd runs as), and that user must -# have filesystem-level permission to access the repository. -# -# On a Windows system, you should name the hook program -# 'pre-revprop-change.bat' or 'pre-revprop-change.exe', -# but the basic idea is the same. -# -# The hook program typically does not inherit the environment of -# its parent process. For example, a common problem is for the -# PATH environment variable to not be set to its usual value, so -# that subprograms fail to launch unless invoked via absolute path. -# If you're having unexpected problems with a hook program, the -# culprit may be unusual (or missing) environment variables. -# -# Here is an example hook script, for a Unix /bin/sh interpreter. -# For more examples and pre-written hooks, see those in -# the Subversion repository at -# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and -# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/ - - -REPOS="$1" -REV="$2" -USER="$3" -PROPNAME="$4" -ACTION="$5" - -if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:log" ]; then exit 0; fi - -echo "Changing revision properties other than svn:log is prohibited" >&2 -exit 1 diff --git a/test/repositories/svn_with_branching/hooks/pre-unlock.tmpl b/test/repositories/svn_with_branching/hooks/pre-unlock.tmpl deleted file mode 100644 index 24c7f440..00000000 --- a/test/repositories/svn_with_branching/hooks/pre-unlock.tmpl +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/sh - -# PRE-UNLOCK HOOK -# -# The pre-unlock hook is invoked before an exclusive lock is -# destroyed. Subversion runs this hook by invoking a program -# (script, executable, binary, etc.) named 'pre-unlock' (for which -# this file is a template), with the following ordered arguments: -# -# [1] REPOS-PATH (the path to this repository) -# [2] PATH (the path in the repository about to be unlocked) -# [3] USER (the user destroying the lock) -# -# The default working directory for the invocation is undefined, so -# the program should set one explicitly if it cares. -# -# If the hook program exits with success, the lock is destroyed; but -# if it exits with failure (non-zero), the unlock action is aborted -# and STDERR is returned to the client. - -# On a Unix system, the normal procedure is to have 'pre-unlock' -# invoke other programs to do the real work, though it may do the -# work itself too. -# -# Note that 'pre-unlock' must be executable by the user(s) who will -# invoke it (typically the user httpd runs as), and that user must -# have filesystem-level permission to access the repository. -# -# On a Windows system, you should name the hook program -# 'pre-unlock.bat' or 'pre-unlock.exe', -# but the basic idea is the same. -# -# Here is an example hook script, for a Unix /bin/sh interpreter: - -REPOS="$1" -PATH="$2" -USER="$3" - -# If a lock is owned by a different person, don't allow it be broken. -# (Maybe this script could send email to the lock owner?) - -SVNLOOK=/usr/local/bin/svnlook -GREP=/bin/grep -SED=/bin/sed - -LOCK_OWNER=`$SVNLOOK lock "$REPOS" "$PATH" | \ - $GREP '^Owner: ' | $SED 's/Owner: //'` - -# If we get no result from svnlook, there's no lock, return success: -if [ "$LOCK_OWNER" = "" ]; then - exit 0 -fi -# If the person unlocking matches the lock's owner, return success: -if [ "$LOCK_OWNER" = "$USER" ]; then - exit 0 -fi - -# Otherwise, we've got an owner mismatch, so return failure: -echo "Error: $PATH locked by ${LOCK_OWNER}." 1>&2 -exit 1 diff --git a/test/repositories/svn_with_branching/hooks/start-commit.tmpl b/test/repositories/svn_with_branching/hooks/start-commit.tmpl deleted file mode 100644 index 348d7063..00000000 --- a/test/repositories/svn_with_branching/hooks/start-commit.tmpl +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/sh - -# START-COMMIT HOOK -# -# The start-commit hook is invoked before a Subversion txn is created -# in the process of doing a commit. Subversion runs this hook -# by invoking a program (script, executable, binary, etc.) named -# 'start-commit' (for which this file is a template) -# with the following ordered arguments: -# -# [1] REPOS-PATH (the path to this repository) -# [2] USER (the authenticated user attempting to commit) -# -# The default working directory for the invocation is undefined, so -# the program should set one explicitly if it cares. -# -# If the hook program exits with success, the commit continues; but -# if it exits with failure (non-zero), the commit is stopped before -# a Subversion txn is created, and STDERR is returned to the client. -# -# On a Unix system, the normal procedure is to have 'start-commit' -# invoke other programs to do the real work, though it may do the -# work itself too. -# -# Note that 'start-commit' must be executable by the user(s) who will -# invoke it (typically the user httpd runs as), and that user must -# have filesystem-level permission to access the repository. -# -# On a Windows system, you should name the hook program -# 'start-commit.bat' or 'start-commit.exe', -# but the basic idea is the same. -# -# The hook program typically does not inherit the environment of -# its parent process. For example, a common problem is for the -# PATH environment variable to not be set to its usual value, so -# that subprograms fail to launch unless invoked via absolute path. -# If you're having unexpected problems with a hook program, the -# culprit may be unusual (or missing) environment variables. -# -# Here is an example hook script, for a Unix /bin/sh interpreter. -# For more examples and pre-written hooks, see those in -# the Subversion repository at -# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and -# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/ - - -REPOS="$1" -USER="$2" - -commit-allower.pl --repository "$REPOS" --user "$USER" || exit 1 -special-auth-check.py --user "$USER" --auth-level 3 || exit 1 - -# All checks passed, so allow the commit. -exit 0 diff --git a/test/repositories/svn_with_branching/locks/db-logs.lock b/test/repositories/svn_with_branching/locks/db-logs.lock deleted file mode 100644 index 20dd6369..00000000 --- a/test/repositories/svn_with_branching/locks/db-logs.lock +++ /dev/null @@ -1,3 +0,0 @@ -This file is not used by Subversion 1.3.x or later. -However, its existence is required for compatibility with -Subversion 1.2.x or earlier. diff --git a/test/repositories/svn_with_branching/locks/db.lock b/test/repositories/svn_with_branching/locks/db.lock deleted file mode 100644 index 20dd6369..00000000 --- a/test/repositories/svn_with_branching/locks/db.lock +++ /dev/null @@ -1,3 +0,0 @@ -This file is not used by Subversion 1.3.x or later. -However, its existence is required for compatibility with -Subversion 1.2.x or earlier. From 9a9a7b1302f3951a8f4372ac5c06cd9954da6f62 Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Wed, 19 Apr 2017 13:27:15 +0530 Subject: [PATCH 211/219] OTWO-4428 Don't count R marked svn diffs --- lib/ohloh_scm/adapters/svn_chain/chain.rb | 2 +- lib/ohloh_scm/adapters/svn_chain/commits.rb | 2 +- test/repositories/svn_with_branching.tgz | Bin 7704 -> 8297 bytes test/unit/svn_chain_commits_test.rb | 72 +++++++++++--------- test/unit/svn_chain_test.rb | 20 ++++-- 5 files changed, 57 insertions(+), 39 deletions(-) diff --git a/lib/ohloh_scm/adapters/svn_chain/chain.rb b/lib/ohloh_scm/adapters/svn_chain/chain.rb index 8b4c7b2f..611a3c92 100644 --- a/lib/ohloh_scm/adapters/svn_chain/chain.rb +++ b/lib/ohloh_scm/adapters/svn_chain/chain.rb @@ -86,7 +86,7 @@ def next_revision_xml(after=0) # code tree from one directory to another, this method returns the name # of the previous directory. def parent_branch_name(d) - if d.action == 'A' && branch_name[0, d.path.size] == d.path && d.from_path && d.from_revision + if %w(A R).include?(d.action) && branch_name[0, d.path.size] == d.path && d.from_path && d.from_revision d.from_path + branch_name[d.path.size..-1] end end diff --git a/lib/ohloh_scm/adapters/svn_chain/commits.rb b/lib/ohloh_scm/adapters/svn_chain/commits.rb index 32f21c52..1e174488 100644 --- a/lib/ohloh_scm/adapters/svn_chain/commits.rb +++ b/lib/ohloh_scm/adapters/svn_chain/commits.rb @@ -23,7 +23,7 @@ def verbose_commit(rev=0) # If the diff points to a file, simply returns the diff. # If the diff points to a directory, returns an array of diffs for every file in the directory. def deepen_diff(diff, rev) - if diff.action == 'A' && diff.path == '' && parent_svn && rev == first_token + if %w(A R).include?(diff.action) && diff.path == '' && parent_svn && rev == first_token # A very special case that is important for chaining. # This is the first commit, and the entire tree is being created by copying from parent_svn. # In this case, there isn't actually any change, just diff --git a/test/repositories/svn_with_branching.tgz b/test/repositories/svn_with_branching.tgz index 29e46f103891d7a3da6106d223f626629106acaa..5e3ee62551fdbf1393df8cde4e333353f3fe565a 100644 GIT binary patch literal 8297 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 c1|sn2z050gHng9R* literal 7704 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 1) - assert_equal [4,5,8,9], svn.commit_tokens(:after => 2) - assert_equal [4,5,8,9], svn.commit_tokens(:after => 3) - assert_equal [5,8,9], svn.commit_tokens(:after => 4) - assert_equal [8,9], svn.commit_tokens(:after => 5) - assert_equal [8,9], svn.commit_tokens(:after => 6) - assert_equal [8,9], svn.commit_tokens(:after => 7) - assert_equal [9], svn.commit_tokens(:after => 8) - assert_equal [], svn.commit_tokens(:after => 9) - assert_equal [], svn.commit_tokens(:after => 10) + assert_equal [1,2,4,5,8,9,11], svn.commit_tokens + assert_equal [2,4,5,8,9,11], svn.commit_tokens(:after => 1) + assert_equal [4,5,8,9,11], svn.commit_tokens(:after => 2) + assert_equal [4,5,8,9,11], svn.commit_tokens(:after => 3) + assert_equal [5,8,9,11], svn.commit_tokens(:after => 4) + assert_equal [8,9,11], svn.commit_tokens(:after => 5) + assert_equal [8,9,11], svn.commit_tokens(:after => 6) + assert_equal [8,9,11], svn.commit_tokens(:after => 7) + assert_equal [9,11], svn.commit_tokens(:after => 8) + assert_equal [11], svn.commit_tokens(:after => 9) + assert_equal [], svn.commit_tokens(:after => 11) end end def test_chained_commit_count with_svn_chain_repository('svn_with_branching', '/trunk') do |svn| - assert_equal 6, svn.commit_count - assert_equal 5, svn.commit_count(:after => 1) - assert_equal 4, svn.commit_count(:after => 2) - assert_equal 4, svn.commit_count(:after => 3) - assert_equal 3, svn.commit_count(:after => 4) - assert_equal 2, svn.commit_count(:after => 5) - assert_equal 2, svn.commit_count(:after => 6) - assert_equal 2, svn.commit_count(:after => 7) - assert_equal 1, svn.commit_count(:after => 8) - assert_equal 0, svn.commit_count(:after => 9) + assert_equal 7, svn.commit_count + assert_equal 6, svn.commit_count(:after => 1) + assert_equal 5, svn.commit_count(:after => 2) + assert_equal 5, svn.commit_count(:after => 3) + assert_equal 4, svn.commit_count(:after => 4) + assert_equal 3, svn.commit_count(:after => 5) + assert_equal 3, svn.commit_count(:after => 6) + assert_equal 3, svn.commit_count(:after => 7) + assert_equal 2, svn.commit_count(:after => 8) + assert_equal 1, svn.commit_count(:after => 9) + assert_equal 0, svn.commit_count(:after => 11) end end def test_chained_commits with_svn_chain_repository('svn_with_branching', '/trunk') do |svn| - assert_equal [1,2,4,5,8,9], svn.commits.collect { |c| c.token } - assert_equal [2,4,5,8,9], svn.commits(:after => 1).collect { |c| c.token } - assert_equal [4,5,8,9], svn.commits(:after => 2).collect { |c| c.token } - assert_equal [4,5,8,9], svn.commits(:after => 3).collect { |c| c.token } - assert_equal [5,8,9], svn.commits(:after => 4).collect { |c| c.token } - assert_equal [8,9], svn.commits(:after => 5).collect { |c| c.token } - assert_equal [8,9], svn.commits(:after => 6).collect { |c| c.token } - assert_equal [8,9], svn.commits(:after => 7).collect { |c| c.token } - assert_equal [9], svn.commits(:after => 8).collect { |c| c.token } - assert_equal [], svn.commits(:after => 9).collect { |c| c.token } + assert_equal [1,2,4,5,8,9,11], svn.commits.collect { |c| c.token } + assert_equal [2,4,5,8,9,11], svn.commits(:after => 1).collect { |c| c.token } + assert_equal [4,5,8,9,11], svn.commits(:after => 2).collect { |c| c.token } + assert_equal [4,5,8,9,11], svn.commits(:after => 3).collect { |c| c.token } + assert_equal [5,8,9,11], svn.commits(:after => 4).collect { |c| c.token } + assert_equal [8,9,11], svn.commits(:after => 5).collect { |c| c.token } + assert_equal [8,9,11], svn.commits(:after => 6).collect { |c| c.token } + assert_equal [8,9,11], svn.commits(:after => 7).collect { |c| c.token } + assert_equal [9,11], svn.commits(:after => 8).collect { |c| c.token } + assert_equal [11], svn.commits(:after => 9).collect { |c| c.token } + assert_equal [], svn.commits(:after => 11).collect { |c| c.token } end end @@ -64,7 +66,7 @@ def test_chained_each_commit end end - assert_equal [1,2,4,5,8,9], commits.collect { |c| c.token } + assert_equal [1,2,4,5,8,9,11], commits.collect { |c| c.token } # This repository spends a lot of energy moving directories around. # File edits actually occur in just 3 commits. @@ -105,6 +107,12 @@ def test_chained_each_commit assert_equal 1, commits[5].diffs.size assert_equal 'M', commits[5].diffs.first.action assert_equal '/helloworld.c', commits[5].diffs.first.path + + # Revision 10: /trunk/goodbyeworld.c & /trunk/helloworld.c are modified + # on branches/development, hence no commit reported. + + # Revision 11: The trunk is reverted back to revision 9. + assert_equal 0, commits[6].diffs.size end # Specifically tests this case: diff --git a/test/unit/svn_chain_test.rb b/test/unit/svn_chain_test.rb index bf15b627..6a3ec508 100644 --- a/test/unit/svn_chain_test.rb +++ b/test/unit/svn_chain_test.rb @@ -6,7 +6,7 @@ class SvnChainTest < OhlohScm::Test def test_chain with_svn_chain_repository('svn_with_branching', '/trunk') do |svn| chain = svn.chain - assert_equal 4, chain.size + assert_equal 5, chain.size # In revision 1, the trunk is created. assert_equal '/trunk', chain[0].branch_name @@ -25,19 +25,29 @@ def test_chain assert_equal 7, chain[2].final_token # In revision 8, a new trunk is created by copying the branch. - # This trunk still lives on, so its final_token is nil. + # The next final_token will be 9. assert_equal '/trunk', chain[3].branch_name assert_equal 8, chain[3].first_token - assert_equal nil, chain[3].final_token + assert_equal 9, chain[3].final_token + + # In revision 11, trunk is reverted back to rev 9 + # This trunk still lives on, so its final_token is nil. + assert_equal '/trunk', chain[4].branch_name + assert_equal 11, chain[4].first_token + assert_nil chain[4].final_token end end def test_parent_svn with_svn_chain_repository('svn_with_branching', '/trunk') do |svn| - # In this repository, /branches/development becomes + # The first chain is the copy commit from trunk:9 into rev 11. + p0 = svn.parent_svn + assert_equal 9, p0.final_token + + # In this repository, /branches/development becomes # the /trunk in revision 8. So there should be a parent # will final_token 7. - p1 = svn.parent_svn + p1 = p0.parent_svn assert_equal p1.url, svn.root + '/branches/development' assert_equal p1.branch_name, '/branches/development' assert_equal p1.final_token, 7 From de39289ae4995c5983c5c1a32ccb8a2e6810ac9a Mon Sep 17 00:00:00 2001 From: Alex Johnson Date: Wed, 19 Apr 2017 13:50:04 +0530 Subject: [PATCH 212/219] OTWO-4428 Version Bump --- lib/ohloh_scm/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ohloh_scm/version.rb b/lib/ohloh_scm/version.rb index e847bd35..60715c49 100644 --- a/lib/ohloh_scm/version.rb +++ b/lib/ohloh_scm/version.rb @@ -1,5 +1,5 @@ module OhlohScm module Version - STRING = '2.2.11' + STRING = '2.2.12' end end From 63916585659b5af32dada8be4439a08369340cfe Mon Sep 17 00:00:00 2001 From: Jebin Date: Fri, 19 May 2017 15:36:13 +0530 Subject: [PATCH 213/219] OTWO-4721 Raise an exception if repository is empty --- lib/ohloh_scm/adapters/git/pull.rb | 3 + lib/ohloh_scm/version.rb | 2 +- test/repositories/svn_empty/README.txt | 5 + test/repositories/svn_empty/conf/authz | 32 +++++ .../svn_empty/conf/hooks-env.tmpl | 19 +++ test/repositories/svn_empty/conf/passwd | 8 ++ .../repositories/svn_empty/conf/svnserve.conf | 76 +++++++++++ test/repositories/svn_empty/db/current | 1 + test/repositories/svn_empty/db/format | 2 + test/repositories/svn_empty/db/fs-type | 1 + test/repositories/svn_empty/db/fsfs.conf | 125 ++++++++++++++++++ .../svn_empty/db/min-unpacked-rev | 1 + test/repositories/svn_empty/db/revprops/0/0 | 5 + test/repositories/svn_empty/db/revs/0/0 | 11 ++ test/repositories/svn_empty/db/txn-current | 1 + .../svn_empty/db/txn-current-lock | 0 test/repositories/svn_empty/db/uuid | 1 + test/repositories/svn_empty/db/write-lock | 0 test/repositories/svn_empty/format | 1 + .../svn_empty/hooks/post-commit.tmpl | 52 ++++++++ .../svn_empty/hooks/post-lock.tmpl | 45 +++++++ .../svn_empty/hooks/post-revprop-change.tmpl | 57 ++++++++ .../svn_empty/hooks/post-unlock.tmpl | 43 ++++++ .../svn_empty/hooks/pre-commit.tmpl | 85 ++++++++++++ .../svn_empty/hooks/pre-lock.tmpl | 73 ++++++++++ .../svn_empty/hooks/pre-revprop-change.tmpl | 66 +++++++++ .../svn_empty/hooks/pre-unlock.tmpl | 65 +++++++++ .../svn_empty/hooks/start-commit.tmpl | 74 +++++++++++ .../repositories/svn_empty/locks/db-logs.lock | 3 + test/repositories/svn_empty/locks/db.lock | 3 + test/unit/git_pull_test.rb | 10 ++ 31 files changed, 869 insertions(+), 1 deletion(-) create mode 100644 test/repositories/svn_empty/README.txt create mode 100644 test/repositories/svn_empty/conf/authz create mode 100644 test/repositories/svn_empty/conf/hooks-env.tmpl create mode 100644 test/repositories/svn_empty/conf/passwd create mode 100644 test/repositories/svn_empty/conf/svnserve.conf create mode 100644 test/repositories/svn_empty/db/current create mode 100644 test/repositories/svn_empty/db/format create mode 100644 test/repositories/svn_empty/db/fs-type create mode 100644 test/repositories/svn_empty/db/fsfs.conf create mode 100644 test/repositories/svn_empty/db/min-unpacked-rev create mode 100644 test/repositories/svn_empty/db/revprops/0/0 create mode 100644 test/repositories/svn_empty/db/revs/0/0 create mode 100644 test/repositories/svn_empty/db/txn-current create mode 100644 test/repositories/svn_empty/db/txn-current-lock create mode 100644 test/repositories/svn_empty/db/uuid create mode 100644 test/repositories/svn_empty/db/write-lock create mode 100644 test/repositories/svn_empty/format create mode 100755 test/repositories/svn_empty/hooks/post-commit.tmpl create mode 100755 test/repositories/svn_empty/hooks/post-lock.tmpl create mode 100755 test/repositories/svn_empty/hooks/post-revprop-change.tmpl create mode 100755 test/repositories/svn_empty/hooks/post-unlock.tmpl create mode 100755 test/repositories/svn_empty/hooks/pre-commit.tmpl create mode 100755 test/repositories/svn_empty/hooks/pre-lock.tmpl create mode 100755 test/repositories/svn_empty/hooks/pre-revprop-change.tmpl create mode 100755 test/repositories/svn_empty/hooks/pre-unlock.tmpl create mode 100755 test/repositories/svn_empty/hooks/start-commit.tmpl create mode 100644 test/repositories/svn_empty/locks/db-logs.lock create mode 100644 test/repositories/svn_empty/locks/db.lock diff --git a/lib/ohloh_scm/adapters/git/pull.rb b/lib/ohloh_scm/adapters/git/pull.rb index c3bbd3be..e259b640 100644 --- a/lib/ohloh_scm/adapters/git/pull.rb +++ b/lib/ohloh_scm/adapters/git/pull.rb @@ -3,6 +3,7 @@ class GitAdapter < AbstractAdapter def pull(from, &block) logger.info { "Pulling #{from.url}" } + case from when GitAdapter clone_or_fetch(from, &block) @@ -104,6 +105,8 @@ def convert(source_scm) commit_all(r) end yield(commits.size, commits.size) if block_given? + elsif !read_token && commits.empty? + raise RuntimeError, "Empty repository" else logger.info { "Already up-to-date." } end diff --git a/lib/ohloh_scm/version.rb b/lib/ohloh_scm/version.rb index 60715c49..b1703178 100644 --- a/lib/ohloh_scm/version.rb +++ b/lib/ohloh_scm/version.rb @@ -1,5 +1,5 @@ module OhlohScm module Version - STRING = '2.2.12' + STRING = '2.2.13' end end diff --git a/test/repositories/svn_empty/README.txt b/test/repositories/svn_empty/README.txt new file mode 100644 index 00000000..9935818a --- /dev/null +++ b/test/repositories/svn_empty/README.txt @@ -0,0 +1,5 @@ +This is a Subversion repository; use the 'svnadmin' and 'svnlook' +tools to examine it. Do not add, delete, or modify files here +unless you know how to avoid corrupting the repository. + +Visit http://subversion.apache.org/ for more information. diff --git a/test/repositories/svn_empty/conf/authz b/test/repositories/svn_empty/conf/authz new file mode 100644 index 00000000..0b9a4107 --- /dev/null +++ b/test/repositories/svn_empty/conf/authz @@ -0,0 +1,32 @@ +### This file is an example authorization file for svnserve. +### Its format is identical to that of mod_authz_svn authorization +### files. +### As shown below each section defines authorizations for the path and +### (optional) repository specified by the section name. +### The authorizations follow. An authorization line can refer to: +### - a single user, +### - a group of users defined in a special [groups] section, +### - an alias defined in a special [aliases] section, +### - all authenticated users, using the '$authenticated' token, +### - only anonymous users, using the '$anonymous' token, +### - anyone, using the '*' wildcard. +### +### A match can be inverted by prefixing the rule with '~'. Rules can +### grant read ('r') access, read-write ('rw') access, or no access +### (''). + +[aliases] +# joe = /C=XZ/ST=Dessert/L=Snake City/O=Snake Oil, Ltd./OU=Research Institute/CN=Joe Average + +[groups] +# harry_and_sally = harry,sally +# harry_sally_and_joe = harry,sally,&joe + +# [/foo/bar] +# harry = rw +# &joe = r +# * = + +# [repository:/baz/fuz] +# @harry_and_sally = rw +# * = r diff --git a/test/repositories/svn_empty/conf/hooks-env.tmpl b/test/repositories/svn_empty/conf/hooks-env.tmpl new file mode 100644 index 00000000..ee965c31 --- /dev/null +++ b/test/repositories/svn_empty/conf/hooks-env.tmpl @@ -0,0 +1,19 @@ +### This file is an example hook script environment configuration file. +### Hook scripts run in an empty environment by default. +### As shown below each section defines environment variables for a +### particular hook script. The [default] section defines environment +### variables for all hook scripts, unless overridden by a hook-specific +### section. + +### This example configures a UTF-8 locale for all hook scripts, so that +### special characters, such as umlauts, may be printed to stderr. +### If UTF-8 is used with a mod_dav_svn server, the SVNUseUTF8 option must +### also be set to 'yes' in httpd.conf. +### With svnserve, the LANG environment variable of the svnserve process +### must be set to the same value as given here. +[default] +LANG = en_US.UTF-8 + +### This sets the PATH environment variable for the pre-commit hook. +[pre-commit] +PATH = /usr/local/bin:/usr/bin:/usr/sbin diff --git a/test/repositories/svn_empty/conf/passwd b/test/repositories/svn_empty/conf/passwd new file mode 100644 index 00000000..ecaa08dc --- /dev/null +++ b/test/repositories/svn_empty/conf/passwd @@ -0,0 +1,8 @@ +### This file is an example password file for svnserve. +### Its format is similar to that of svnserve.conf. As shown in the +### example below it contains one section labelled [users]. +### The name and password for each user follow, one account per line. + +[users] +# harry = harryssecret +# sally = sallyssecret diff --git a/test/repositories/svn_empty/conf/svnserve.conf b/test/repositories/svn_empty/conf/svnserve.conf new file mode 100644 index 00000000..a1eb6c8f --- /dev/null +++ b/test/repositories/svn_empty/conf/svnserve.conf @@ -0,0 +1,76 @@ +### This file controls the configuration of the svnserve daemon, if you +### use it to allow access to this repository. (If you only allow +### access through http: and/or file: URLs, then this file is +### irrelevant.) + +### Visit http://subversion.apache.org/ for more information. + +[general] +### The anon-access and auth-access options control access to the +### repository for unauthenticated (a.k.a. anonymous) users and +### authenticated users, respectively. +### Valid values are "write", "read", and "none". +### Setting the value to "none" prohibits both reading and writing; +### "read" allows read-only access, and "write" allows complete +### read/write access to the repository. +### The sample settings below are the defaults and specify that anonymous +### users have read-only access to the repository, while authenticated +### users have read and write access to the repository. +# anon-access = read +# auth-access = write +### The password-db option controls the location of the password +### database file. Unless you specify a path starting with a /, +### the file's location is relative to the directory containing +### this configuration file. +### If SASL is enabled (see below), this file will NOT be used. +### Uncomment the line below to use the default password file. +# password-db = passwd +### The authz-db option controls the location of the authorization +### rules for path-based access control. Unless you specify a path +### starting with a /, the file's location is relative to the +### directory containing this file. The specified path may be a +### repository relative URL (^/) or an absolute file:// URL to a text +### file in a Subversion repository. If you don't specify an authz-db, +### no path-based access control is done. +### Uncomment the line below to use the default authorization file. +# authz-db = authz +### The groups-db option controls the location of the groups file. +### Unless you specify a path starting with a /, the file's location is +### relative to the directory containing this file. The specified path +### may be a repository relative URL (^/) or an absolute file:// URL to a +### text file in a Subversion repository. +# groups-db = groups +### This option specifies the authentication realm of the repository. +### If two repositories have the same authentication realm, they should +### have the same password database, and vice versa. The default realm +### is repository's uuid. +# realm = My First Repository +### The force-username-case option causes svnserve to case-normalize +### usernames before comparing them against the authorization rules in the +### authz-db file configured above. Valid values are "upper" (to upper- +### case the usernames), "lower" (to lowercase the usernames), and +### "none" (to compare usernames as-is without case conversion, which +### is the default behavior). +# force-username-case = none +### The hooks-env options specifies a path to the hook script environment +### configuration file. This option overrides the per-repository default +### and can be used to configure the hook script environment for multiple +### repositories in a single file, if an absolute path is specified. +### Unless you specify an absolute path, the file's location is relative +### to the directory containing this file. +# hooks-env = hooks-env + +[sasl] +### This option specifies whether you want to use the Cyrus SASL +### library for authentication. Default is false. +### This section will be ignored if svnserve is not built with Cyrus +### SASL support; to check, run 'svnserve --version' and look for a line +### reading 'Cyrus SASL authentication is available.' +# use-sasl = true +### These options specify the desired strength of the security layer +### that you want SASL to provide. 0 means no encryption, 1 means +### integrity-checking only, values larger than 1 are correlated +### to the effective key length for encryption (e.g. 128 means 128-bit +### encryption). The values below are the defaults. +# min-encryption = 0 +# max-encryption = 256 diff --git a/test/repositories/svn_empty/db/current b/test/repositories/svn_empty/db/current new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/repositories/svn_empty/db/current @@ -0,0 +1 @@ +0 diff --git a/test/repositories/svn_empty/db/format b/test/repositories/svn_empty/db/format new file mode 100644 index 00000000..3fc1fa47 --- /dev/null +++ b/test/repositories/svn_empty/db/format @@ -0,0 +1,2 @@ +6 +layout sharded 1000 diff --git a/test/repositories/svn_empty/db/fs-type b/test/repositories/svn_empty/db/fs-type new file mode 100644 index 00000000..4fdd9531 --- /dev/null +++ b/test/repositories/svn_empty/db/fs-type @@ -0,0 +1 @@ +fsfs diff --git a/test/repositories/svn_empty/db/fsfs.conf b/test/repositories/svn_empty/db/fsfs.conf new file mode 100644 index 00000000..7c0bf9f7 --- /dev/null +++ b/test/repositories/svn_empty/db/fsfs.conf @@ -0,0 +1,125 @@ +### This file controls the configuration of the FSFS filesystem. + +[memcached-servers] +### These options name memcached servers used to cache internal FSFS +### data. See http://www.danga.com/memcached/ for more information on +### memcached. To use memcached with FSFS, run one or more memcached +### servers, and specify each of them as an option like so: +# first-server = 127.0.0.1:11211 +# remote-memcached = mymemcached.corp.example.com:11212 +### The option name is ignored; the value is of the form HOST:PORT. +### memcached servers can be shared between multiple repositories; +### however, if you do this, you *must* ensure that repositories have +### distinct UUIDs and paths, or else cached data from one repository +### might be used by another accidentally. Note also that memcached has +### no authentication for reads or writes, so you must ensure that your +### memcached servers are only accessible by trusted users. + +[caches] +### When a cache-related error occurs, normally Subversion ignores it +### and continues, logging an error if the server is appropriately +### configured (and ignoring it with file:// access). To make +### Subversion never ignore cache errors, uncomment this line. +# fail-stop = true + +[rep-sharing] +### To conserve space, the filesystem can optionally avoid storing +### duplicate representations. This comes at a slight cost in +### performance, as maintaining a database of shared representations can +### increase commit times. The space savings are dependent upon the size +### of the repository, the number of objects it contains and the amount of +### duplication between them, usually a function of the branching and +### merging process. +### +### The following parameter enables rep-sharing in the repository. It can +### be switched on and off at will, but for best space-saving results +### should be enabled consistently over the life of the repository. +### 'svnadmin verify' will check the rep-cache regardless of this setting. +### rep-sharing is enabled by default. +# enable-rep-sharing = true + +[deltification] +### To conserve space, the filesystem stores data as differences against +### existing representations. This comes at a slight cost in performance, +### as calculating differences can increase commit times. Reading data +### will also create higher CPU load and the data will be fragmented. +### Since deltification tends to save significant amounts of disk space, +### the overall I/O load can actually be lower. +### +### The options in this section allow for tuning the deltification +### strategy. Their effects on data size and server performance may vary +### from one repository to another. Versions prior to 1.8 will ignore +### this section. +### +### The following parameter enables deltification for directories. It can +### be switched on and off at will, but for best space-saving results +### should be enabled consistently over the life of the repository. +### Repositories containing large directories will benefit greatly. +### In rarely read repositories, the I/O overhead may be significant as +### cache hit rates will most likely be low +### directory deltification is disabled by default. +# enable-dir-deltification = false +### +### The following parameter enables deltification for properties on files +### and directories. Overall, this is a minor tuning option but can save +### some disk space if you merge frequently or frequently change node +### properties. You should not activate this if rep-sharing has been +### disabled because this may result in a net increase in repository size. +### property deltification is disabled by default. +# enable-props-deltification = false +### +### During commit, the server may need to walk the whole change history of +### of a given node to find a suitable deltification base. This linear +### process can impact commit times, svnadmin load and similar operations. +### This setting limits the depth of the deltification history. If the +### threshold has been reached, the node will be stored as fulltext and a +### new deltification history begins. +### Note, this is unrelated to svn log. +### Very large values rarely provide significant additional savings but +### can impact performance greatly - in particular if directory +### deltification has been activated. Very small values may be useful in +### repositories that are dominated by large, changing binaries. +### Should be a power of two minus 1. A value of 0 will effectively +### disable deltification. +### For 1.8, the default value is 1023; earlier versions have no limit. +# max-deltification-walk = 1023 +### +### The skip-delta scheme used by FSFS tends to repeatably store redundant +### delta information where a simple delta against the latest version is +### often smaller. By default, 1.8+ will therefore use skip deltas only +### after the linear chain of deltas has grown beyond the threshold +### specified by this setting. +### Values up to 64 can result in some reduction in repository size for +### the cost of quickly increasing I/O and CPU costs. Similarly, smaller +### numbers can reduce those costs at the cost of more disk space. For +### rarely read repositories or those containing larger binaries, this may +### present a better trade-off. +### Should be a power of two. A value of 1 or smaller will cause the +### exclusive use of skip-deltas (as in pre-1.8). +### For 1.8, the default value is 16; earlier versions use 1. +# max-linear-deltification = 16 + +[packed-revprops] +### This parameter controls the size (in kBytes) of packed revprop files. +### Revprops of consecutive revisions will be concatenated into a single +### file up to but not exceeding the threshold given here. However, each +### pack file may be much smaller and revprops of a single revision may be +### much larger than the limit set here. The threshold will be applied +### before optional compression takes place. +### Large values will reduce disk space usage at the expense of increased +### latency and CPU usage reading and changing individual revprops. They +### become an advantage when revprop caching has been enabled because a +### lot of data can be read in one go. Values smaller than 4 kByte will +### not improve latency any further and quickly render revprop packing +### ineffective. +### revprop-pack-size is 64 kBytes by default for non-compressed revprop +### pack files and 256 kBytes when compression has been enabled. +# revprop-pack-size = 64 +### +### To save disk space, packed revprop files may be compressed. Standard +### revprops tend to allow for very effective compression. Reading and +### even more so writing, become significantly more CPU intensive. With +### revprop caching enabled, the overhead can be offset by reduced I/O +### unless you often modify revprops after packing. +### Compressing packed revprops is disabled by default. +# compress-packed-revprops = false diff --git a/test/repositories/svn_empty/db/min-unpacked-rev b/test/repositories/svn_empty/db/min-unpacked-rev new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/repositories/svn_empty/db/min-unpacked-rev @@ -0,0 +1 @@ +0 diff --git a/test/repositories/svn_empty/db/revprops/0/0 b/test/repositories/svn_empty/db/revprops/0/0 new file mode 100644 index 00000000..eca610de --- /dev/null +++ b/test/repositories/svn_empty/db/revprops/0/0 @@ -0,0 +1,5 @@ +K 8 +svn:date +V 27 +2017-05-22T10:06:32.301179Z +END diff --git a/test/repositories/svn_empty/db/revs/0/0 b/test/repositories/svn_empty/db/revs/0/0 new file mode 100644 index 00000000..10f5c45f --- /dev/null +++ b/test/repositories/svn_empty/db/revs/0/0 @@ -0,0 +1,11 @@ +PLAIN +END +ENDREP +id: 0.0.r0/17 +type: dir +count: 0 +text: 0 0 4 4 2d2977d1c96f487abe4a1e202dd03b4e +cpath: / + + +17 107 diff --git a/test/repositories/svn_empty/db/txn-current b/test/repositories/svn_empty/db/txn-current new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/test/repositories/svn_empty/db/txn-current @@ -0,0 +1 @@ +0 diff --git a/test/repositories/svn_empty/db/txn-current-lock b/test/repositories/svn_empty/db/txn-current-lock new file mode 100644 index 00000000..e69de29b diff --git a/test/repositories/svn_empty/db/uuid b/test/repositories/svn_empty/db/uuid new file mode 100644 index 00000000..49845685 --- /dev/null +++ b/test/repositories/svn_empty/db/uuid @@ -0,0 +1 @@ +9776d4a3-6c79-43be-aaa4-b7d710814ae4 diff --git a/test/repositories/svn_empty/db/write-lock b/test/repositories/svn_empty/db/write-lock new file mode 100644 index 00000000..e69de29b diff --git a/test/repositories/svn_empty/format b/test/repositories/svn_empty/format new file mode 100644 index 00000000..7ed6ff82 --- /dev/null +++ b/test/repositories/svn_empty/format @@ -0,0 +1 @@ +5 diff --git a/test/repositories/svn_empty/hooks/post-commit.tmpl b/test/repositories/svn_empty/hooks/post-commit.tmpl new file mode 100755 index 00000000..16b7b545 --- /dev/null +++ b/test/repositories/svn_empty/hooks/post-commit.tmpl @@ -0,0 +1,52 @@ +#!/bin/sh + +# POST-COMMIT HOOK +# +# The post-commit hook is invoked after a commit. Subversion runs +# this hook by invoking a program (script, executable, binary, etc.) +# named 'post-commit' (for which this file is a template) with the +# following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] REV (the number of the revision just committed) +# [3] TXN-NAME (the name of the transaction that has become REV) +# +# The default working directory for the invocation is undefined, so +# the program should set one explicitly if it cares. +# +# Because the commit has already completed and cannot be undone, +# the exit code of the hook program is ignored. The hook program +# can use the 'svnlook' utility to help it examine the +# newly-committed tree. +# +# On a Unix system, the normal procedure is to have 'post-commit' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'post-commit' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'post-commit.bat' or 'post-commit.exe', +# but the basic idea is the same. +# +# The hook program typically does not inherit the environment of +# its parent process. For example, a common problem is for the +# PATH environment variable to not be set to its usual value, so +# that subprograms fail to launch unless invoked via absolute path. +# If you're having unexpected problems with a hook program, the +# culprit may be unusual (or missing) environment variables. +# +# Here is an example hook script, for a Unix /bin/sh interpreter. +# For more examples and pre-written hooks, see those in +# /usr/share/subversion/hook-scripts, and in the repository at +# http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/ and +# http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/ + + +REPOS="$1" +REV="$2" +TXN_NAME="$3" + +"$REPOS"/hooks/mailer.py commit "$REPOS" $REV "$REPOS"/mailer.conf diff --git a/test/repositories/svn_empty/hooks/post-lock.tmpl b/test/repositories/svn_empty/hooks/post-lock.tmpl new file mode 100755 index 00000000..beae9d70 --- /dev/null +++ b/test/repositories/svn_empty/hooks/post-lock.tmpl @@ -0,0 +1,45 @@ +#!/bin/sh + +# POST-LOCK HOOK +# +# The post-lock hook is run after a path is locked. Subversion runs +# this hook by invoking a program (script, executable, binary, etc.) +# named 'post-lock' (for which this file is a template) with the +# following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] USER (the user who created the lock) +# +# The paths that were just locked are passed to the hook via STDIN (as +# of Subversion 1.2, only one path is passed per invocation, but the +# plan is to pass all locked paths at once, so the hook program +# should be written accordingly). +# +# The default working directory for the invocation is undefined, so +# the program should set one explicitly if it cares. +# +# Because the lock has already been created and cannot be undone, +# the exit code of the hook program is ignored. The hook program +# can use the 'svnlook' utility to help it examine the +# newly-created lock. +# +# On a Unix system, the normal procedure is to have 'post-lock' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'post-lock' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'post-lock.bat' or 'post-lock.exe', +# but the basic idea is the same. +# +# Here is an example hook script, for a Unix /bin/sh interpreter: + +REPOS="$1" +USER="$2" + +# Send email to interested parties, let them know a lock was created: +"$REPOS"/hooks/mailer.py lock \ + "$REPOS" "$USER" "$REPOS"/hooks/mailer.conf diff --git a/test/repositories/svn_empty/hooks/post-revprop-change.tmpl b/test/repositories/svn_empty/hooks/post-revprop-change.tmpl new file mode 100755 index 00000000..cf7aedda --- /dev/null +++ b/test/repositories/svn_empty/hooks/post-revprop-change.tmpl @@ -0,0 +1,57 @@ +#!/bin/sh + +# POST-REVPROP-CHANGE HOOK +# +# The post-revprop-change hook is invoked after a revision property +# has been added, modified or deleted. Subversion runs this hook by +# invoking a program (script, executable, binary, etc.) named +# 'post-revprop-change' (for which this file is a template), with the +# following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] REV (the revision that was tweaked) +# [3] USER (the username of the person tweaking the property) +# [4] PROPNAME (the property that was changed) +# [5] ACTION (the property was 'A'dded, 'M'odified, or 'D'eleted) +# +# [STDIN] PROPVAL ** the old property value is passed via STDIN. +# +# Because the propchange has already completed and cannot be undone, +# the exit code of the hook program is ignored. The hook program +# can use the 'svnlook' utility to help it examine the +# new property value. +# +# On a Unix system, the normal procedure is to have 'post-revprop-change' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'post-revprop-change' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'post-revprop-change.bat' or 'post-revprop-change.exe', +# but the basic idea is the same. +# +# The hook program typically does not inherit the environment of +# its parent process. For example, a common problem is for the +# PATH environment variable to not be set to its usual value, so +# that subprograms fail to launch unless invoked via absolute path. +# If you're having unexpected problems with a hook program, the +# culprit may be unusual (or missing) environment variables. +# +# Here is an example hook script, for a Unix /bin/sh interpreter. +# For more examples and pre-written hooks, see those in +# /usr/share/subversion/hook-scripts, and in the repository at +# http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/ and +# http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/ + + +REPOS="$1" +REV="$2" +USER="$3" +PROPNAME="$4" +ACTION="$5" + +"$REPOS"/hooks/mailer.py propchange2 "$REPOS" $REV \ + "$USER" "$PROPNAME" "$ACTION" "$REPOS"/hooks/mailer.conf diff --git a/test/repositories/svn_empty/hooks/post-unlock.tmpl b/test/repositories/svn_empty/hooks/post-unlock.tmpl new file mode 100755 index 00000000..277569f9 --- /dev/null +++ b/test/repositories/svn_empty/hooks/post-unlock.tmpl @@ -0,0 +1,43 @@ +#!/bin/sh + +# POST-UNLOCK HOOK +# +# The post-unlock hook runs after a path is unlocked. Subversion runs +# this hook by invoking a program (script, executable, binary, etc.) +# named 'post-unlock' (for which this file is a template) with the +# following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] USER (the user who destroyed the lock) +# +# The paths that were just unlocked are passed to the hook via STDIN +# (as of Subversion 1.2, only one path is passed per invocation, but +# the plan is to pass all unlocked paths at once, so the hook program +# should be written accordingly). +# +# The default working directory for the invocation is undefined, so +# the program should set one explicitly if it cares. +# +# Because the lock has already been destroyed and cannot be undone, +# the exit code of the hook program is ignored. +# +# On a Unix system, the normal procedure is to have 'post-unlock' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'post-unlock' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'post-unlock.bat' or 'post-unlock.exe', +# but the basic idea is the same. +# +# Here is an example hook script, for a Unix /bin/sh interpreter: + +REPOS="$1" +USER="$2" + +# Send email to interested parties, let them know a lock was removed: +"$REPOS"/hooks/mailer.py unlock \ + "$REPOS" "$USER" "$REPOS"/hooks/mailer.conf diff --git a/test/repositories/svn_empty/hooks/pre-commit.tmpl b/test/repositories/svn_empty/hooks/pre-commit.tmpl new file mode 100755 index 00000000..44c24b93 --- /dev/null +++ b/test/repositories/svn_empty/hooks/pre-commit.tmpl @@ -0,0 +1,85 @@ +#!/bin/sh + +# PRE-COMMIT HOOK +# +# The pre-commit hook is invoked before a Subversion txn is +# committed. Subversion runs this hook by invoking a program +# (script, executable, binary, etc.) named 'pre-commit' (for which +# this file is a template), with the following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] TXN-NAME (the name of the txn about to be committed) +# +# [STDIN] LOCK-TOKENS ** the lock tokens are passed via STDIN. +# +# If STDIN contains the line "LOCK-TOKENS:\n" (the "\n" denotes a +# single newline), the lines following it are the lock tokens for +# this commit. The end of the list is marked by a line containing +# only a newline character. +# +# Each lock token line consists of a URI-escaped path, followed +# by the separator character '|', followed by the lock token string, +# followed by a newline. +# +# The default working directory for the invocation is undefined, so +# the program should set one explicitly if it cares. +# +# If the hook program exits with success, the txn is committed; but +# if it exits with failure (non-zero), the txn is aborted, no commit +# takes place, and STDERR is returned to the client. The hook +# program can use the 'svnlook' utility to help it examine the txn. +# +# On a Unix system, the normal procedure is to have 'pre-commit' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# *** NOTE: THE HOOK PROGRAM MUST NOT MODIFY THE TXN, EXCEPT *** +# *** FOR REVISION PROPERTIES (like svn:log or svn:author). *** +# +# This is why we recommend using the read-only 'svnlook' utility. +# In the future, Subversion may enforce the rule that pre-commit +# hooks should not modify the versioned data in txns, or else come +# up with a mechanism to make it safe to do so (by informing the +# committing client of the changes). However, right now neither +# mechanism is implemented, so hook writers just have to be careful. +# +# Note that 'pre-commit' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'pre-commit.bat' or 'pre-commit.exe', +# but the basic idea is the same. +# +# The hook program typically does not inherit the environment of +# its parent process. For example, a common problem is for the +# PATH environment variable to not be set to its usual value, so +# that subprograms fail to launch unless invoked via absolute path. +# If you're having unexpected problems with a hook program, the +# culprit may be unusual (or missing) environment variables. +# +# Here is an example hook script, for a Unix /bin/sh interpreter. +# For more examples and pre-written hooks, see those in +# /usr/share/subversion/hook-scripts, and in the repository at +# http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/ and +# http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/ + + +REPOS="$1" +TXN="$2" + +# Make sure that the log message contains some text. +SVNLOOK=/usr/bin/svnlook +$SVNLOOK log -t "$TXN" "$REPOS" | \ + grep "[a-zA-Z0-9]" > /dev/null || exit 1 + +# Exit on all errors. +set -e + +# Check that the author of this commit has the rights to perform +# the commit on the files and directories being modified. +"$REPOS"/hooks/commit-access-control.pl "$REPOS" $TXN \ + "$REPOS"/hooks/commit-access-control.cfg + +# All checks passed, so allow the commit. +exit 0 diff --git a/test/repositories/svn_empty/hooks/pre-lock.tmpl b/test/repositories/svn_empty/hooks/pre-lock.tmpl new file mode 100755 index 00000000..9fb84425 --- /dev/null +++ b/test/repositories/svn_empty/hooks/pre-lock.tmpl @@ -0,0 +1,73 @@ +#!/bin/sh + +# PRE-LOCK HOOK +# +# The pre-lock hook is invoked before an exclusive lock is +# created. Subversion runs this hook by invoking a program +# (script, executable, binary, etc.) named 'pre-lock' (for which +# this file is a template), with the following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] PATH (the path in the repository about to be locked) +# [3] USER (the user creating the lock) +# [4] COMMENT (the comment of the lock) +# [5] STEAL-LOCK (1 if the user is trying to steal the lock, else 0) +# +# If the hook program outputs anything on stdout, the output string will +# be used as the lock token for this lock operation. If you choose to use +# this feature, you must guarantee the tokens generated are unique across +# the repository each time. +# +# The default working directory for the invocation is undefined, so +# the program should set one explicitly if it cares. +# +# If the hook program exits with success, the lock is created; but +# if it exits with failure (non-zero), the lock action is aborted +# and STDERR is returned to the client. + +# On a Unix system, the normal procedure is to have 'pre-lock' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'pre-lock' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'pre-lock.bat' or 'pre-lock.exe', +# but the basic idea is the same. +# +# Here is an example hook script, for a Unix /bin/sh interpreter: + +REPOS="$1" +PATH="$2" +USER="$3" +COMMENT="$4" +STEAL="$5" + +# If a lock exists and is owned by a different person, don't allow it +# to be stolen (e.g., with 'svn lock --force ...'). + +# (Maybe this script could send email to the lock owner?) +SVNLOOK=/usr/bin/svnlook +GREP=/bin/grep +SED=/bin/sed + +LOCK_OWNER=`$SVNLOOK lock "$REPOS" "$PATH" | \ + $GREP '^Owner: ' | $SED 's/Owner: //'` + +# If we get no result from svnlook, there's no lock, allow the lock to +# happen: +if [ "$LOCK_OWNER" = "" ]; then + exit 0 +fi + +# If the person locking matches the lock's owner, allow the lock to +# happen: +if [ "$LOCK_OWNER" = "$USER" ]; then + exit 0 +fi + +# Otherwise, we've got an owner mismatch, so return failure: +echo "Error: $PATH already locked by ${LOCK_OWNER}." 1>&2 +exit 1 diff --git a/test/repositories/svn_empty/hooks/pre-revprop-change.tmpl b/test/repositories/svn_empty/hooks/pre-revprop-change.tmpl new file mode 100755 index 00000000..5a255285 --- /dev/null +++ b/test/repositories/svn_empty/hooks/pre-revprop-change.tmpl @@ -0,0 +1,66 @@ +#!/bin/sh + +# PRE-REVPROP-CHANGE HOOK +# +# The pre-revprop-change hook is invoked before a revision property +# is added, modified or deleted. Subversion runs this hook by invoking +# a program (script, executable, binary, etc.) named 'pre-revprop-change' +# (for which this file is a template), with the following ordered +# arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] REV (the revision being tweaked) +# [3] USER (the username of the person tweaking the property) +# [4] PROPNAME (the property being set on the revision) +# [5] ACTION (the property is being 'A'dded, 'M'odified, or 'D'eleted) +# +# [STDIN] PROPVAL ** the new property value is passed via STDIN. +# +# If the hook program exits with success, the propchange happens; but +# if it exits with failure (non-zero), the propchange doesn't happen. +# The hook program can use the 'svnlook' utility to examine the +# existing value of the revision property. +# +# WARNING: unlike other hooks, this hook MUST exist for revision +# properties to be changed. If the hook does not exist, Subversion +# will behave as if the hook were present, but failed. The reason +# for this is that revision properties are UNVERSIONED, meaning that +# a successful propchange is destructive; the old value is gone +# forever. We recommend the hook back up the old value somewhere. +# +# On a Unix system, the normal procedure is to have 'pre-revprop-change' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'pre-revprop-change' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'pre-revprop-change.bat' or 'pre-revprop-change.exe', +# but the basic idea is the same. +# +# The hook program typically does not inherit the environment of +# its parent process. For example, a common problem is for the +# PATH environment variable to not be set to its usual value, so +# that subprograms fail to launch unless invoked via absolute path. +# If you're having unexpected problems with a hook program, the +# culprit may be unusual (or missing) environment variables. +# +# Here is an example hook script, for a Unix /bin/sh interpreter. +# For more examples and pre-written hooks, see those in +# /usr/share/subversion/hook-scripts, and in the repository at +# http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/ and +# http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/ + + +REPOS="$1" +REV="$2" +USER="$3" +PROPNAME="$4" +ACTION="$5" + +if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:log" ]; then exit 0; fi + +echo "Changing revision properties other than svn:log is prohibited" >&2 +exit 1 diff --git a/test/repositories/svn_empty/hooks/pre-unlock.tmpl b/test/repositories/svn_empty/hooks/pre-unlock.tmpl new file mode 100755 index 00000000..6f326fbd --- /dev/null +++ b/test/repositories/svn_empty/hooks/pre-unlock.tmpl @@ -0,0 +1,65 @@ +#!/bin/sh + +# PRE-UNLOCK HOOK +# +# The pre-unlock hook is invoked before an exclusive lock is +# destroyed. Subversion runs this hook by invoking a program +# (script, executable, binary, etc.) named 'pre-unlock' (for which +# this file is a template), with the following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] PATH (the path in the repository about to be unlocked) +# [3] USER (the user destroying the lock) +# [4] TOKEN (the lock token to be destroyed) +# [5] BREAK-UNLOCK (1 if the user is breaking the lock, else 0) +# +# The default working directory for the invocation is undefined, so +# the program should set one explicitly if it cares. +# +# If the hook program exits with success, the lock is destroyed; but +# if it exits with failure (non-zero), the unlock action is aborted +# and STDERR is returned to the client. + +# On a Unix system, the normal procedure is to have 'pre-unlock' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'pre-unlock' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'pre-unlock.bat' or 'pre-unlock.exe', +# but the basic idea is the same. +# +# Here is an example hook script, for a Unix /bin/sh interpreter: + +REPOS="$1" +PATH="$2" +USER="$3" +TOKEN="$4" +BREAK="$5" + +# If a lock is owned by a different person, don't allow it be broken. +# (Maybe this script could send email to the lock owner?) + +SVNLOOK=/usr/bin/svnlook +GREP=/bin/grep +SED=/bin/sed + +LOCK_OWNER=`$SVNLOOK lock "$REPOS" "$PATH" | \ + $GREP '^Owner: ' | $SED 's/Owner: //'` + +# If we get no result from svnlook, there's no lock, return success: +if [ "$LOCK_OWNER" = "" ]; then + exit 0 +fi + +# If the person unlocking matches the lock's owner, return success: +if [ "$LOCK_OWNER" = "$USER" ]; then + exit 0 +fi + +# Otherwise, we've got an owner mismatch, so return failure: +echo "Error: $PATH locked by ${LOCK_OWNER}." 1>&2 +exit 1 diff --git a/test/repositories/svn_empty/hooks/start-commit.tmpl b/test/repositories/svn_empty/hooks/start-commit.tmpl new file mode 100755 index 00000000..5a1e6f85 --- /dev/null +++ b/test/repositories/svn_empty/hooks/start-commit.tmpl @@ -0,0 +1,74 @@ +#!/bin/sh + +# START-COMMIT HOOK +# +# The start-commit hook is invoked immediately after a Subversion txn is +# created and populated with initial revprops in the process of doing a +# commit. Subversion runs this hook by invoking a program (script, +# executable, binary, etc.) named 'start-commit' (for which this file +# is a template) with the following ordered arguments: +# +# [1] REPOS-PATH (the path to this repository) +# [2] USER (the authenticated user attempting to commit) +# [3] CAPABILITIES (a colon-separated list of capabilities reported +# by the client; see note below) +# [4] TXN-NAME (the name of the commit txn just created) +# +# Note: The CAPABILITIES parameter is new in Subversion 1.5, and 1.5 +# clients will typically report at least the "mergeinfo" capability. +# If there are other capabilities, then the list is colon-separated, +# e.g.: "mergeinfo:some-other-capability" (the order is undefined). +# +# Note: The TXN-NAME parameter is new in Subversion 1.8. Prior to version +# 1.8, the start-commit hook was invoked before the commit txn was even +# created, so the ability to inspect the commit txn and its metadata from +# within the start-commit hook was not possible. +# +# The list is self-reported by the client. Therefore, you should not +# make security assumptions based on the capabilities list, nor should +# you assume that clients reliably report every capability they have. +# +# The working directory for this hook program's invocation is undefined, +# so the program should set one explicitly if it cares. +# +# If the hook program exits with success, the commit continues; but +# if it exits with failure (non-zero), the commit is stopped before +# a Subversion txn is created, and STDERR is returned to the client. +# +# On a Unix system, the normal procedure is to have 'start-commit' +# invoke other programs to do the real work, though it may do the +# work itself too. +# +# Note that 'start-commit' must be executable by the user(s) who will +# invoke it (typically the user httpd runs as), and that user must +# have filesystem-level permission to access the repository. +# +# On a Windows system, you should name the hook program +# 'start-commit.bat' or 'start-commit.exe', +# but the basic idea is the same. +# +# The hook program typically does not inherit the environment of +# its parent process. For example, a common problem is for the +# PATH environment variable to not be set to its usual value, so +# that subprograms fail to launch unless invoked via absolute path. +# If you're having unexpected problems with a hook program, the +# culprit may be unusual (or missing) environment variables. +# +# Here is an example hook script, for a Unix /bin/sh interpreter. +# For more examples and pre-written hooks, see those in +# /usr/share/subversion/hook-scripts, and in the repository at +# http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/ and +# http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/ + + +REPOS="$1" +USER="$2" + +# Exit on all errors. +set -e + +"$REPOS"/hooks/commit-allower.pl --repository "$REPOS" --user "$USER" +"$REPOS"/hooks/special-auth-check.py --user "$USER" --auth-level 3 + +# All checks passed, so allow the commit. +exit 0 diff --git a/test/repositories/svn_empty/locks/db-logs.lock b/test/repositories/svn_empty/locks/db-logs.lock new file mode 100644 index 00000000..20dd6369 --- /dev/null +++ b/test/repositories/svn_empty/locks/db-logs.lock @@ -0,0 +1,3 @@ +This file is not used by Subversion 1.3.x or later. +However, its existence is required for compatibility with +Subversion 1.2.x or earlier. diff --git a/test/repositories/svn_empty/locks/db.lock b/test/repositories/svn_empty/locks/db.lock new file mode 100644 index 00000000..20dd6369 --- /dev/null +++ b/test/repositories/svn_empty/locks/db.lock @@ -0,0 +1,3 @@ +This file is not used by Subversion 1.3.x or later. +However, its existence is required for compatibility with +Subversion 1.2.x or earlier. diff --git a/test/unit/git_pull_test.rb b/test/unit/git_pull_test.rb index 21d0bfea..745bc610 100644 --- a/test/unit/git_pull_test.rb +++ b/test/unit/git_pull_test.rb @@ -18,5 +18,15 @@ def test_basic_pull end end + def test_basic_pull_with_exception + with_svn_repository('svn_empty') do |src| + OhlohScm::ScratchDir.new do |dest_dir| + dest = GitAdapter.new(:url => dest_dir).normalize + assert !dest.exist? + err = assert_raises(RuntimeError) { dest.pull(src) } + assert_match /Empty repository/, err.message + end + end + end end end From db7b50f1498f18ed5d2d28ca39552e11d0358f46 Mon Sep 17 00:00:00 2001 From: Jebin Date: Fri, 26 May 2017 14:15:05 +0530 Subject: [PATCH 214/219] OTWO-4738: upgraded ruby version 2.2.5 --- .ruby-version | 2 +- .travis/.install_dependencies.sh | 2 ++ lib/ohloh_scm/version.rb | 2 +- test/unit/cvs_branch_number_test.rb | 36 ----------------------------- test/unit/hg_commits_test.rb | 10 -------- test/unit/hg_head_test.rb | 2 +- 6 files changed, 5 insertions(+), 49 deletions(-) diff --git a/.ruby-version b/.ruby-version index f211840f..482f3b3e 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1,2 +1,2 @@ -2.0.0-p648 +2.2.5 diff --git a/.travis/.install_dependencies.sh b/.travis/.install_dependencies.sh index bcec6f01..8cff1281 100755 --- a/.travis/.install_dependencies.sh +++ b/.travis/.install_dependencies.sh @@ -8,6 +8,8 @@ sudo bzr branch lp:bzr-xmloutput sudo mv bzr-xmloutput xmloutput +gem install 'test-unit' -v '3.2.4' + cd xmloutput python setup.py build_ext -i diff --git a/lib/ohloh_scm/version.rb b/lib/ohloh_scm/version.rb index 60715c49..9a6ae742 100644 --- a/lib/ohloh_scm/version.rb +++ b/lib/ohloh_scm/version.rb @@ -1,5 +1,5 @@ module OhlohScm module Version - STRING = '2.2.12' + STRING = '2.3.0' end end diff --git a/test/unit/cvs_branch_number_test.rb b/test/unit/cvs_branch_number_test.rb index 4b5df6ee..03ede171 100644 --- a/test/unit/cvs_branch_number_test.rb +++ b/test/unit/cvs_branch_number_test.rb @@ -69,21 +69,6 @@ def test_complex_primary_revision_number_change assert !b.inherits_from?(BranchNumber.new('3.1')) end - # Crazy CVS inserts a zero before the last piece of a branch number - def test_magic_branch_numbers - assert BranchNumber.new('1.1.2.1').inherits_from?(BranchNumber.new('1.1.0.2')) - assert BranchNumber.new('1.1.2.1.2.1').inherits_from?(BranchNumber.new('1.1.0.2')) - - assert BranchNumber.new('1.1.0.2').inherits_from?(BranchNumber.new('1.1')) - assert !BranchNumber.new('1.1.0.2').inherits_from?(BranchNumber.new('1.2')) - assert !BranchNumber.new('1.1.0.2').inherits_from?(BranchNumber.new('1.1.2.1')) - - assert BranchNumber.new('1.1.0.4').inherits_from?(BranchNumber.new('1.1')) - assert !BranchNumber.new('1.1.0.4').inherits_from?(BranchNumber.new('1.1.2.1')) - assert !BranchNumber.new('1.1.0.4').inherits_from?(BranchNumber.new('1.1.0.2')) - assert !BranchNumber.new('1.1.0.4').inherits_from?(BranchNumber.new('1.1.4.1')) - assert !BranchNumber.new('1.1.0.4').inherits_from?(BranchNumber.new('1.1.0.6')) - end def test_simple_on_same_line b = BranchNumber.new('1.3') @@ -125,27 +110,6 @@ def test_complex_on_same_line assert !b.on_same_line?(BranchNumber.new('1.3.6.3.2.99.2.1')) end - def test_primary_revision_number_change - b = BranchNumber.new('2.3') - - assert b.on_same_line?(BranchNumber.new('2.2')) - assert b.on_same_line?(BranchNumber.new('2.1')) - assert b.on_same_line?(BranchNumber.new('1.1')) - assert b.on_same_line?(BranchNumber.new('1.9999')) - assert b.on_same_line?(BranchNumber.new('2.4')) - assert b.on_same_line?(BranchNumber.new('3.1')) - end - - def test_complex_primary_revision_number_change - b = BranchNumber.new('2.3.2.1') - - assert b.on_same_line?(BranchNumber.new('2.3')) - assert b.on_same_line?(BranchNumber.new('2.2')) - assert b.on_same_line?(BranchNumber.new('1.1')) - assert b.on_same_line?(BranchNumber.new('1.9999')) - assert !b.on_same_line?(BranchNumber.new('2.4')) - assert !b.on_same_line?(BranchNumber.new('3.1')) - end # Crazy CVS inserts a zero before the last piece of a branch number def test_magic_branch_numbers diff --git a/test/unit/hg_commits_test.rb b/test/unit/hg_commits_test.rb index f2b09b6f..1c62d1bc 100644 --- a/test/unit/hg_commits_test.rb +++ b/test/unit/hg_commits_test.rb @@ -72,16 +72,6 @@ def test_commits_with_branch end end - def test_trunk_only_commits - with_hg_repository('hg_dupe_delete') do |hg| - assert_equal ['73e93f57224e3fd828cf014644db8eec5013cd6b', - '732345b1d5f4076498132fd4b965b1fec0108a50', - # '525de321d8085bc1d4a3c7608fda6b4020027985', # On branch - '72fe74d643bdcb30b00da3b58796c50f221017d0'], - hg.commits(:trunk_only => true).collect { |c| c.token } - end - end - def test_trunk_only_commit_count with_hg_repository('hg_dupe_delete') do |hg| assert_equal 4, hg.commit_count(:trunk_only => false) diff --git a/test/unit/hg_head_test.rb b/test/unit/hg_head_test.rb index bca86f9d..c6edcc1c 100644 --- a/test/unit/hg_head_test.rb +++ b/test/unit/hg_head_test.rb @@ -3,7 +3,7 @@ module OhlohScm::Adapters class HgHeadTest < OhlohScm::Test - def test_head_and_parents + def test_hg_head_and_parents with_hg_repository('hg') do |hg| assert_equal '655f04cf6ad7', hg.head_token assert_equal '655f04cf6ad708ab58c7b941672dce09dd369a18', hg.head.token From c0fc6ed59f871cb4131c56be55e5bda313d3bb32 Mon Sep 17 00:00:00 2001 From: Jebin Date: Mon, 21 Aug 2017 14:11:31 +0530 Subject: [PATCH 215/219] OTWO-4904: Fix error caused due branch_name set to nil --- lib/ohloh_scm/adapters/svn_chain/chain.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ohloh_scm/adapters/svn_chain/chain.rb b/lib/ohloh_scm/adapters/svn_chain/chain.rb index 611a3c92..d7c21063 100644 --- a/lib/ohloh_scm/adapters/svn_chain/chain.rb +++ b/lib/ohloh_scm/adapters/svn_chain/chain.rb @@ -79,7 +79,7 @@ def first_commit(after=0) # Returns the first commit with a revision number greater than the provided revision number def next_revision_xml(after=0) return "" if after.to_i >= head_token - run "svn log --trust-server-cert --non-interactive --verbose --xml --stop-on-copy -r #{after.to_i+1}:#{final_token || 'HEAD'} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name))}@#{final_token || 'HEAD'}' | #{ string_encoder }" + run "svn log --trust-server-cert --non-interactive --verbose --xml --stop-on-copy -r #{after.to_i+1}:#{final_token || 'HEAD'} --limit 1 #{opt_auth} '#{SvnAdapter.uri_encode(File.join(self.root, self.branch_name.to_s))}@#{final_token || 'HEAD'}' | #{ string_encoder }" end # If the passed diff represents the wholesale movement of the entire From 9937a8d571f13e2c6f5b97cddb85de4f2a2af4d5 Mon Sep 17 00:00:00 2001 From: santhanakarthikeyan Date: Wed, 23 Aug 2017 12:54:14 +0530 Subject: [PATCH 216/219] OTWO=4901: Changed Hg adapter commit head_token to return long sha instead of short --- lib/ohloh_scm/adapters/hg/head.rb | 2 +- lib/ohloh_scm/version.rb | 2 +- test/unit/hg_head_test.rb | 2 +- test/unit/hglib_head_test.rb | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/ohloh_scm/adapters/hg/head.rb b/lib/ohloh_scm/adapters/hg/head.rb index 4465d446..cf89a16a 100644 --- a/lib/ohloh_scm/adapters/hg/head.rb +++ b/lib/ohloh_scm/adapters/hg/head.rb @@ -4,7 +4,7 @@ def head_token # This only returns first 12 characters. # How can we make it return the entire hash? branch_opts = "--rev #{branch_name || :default}" - token = run("hg id -q #{url} #{branch_opts}").strip + token = run("hg id --debug -i -q #{url} #{branch_opts}").strip # Recent versions of Hg now somtimes append a '+' char to the token. # I believe this signifies pending changes... but we don't care. diff --git a/lib/ohloh_scm/version.rb b/lib/ohloh_scm/version.rb index 9a6ae742..c68bbaba 100644 --- a/lib/ohloh_scm/version.rb +++ b/lib/ohloh_scm/version.rb @@ -1,5 +1,5 @@ module OhlohScm module Version - STRING = '2.3.0' + STRING = '2.3.1' end end diff --git a/test/unit/hg_head_test.rb b/test/unit/hg_head_test.rb index c6edcc1c..d86c0151 100644 --- a/test/unit/hg_head_test.rb +++ b/test/unit/hg_head_test.rb @@ -5,7 +5,7 @@ class HgHeadTest < OhlohScm::Test def test_hg_head_and_parents with_hg_repository('hg') do |hg| - assert_equal '655f04cf6ad7', hg.head_token + assert_equal '655f04cf6ad708ab58c7b941672dce09dd369a18', hg.head_token assert_equal '655f04cf6ad708ab58c7b941672dce09dd369a18', hg.head.token assert hg.head.diffs.any? # diffs should be populated diff --git a/test/unit/hglib_head_test.rb b/test/unit/hglib_head_test.rb index 5704984f..ab409372 100644 --- a/test/unit/hglib_head_test.rb +++ b/test/unit/hglib_head_test.rb @@ -5,7 +5,7 @@ class HgHeadTest < OhlohScm::Test def test_head_and_parents with_hglib_repository('hg') do |hg| - assert_equal '655f04cf6ad7', hg.head_token + assert_equal '655f04cf6ad708ab58c7b941672dce09dd369a18', hg.head_token assert_equal '655f04cf6ad708ab58c7b941672dce09dd369a18', hg.head.token assert hg.head.diffs.any? # diffs should be populated From e02a0fd57deb8ac0f7a068261acee834813c8215 Mon Sep 17 00:00:00 2001 From: Daniel Rubio Date: Wed, 1 Nov 2017 16:29:14 -0500 Subject: [PATCH 217/219] Install updated mercurial --- .travis/.install_multiple_scms.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis/.install_multiple_scms.sh b/.travis/.install_multiple_scms.sh index 3fd09e34..8a34cfdf 100644 --- a/.travis/.install_multiple_scms.sh +++ b/.travis/.install_multiple_scms.sh @@ -4,3 +4,6 @@ sudo apt-add-repository -y ppa:git-core/ppa sudo apt-get update sudo apt-get install -y git subversion cvs bzr mercurial sudo ln -s /usr/bin/cvs /usr/bin/cvsnt +sudo add-apt-repository ppa:mercurial-ppa/releases +sudo apt-get update +sudo apt-get install --only-upgrade mercurial From 08762de33fad4e151e522266b82beccdbcc4e45c Mon Sep 17 00:00:00 2001 From: Daniel Rubio Date: Wed, 1 Nov 2017 16:43:25 -0500 Subject: [PATCH 218/219] Add -y flag --- .travis/.install_multiple_scms.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/.install_multiple_scms.sh b/.travis/.install_multiple_scms.sh index 8a34cfdf..fbb6775e 100644 --- a/.travis/.install_multiple_scms.sh +++ b/.travis/.install_multiple_scms.sh @@ -6,4 +6,4 @@ sudo apt-get install -y git subversion cvs bzr mercurial sudo ln -s /usr/bin/cvs /usr/bin/cvsnt sudo add-apt-repository ppa:mercurial-ppa/releases sudo apt-get update -sudo apt-get install --only-upgrade mercurial +sudo apt-get install --only-upgrade -y mercurial From 11d53376ff953539da7c74b617f08aff834c3d45 Mon Sep 17 00:00:00 2001 From: Daniel Rubio Date: Wed, 1 Nov 2017 17:02:30 -0500 Subject: [PATCH 219/219] Add -y flag to ppa package --- .travis/.install_multiple_scms.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/.install_multiple_scms.sh b/.travis/.install_multiple_scms.sh index fbb6775e..c4045e6a 100644 --- a/.travis/.install_multiple_scms.sh +++ b/.travis/.install_multiple_scms.sh @@ -4,6 +4,6 @@ sudo apt-add-repository -y ppa:git-core/ppa sudo apt-get update sudo apt-get install -y git subversion cvs bzr mercurial sudo ln -s /usr/bin/cvs /usr/bin/cvsnt -sudo add-apt-repository ppa:mercurial-ppa/releases +sudo add-apt-repository -y ppa:mercurial-ppa/releases sudo apt-get update sudo apt-get install --only-upgrade -y mercurial