rscm-accurev 0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +25 -0
- data/README +9 -0
- data/Rakefile +137 -0
- data/STATUS +63 -0
- data/TODO +43 -0
- data/apitest.rb +21 -0
- data/bumprelease.sh +13 -0
- data/lib/rscm/accurev.rb +18 -0
- data/lib/rscm/scm/accurev/api.rb +411 -0
- data/lib/rscm/scm/accurev/api.rb.mine +382 -0
- data/lib/rscm/scm/accurev/api.rb.r263 +364 -0
- data/lib/rscm/scm/accurev/api.rb.r265 +393 -0
- data/lib/rscm/scm/accurev/command.rb +151 -0
- data/lib/rscm/scm/accurev/exception.rb +38 -0
- data/lib/rscm/scm/accurev/filterio.rb +57 -0
- data/lib/rscm/scm/accurev/xml.rb +224 -0
- data/lib/test/unit/ui/xml/testrunner.rb +165 -0
- data/lib/test/unit/ui/xml/xmltestrunner.xslt +79 -0
- data/test/acreplay.rb +22 -0
- data/test/coverage/analyzer.rb +127 -0
- data/test/coverage/c_loader.rb +34 -0
- data/test/coverage/cover.rb +91 -0
- data/test/coverage/coverage_loader.rb +21 -0
- data/test/coverage/coveragetask.rb +38 -0
- data/test/coverage/index_tmpl.html +42 -0
- data/test/coverage/template.html +36 -0
- data/test/eg/ac-files.xml +172 -0
- data/test/eg/ac-pop.txt +195 -0
- data/test/eg/files-various-states.xml +188 -0
- data/test/eg/hist-oneweek-all.xml +1483 -0
- data/test/eg/hist-oneweek-external.xml +246 -0
- data/test/eg/hist-oneweek-promotes.xml +1092 -0
- data/test/eg/info.txt +14 -0
- data/test/eg/stat-a-various.xml +1789 -0
- data/test/eg/stat-m.xml +13 -0
- data/test/eg/stat-overlap.xml +13 -0
- data/test/eg/stat-x.xml +20 -0
- data/test/eg/update-i-mods-and-updates-and-overlap.xml +73 -0
- data/test/eg/update-i-nochanges.xml +8 -0
- data/test/eg/update-i-stale.xml +0 -0
- data/test/eg/update-i-updates.xml +125 -0
- data/test/eg/update-newwksp.xml +183 -0
- data/test/eg/update-nochanges.xml +7 -0
- data/test/eg/update-stale.xml +12 -0
- data/test/eg/update-updates.xml +147 -0
- data/test/t_api.rb +163 -0
- data/test/t_command.rb +85 -0
- data/test/t_filterio.rb +60 -0
- data/test/t_load.rb +11 -0
- data/test/t_scrubio.rb +117 -0
- data/test/t_xmlmapper.rb +75 -0
- metadata +106 -0
data/LICENSE
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
Copyright (c) 2005, Gregory D. Fast
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions
|
6
|
+
are met:
|
7
|
+
|
8
|
+
* Redistributions of source code must retain the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer.
|
10
|
+
|
11
|
+
* Redistributions in binary form must reproduce the above copyright
|
12
|
+
notice, this list of conditions and the following disclaimer in the
|
13
|
+
documentation and/or other materials provided with the distribution.
|
14
|
+
|
15
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
16
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
17
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
18
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
19
|
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
20
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
21
|
+
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
22
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
23
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
24
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
25
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rake'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
require 'rake/packagetask'
|
7
|
+
require 'rake/gempackagetask'
|
8
|
+
require 'tracer'
|
9
|
+
|
10
|
+
# this rakefile originally borrowed shamelessly from rscm
|
11
|
+
|
12
|
+
PKG_NAME = 'rscm-accurev'
|
13
|
+
PKG_BUILD = ENV['PKG_BUILD'] ? '.'+ENV['PKG_BUILD'] : ''
|
14
|
+
PKG_VERSION = '0.0' + PKG_BUILD
|
15
|
+
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
16
|
+
PKG_SUMMARY = 'RSCM::Accurev - RSCM API for Accurev'
|
17
|
+
|
18
|
+
desc "Default Task"
|
19
|
+
task :default => [ :test, :gem ]
|
20
|
+
|
21
|
+
RAKEVERSION =~ /^(\d+)\.(\d+).(.*)/
|
22
|
+
rake_maj,rake_min,rake_patch = $1,$2,$3
|
23
|
+
if rake_maj.to_f < 1 and rake_min.to_f <= 5 and rake_patch.to_f <= 4
|
24
|
+
# use this for rake <= 0.5.4:
|
25
|
+
task :test => [ :plaintest ]
|
26
|
+
HAVEXMLTEST = false
|
27
|
+
else
|
28
|
+
# rake 0.5.4.6+ (0.5.5)
|
29
|
+
task :test => [ :backup_testresults, :xmltest ]
|
30
|
+
HAVEXMLTEST = true
|
31
|
+
end
|
32
|
+
|
33
|
+
# define a task(s) to run tests
|
34
|
+
|
35
|
+
test_files = FileList.new( "test/**/t_*.rb" )
|
36
|
+
TEST_OUTPUT = "html/test"
|
37
|
+
|
38
|
+
Rake::TestTask.new( :plaintest ) do |t|
|
39
|
+
t.libs << "test"
|
40
|
+
t.test_files = test_files
|
41
|
+
t.verbose = true
|
42
|
+
end
|
43
|
+
|
44
|
+
if HAVEXMLTEST
|
45
|
+
# rake<0.5.5 requires a patch to rake_test_loader.rb to exclude options
|
46
|
+
# rake<0.5.5 requires a patch to rake/testtask.rb to support ruby_opts
|
47
|
+
# (see doc/patches)
|
48
|
+
Rake::TestTask.new( :xmltest ) do |t|
|
49
|
+
t.libs << "test"
|
50
|
+
t.test_files = test_files
|
51
|
+
t.verbose = true
|
52
|
+
t.ruby_opts << '-rtest/unit/ui/xml/testrunner'
|
53
|
+
ENV['XMLTEST_OUTPUT'] = "#{TEST_OUTPUT}/testresults.xml"
|
54
|
+
t.options = "--runner=xml"
|
55
|
+
end
|
56
|
+
end # !HAVEXMLTEST
|
57
|
+
|
58
|
+
|
59
|
+
# backs up existing testresults.xml files in test target dir
|
60
|
+
task :backup_testresults do
|
61
|
+
unless File.exist?( TEST_OUTPUT )
|
62
|
+
mkdir_p( TEST_OUTPUT )
|
63
|
+
end
|
64
|
+
old = "#{TEST_OUTPUT}/testresults.xml"
|
65
|
+
if File.exist?( old )
|
66
|
+
stat = File.stat( old )
|
67
|
+
bak = stat.ctime.strftime('testresults-%Y%m%d-%H%M.xml')
|
68
|
+
new = "#{TEST_OUTPUT}/#{bak}"
|
69
|
+
#puts "...Backing up previous test results to #{new}"
|
70
|
+
mv( old, new )
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# define a task to create rdocs
|
75
|
+
# keep a reference to it so we can reuse it in the gempkg task
|
76
|
+
rd_task = Rake::RDocTask.new( :rdoc ) do |rdoc|
|
77
|
+
rdoc.title = PKG_SUMMARY
|
78
|
+
rdoc.template = "doc/jamis.rb" # so nice
|
79
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
80
|
+
rdoc.rdoc_files.include( 'STATUS' )
|
81
|
+
rdoc.rdoc_files.include( 'lib/**/*.rb' )
|
82
|
+
rdoc.rdoc_files.include( 'doc/*.rd' )
|
83
|
+
end
|
84
|
+
|
85
|
+
PKG_FILES = FileList[
|
86
|
+
'*',
|
87
|
+
'lib/**/*',
|
88
|
+
'test/**/*'
|
89
|
+
]
|
90
|
+
|
91
|
+
if ! defined?(Gem)
|
92
|
+
puts "Target 'package' requires RubyGems"
|
93
|
+
else
|
94
|
+
spec = Gem::Specification.new do |s|
|
95
|
+
s.name = PKG_NAME
|
96
|
+
s.version = PKG_VERSION
|
97
|
+
s.summary = PKG_SUMMARY
|
98
|
+
s.description = "RSCM::Accurev is an RSCM API for the SCM tool Accurev (http://www.accurev.com/)."
|
99
|
+
s.files = PKG_FILES.to_a
|
100
|
+
s.require_path = 'lib'
|
101
|
+
s.autorequire = 'rscm/scm/accurev'
|
102
|
+
s.has_rdoc = true
|
103
|
+
rd_task.options.each {|opt| s.rdoc_options << opt }
|
104
|
+
s.author = "Greg Fast"
|
105
|
+
s.email = "gdf@speakeasy.net"
|
106
|
+
s.homepage = "http://rscm-accurev.rubyforge.org"
|
107
|
+
end
|
108
|
+
|
109
|
+
# define a gem package task
|
110
|
+
Rake::GemPackageTask.new( spec ) do |pkg|
|
111
|
+
pkg.need_zip = true
|
112
|
+
pkg.need_tar = true
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
desc "Delete all generated files (includes built packages)"
|
117
|
+
task :realclean do
|
118
|
+
f = FileList[ 'pkg', 'html', 'doc/test*.xml' ]
|
119
|
+
rm_rf f
|
120
|
+
end
|
121
|
+
|
122
|
+
desc "Coverage! (still a big hack)"
|
123
|
+
task :coverage => [ :test_coverage, :coverage_summary ]
|
124
|
+
|
125
|
+
Rake::TestTask.new( :test_coverage ) do |t|
|
126
|
+
t.libs << "test"
|
127
|
+
t.test_files = test_files
|
128
|
+
t.verbose = true
|
129
|
+
def t.rake_loader
|
130
|
+
'test/coverage/c_loader.rb'
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
task :coverage_summary do
|
135
|
+
# too many options!@
|
136
|
+
ruby "test/coverage/analyzer.rb xxx.trace html/coverage test/coverage/template.html test/coverage/index_tmpl.html"
|
137
|
+
end
|
data/STATUS
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
|
2
|
+
= RSCM::Accurev Status
|
3
|
+
|
4
|
+
------------------------
|
5
|
+
|
6
|
+
== Core RSCM API (RSCM::Accurev::API)
|
7
|
+
|
8
|
+
[checkout()] supported
|
9
|
+
|
10
|
+
- basic checkouts should work
|
11
|
+
|
12
|
+
- time-based checkouts do not work
|
13
|
+
|
14
|
+
[update()] basic updates work
|
15
|
+
|
16
|
+
- time-based updates ("update( yesterday )") not working
|
17
|
+
|
18
|
+
- elements list returned currently includes directories and removed files
|
19
|
+
|
20
|
+
[add()] unsupported, todo(?)
|
21
|
+
|
22
|
+
[edit()] supported (no-op)
|
23
|
+
|
24
|
+
[revisions()] supported
|
25
|
+
|
26
|
+
- time-based limits do not work
|
27
|
+
|
28
|
+
- should be history-based
|
29
|
+
|
30
|
+
-------------------------------------------
|
31
|
+
|
32
|
+
== Accurev-specific API (RSCM::Accurev::API)
|
33
|
+
|
34
|
+
[ac_update()] unsupported, todo
|
35
|
+
|
36
|
+
[ac_files()] supported
|
37
|
+
|
38
|
+
[ac_info()] supported
|
39
|
+
|
40
|
+
[ac_stat()] unsupported, use ac_files().
|
41
|
+
|
42
|
+
[ac_move()] unsupported, todo
|
43
|
+
|
44
|
+
[ac_pop()] unsupported, todo
|
45
|
+
|
46
|
+
[ac_purge()] unsupported, todo
|
47
|
+
|
48
|
+
[ac_hist()] unsupported, todo
|
49
|
+
|
50
|
+
[ac_keep()] unsupported, todo
|
51
|
+
|
52
|
+
[ac_promote()] unsupported, todo
|
53
|
+
|
54
|
+
-------------------------------------------
|
55
|
+
|
56
|
+
== Other Items
|
57
|
+
|
58
|
+
[code docs] woefully incomplete
|
59
|
+
|
60
|
+
[usage docs] virtually nonexistant
|
61
|
+
|
62
|
+
[test coverage] truly pitiful
|
63
|
+
|
data/TODO
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# todo for rscm/scm/accurev.rb
|
2
|
+
|
3
|
+
api - checkout
|
4
|
+
- there is no rscm-api update() (only checkout-to-existing-ws)
|
5
|
+
- `pop`, `update`
|
6
|
+
|
7
|
+
**api - revisions
|
8
|
+
- `hist` (others?)
|
9
|
+
|
10
|
+
api - diff
|
11
|
+
- `diff` (yukx)
|
12
|
+
|
13
|
+
api - import_central, create_central
|
14
|
+
- munge depots - probably skip these, or use acxmlparser
|
15
|
+
|
16
|
+
api - api-specific commands to manage streams
|
17
|
+
- use acxmlparser
|
18
|
+
|
19
|
+
api - triggers?
|
20
|
+
|
21
|
+
**api - identifiers (Time or revision) to ac format
|
22
|
+
- is this even always applicable? does stat/update take limits?
|
23
|
+
|
24
|
+
# xml - s/FileStatus/FileData/
|
25
|
+
|
26
|
+
api - checkout(Time.infinite) just does update
|
27
|
+
checkout(x) only works if ws not exist
|
28
|
+
unless it implies nuke-and-re-checkout (slow)
|
29
|
+
|
30
|
+
api - need ac_update which returns an acresponse
|
31
|
+
|
32
|
+
api - update: elements list should not contain directories
|
33
|
+
|
34
|
+
api - update: elements list should probably not include removed files
|
35
|
+
|
36
|
+
# command - Command.working_dir is bad: should use with_working_dir()
|
37
|
+
|
38
|
+
*** api - checkout() should use `pop` instead of `mkws`, unless
|
39
|
+
user *really* wants it
|
40
|
+
- yeargh... how does update work with pop? just nuke and/or overwrite?
|
41
|
+
|
42
|
+
ac pop -R -v orbitz-host-gt3-0-rc -L . . > ~/cheese/rscm-accurev/test/eg/ac-pop.txt
|
43
|
+
|
data/apitest.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/opt/ruby/bin/ruby
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
$:<<"lib"
|
5
|
+
require 'rscm/scm/accurev'
|
6
|
+
|
7
|
+
#files; ac = RSCM::Accurev.new( '/home/gfast/dev/orbitz-host-gt3-0-impl' )
|
8
|
+
#files; ac.ac_files(".").each do |f|
|
9
|
+
#files; puts "#{f.location}\t\t#{f.status}"
|
10
|
+
#files; end
|
11
|
+
|
12
|
+
# yes, i cannot spell, the dir is "hirdcar":
|
13
|
+
ac = RSCM::Accurev.new( '/home/gfast/dev/orbitz-api-hirdcar-0-rc' )
|
14
|
+
ac.backing_stream = "orbitz-api-hiredcar-0-rc"
|
15
|
+
ac.workspace_stream = "orbitz-api-hiredcar-0-rc-testing_gfast"
|
16
|
+
ac.checkout() do |l|
|
17
|
+
puts l
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
|
data/bumprelease.sh
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
# gee, i bet you could stick this in the rakefile...
|
4
|
+
|
5
|
+
LAST=`cat .version.minor`
|
6
|
+
MINOR=$(( $LAST + 1 ))
|
7
|
+
|
8
|
+
perl -i~~ -pe "s/VERSION = '0.0.\d+'/VERSION = '0.0.$MINOR'/" \
|
9
|
+
lib/rscm/accurev.rb
|
10
|
+
|
11
|
+
PKG_BUILD=$MINOR rake package gem && \
|
12
|
+
echo $MINOR > .version.minor
|
13
|
+
|
data/lib/rscm/accurev.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rscm/scm/accurev/api'
|
3
|
+
require 'rscm/scm/accurev/command'
|
4
|
+
require 'rscm/scm/accurev/xml'
|
5
|
+
require 'rscm/scm/accurev/filterio'
|
6
|
+
|
7
|
+
module RSCM
|
8
|
+
#
|
9
|
+
# == module RSCM::Accurev
|
10
|
+
#
|
11
|
+
# Namespace for accurev api classes and utils.
|
12
|
+
#
|
13
|
+
# See RSCM::Accurev::API.
|
14
|
+
#
|
15
|
+
module Accurev
|
16
|
+
VERSION = '0.0.5'
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,411 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
#
|
3
|
+
# = api.rb
|
4
|
+
#
|
5
|
+
# API for interacting with accurev workspaces.
|
6
|
+
#
|
7
|
+
# Includes:
|
8
|
+
#
|
9
|
+
# * API
|
10
|
+
#
|
11
|
+
require 'stringio'
|
12
|
+
require 'rscm/base'
|
13
|
+
require 'rscm/path_converter'
|
14
|
+
require 'rexml/document'
|
15
|
+
require 'rscm/scm/accurev/xml'
|
16
|
+
require 'rscm/scm/accurev/filterio'
|
17
|
+
require 'rscm/scm/accurev/command'
|
18
|
+
require 'rscm/scm/accurev/exception'
|
19
|
+
|
20
|
+
# need to define module within module before you can use module X::Y
|
21
|
+
module RSCM; module Accurev; end; end
|
22
|
+
|
23
|
+
module RSCM::Accurev
|
24
|
+
|
25
|
+
#
|
26
|
+
# RSCM implementation for Accurev (http://www.accurev.com).
|
27
|
+
#
|
28
|
+
# Requires an accurev cli executable on the path (see also
|
29
|
+
# RSCM::Accurev::Command), and the correct environment
|
30
|
+
# configuration for ac server/principal/password.
|
31
|
+
#
|
32
|
+
# ---
|
33
|
+
#
|
34
|
+
# === Example
|
35
|
+
#
|
36
|
+
# api = RSCM::Accurev::API.new( "./ws/proj-1", "proj", "proj-1" )
|
37
|
+
# api.checkout() each do |file|
|
38
|
+
# puts "Updated #{file}..."
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
class API < RSCM::Base
|
42
|
+
register self
|
43
|
+
|
44
|
+
ann :description => "Accurev Depot"
|
45
|
+
attr_accessor :depot
|
46
|
+
|
47
|
+
ann :description => "Backing Stream (autodetected)"
|
48
|
+
attr_accessor :backing_stream
|
49
|
+
|
50
|
+
# If workspace stream is nil (the default), checkout/update will be
|
51
|
+
# done using `accurev pop`. This is faster and more appropriate for
|
52
|
+
# read-only use; however a workspace is required for commits.
|
53
|
+
ann :description => "Workspace Stream"
|
54
|
+
attr_accessor :workspace_stream
|
55
|
+
|
56
|
+
# [defined in Base]
|
57
|
+
# ann :description => "Filesystem Path to Workspace"
|
58
|
+
# attr_accessor :checkout_dir
|
59
|
+
|
60
|
+
ann :description => "Overwrite Mode: if true, co overwrites existing"
|
61
|
+
attr_accessor :overwrite
|
62
|
+
|
63
|
+
def initialize(checkout_dir=nil, backing_stream=nil, workspace_stream=nil)
|
64
|
+
@depot = nil # will be pulled from files cmd output
|
65
|
+
@workspace_stream = workspace_stream
|
66
|
+
@backing_stream = backing_stream
|
67
|
+
@checkout_dir = checkout_dir
|
68
|
+
@overwrite = false
|
69
|
+
end
|
70
|
+
|
71
|
+
def name()
|
72
|
+
return "Accurev"
|
73
|
+
end
|
74
|
+
|
75
|
+
# Accurev operations are atomic: returns true.
|
76
|
+
def transactional?
|
77
|
+
return true
|
78
|
+
end
|
79
|
+
|
80
|
+
# "Adds +relative_filename+ to the working copy."
|
81
|
+
def add( relative_filename )
|
82
|
+
raise "XXX implement me"
|
83
|
+
end
|
84
|
+
|
85
|
+
def edit( relative_filename )
|
86
|
+
# NOP - not required for ac
|
87
|
+
end
|
88
|
+
|
89
|
+
# "Returns a Revisions object for the period specified ... (inclusive)."
|
90
|
+
#
|
91
|
+
# list txns (promotes to bs) from hist within the period
|
92
|
+
#
|
93
|
+
def revisions( from_identifier, to_identifier=Time.infinity )
|
94
|
+
raise "XXX implement me"
|
95
|
+
end
|
96
|
+
|
97
|
+
# default impl depends on a correct impl of revisions()
|
98
|
+
# def uptodate?( identifier=nil )
|
99
|
+
#
|
100
|
+
# end
|
101
|
+
|
102
|
+
# def checked_out? - base
|
103
|
+
|
104
|
+
# accurev actually does have triggers, but I haven't implemented that yet
|
105
|
+
def supports_trigger?
|
106
|
+
false
|
107
|
+
end
|
108
|
+
|
109
|
+
# def diff() XXX
|
110
|
+
|
111
|
+
|
112
|
+
# --- ac specific
|
113
|
+
|
114
|
+
# remember: ac_files is non-recursive
|
115
|
+
def ac_files( relative_path )
|
116
|
+
cmd = Command.instance
|
117
|
+
ret = []
|
118
|
+
with_working_dir( co_filepath ) do
|
119
|
+
acresponse = cmd.accurev( "files", relative_path )
|
120
|
+
if acresponse['element'].nil?
|
121
|
+
return []
|
122
|
+
end
|
123
|
+
acresponse['element'].each do |fd|
|
124
|
+
yield fd if block_given?
|
125
|
+
ret << fd
|
126
|
+
end
|
127
|
+
end
|
128
|
+
return ret
|
129
|
+
end
|
130
|
+
|
131
|
+
def ac_stat( flag="-a" )
|
132
|
+
cmd = Command.instance
|
133
|
+
ret = []
|
134
|
+
with_working_dir( co_filepath ) do
|
135
|
+
acresponse = cmd.accurev( "stat", flag )
|
136
|
+
return [] if acresponse['element'].nil?
|
137
|
+
acresponse['element'].each do |fd|
|
138
|
+
yield fd if block_given?
|
139
|
+
ret << fd
|
140
|
+
end
|
141
|
+
end
|
142
|
+
return ret
|
143
|
+
end
|
144
|
+
|
145
|
+
# yeilds the TransactionData objects for the given time period
|
146
|
+
# (promotes only)
|
147
|
+
def ac_hist( from, to=Time.infinite )
|
148
|
+
cmd = Command.instance
|
149
|
+
lower = from.to_accurev
|
150
|
+
upper = "now"
|
151
|
+
unless to == Time.infinite
|
152
|
+
upper = to.to_accurev
|
153
|
+
end
|
154
|
+
with_working_dir( self.co_filepath ) do
|
155
|
+
acresponse = cmd.accurev( "hist",
|
156
|
+
"-t", "'#{upper}-#{lower}'",
|
157
|
+
"-k", "promote"
|
158
|
+
)
|
159
|
+
ret = []
|
160
|
+
acresponse['transaction'].each do |txn|
|
161
|
+
ret << txn
|
162
|
+
yield txn if block_given?
|
163
|
+
end
|
164
|
+
return ret
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def ac_keep( files=[], message="" )
|
169
|
+
raise "XXX implement me"
|
170
|
+
end
|
171
|
+
|
172
|
+
def ac_promote( files=[], message="" )
|
173
|
+
raise "XXX implement me"
|
174
|
+
end
|
175
|
+
|
176
|
+
def ac_update( relative_path="." )
|
177
|
+
d = accurev( "update", relative_path )
|
178
|
+
if xxx_error_stale
|
179
|
+
raise StaleWorkspaceError.new( "#{relative_path} is stale -- keep/anchor all changes and re-update" )
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def ac_purge( files=[] )
|
184
|
+
raise "XXX implement me"
|
185
|
+
end
|
186
|
+
|
187
|
+
def ac_revert( files=[] )
|
188
|
+
raise "XXX implement me"
|
189
|
+
end
|
190
|
+
|
191
|
+
def ac_move( current_file, new_file )
|
192
|
+
raise "XXX implement me"
|
193
|
+
end
|
194
|
+
|
195
|
+
#
|
196
|
+
# Performs an "accurev info" command in the workspace.
|
197
|
+
# Returns a map of
|
198
|
+
#
|
199
|
+
# ac info: shows eg, backing stream
|
200
|
+
# but doesn't support -fx!
|
201
|
+
#
|
202
|
+
def ac_info()
|
203
|
+
co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir )
|
204
|
+
unless File.exists?( co )
|
205
|
+
raise AccurevException.new( "Checkout dir #{co} does not exist" )
|
206
|
+
end
|
207
|
+
info = {}
|
208
|
+
with_working_dir( co ) do
|
209
|
+
cmd = Command.instance
|
210
|
+
io = StringIO.new( cmd.accurev_nofx( "info" ) )
|
211
|
+
io.each_line do |line|
|
212
|
+
next unless line =~ /\S/
|
213
|
+
if line =~ /^(.*?):\s+(.*)$/
|
214
|
+
info[$1] = $2
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
return info
|
219
|
+
end
|
220
|
+
|
221
|
+
# ac mkws
|
222
|
+
# -b orbitz-host-gt3-0-impl
|
223
|
+
# -w orbitz-host-gt3-0-impl-test2_gfast
|
224
|
+
# -l `pwd`
|
225
|
+
# - does not support fx (argh!@)
|
226
|
+
# - does not pop
|
227
|
+
#
|
228
|
+
|
229
|
+
# diff: /usr/local/bin/acdiff (!) --fx
|
230
|
+
# (after an ac cat on the backed file)
|
231
|
+
# (eg, no in-process diffing ala cvs diff)
|
232
|
+
# lists modified lines in xml
|
233
|
+
|
234
|
+
#
|
235
|
+
# "Checks out or updates[!] contents from a central SCM
|
236
|
+
# to +checkout_dir+ - a local working copy."
|
237
|
+
#
|
238
|
+
# "The +to_identifier+ parameter may be optionally specified to
|
239
|
+
# obtain files up to a particular time or label."
|
240
|
+
#
|
241
|
+
# For accurev, this:
|
242
|
+
# * checks to see if +@checkout_dir+ exists and appears checked out.
|
243
|
+
# If it's already checked out, this calls +update()+. If
|
244
|
+
# +@checkout_dir+ exists and +to_identifier+ is given, an
|
245
|
+
# exception is raised.
|
246
|
+
# * otherwise, this creates a new workspace stream and populates it
|
247
|
+
# at +@checkout_dir+.
|
248
|
+
#
|
249
|
+
# This both returns and yields a list of updated files.
|
250
|
+
# Only updated files are returned, not directories.
|
251
|
+
#
|
252
|
+
# Current, ac_update returns both files and directories, including
|
253
|
+
# deleted files.
|
254
|
+
#
|
255
|
+
def checkout( to_identifier=Time.infinite )
|
256
|
+
co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir )
|
257
|
+
if @backing_stream.nil?
|
258
|
+
self.attempt_init_from_info()
|
259
|
+
end
|
260
|
+
if @workspace_stream.nil?
|
261
|
+
self.checkout_pop()
|
262
|
+
else
|
263
|
+
unless File.exists?( co )
|
264
|
+
# create new workspace
|
265
|
+
self.checkout_workspace()
|
266
|
+
end
|
267
|
+
# update workspace
|
268
|
+
self.update( to_identifier )
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
def checkout_pop()
|
273
|
+
co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir )
|
274
|
+
raise "A backing stream is required" if @backing_stream.nil?
|
275
|
+
raise "A working stream may not be given" unless @working_stream.nil?
|
276
|
+
# for `accurev pop`: remove and re-pop the checkout copy
|
277
|
+
if File.exists?( co )
|
278
|
+
unless @overwrite
|
279
|
+
raise "Checkout dir #{co} already exists (@overwrite=#@overwrite)"
|
280
|
+
end
|
281
|
+
rm_rf( co )
|
282
|
+
end
|
283
|
+
mkdir(co)
|
284
|
+
with_working_dir( co ) do
|
285
|
+
cmd = Command.instance
|
286
|
+
pop_out = cmd.accurev_nofx("pop",
|
287
|
+
"-R",
|
288
|
+
"-v", @backing_stream,
|
289
|
+
"-L", ".", ".")
|
290
|
+
elems = []
|
291
|
+
popio = StringIO.new( pop_out )
|
292
|
+
popio.each_line do |line|
|
293
|
+
if line =~ /^Populating element \/.\/(.*)$/
|
294
|
+
loc = $1
|
295
|
+
elems << loc
|
296
|
+
yield loc if block_given?
|
297
|
+
end
|
298
|
+
end
|
299
|
+
return elems
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
def checkout_workspace()
|
304
|
+
co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir )
|
305
|
+
raise "A backing stream is required" if @backing_stream.nil?
|
306
|
+
raise "A workspace is required" if @working_stream.nil?
|
307
|
+
if File.exist?( co ) and !@overwrite
|
308
|
+
raise "Checkout dir #{co} already exists (@overwrite=#@overwrite)"
|
309
|
+
end
|
310
|
+
cmd = Command.instance
|
311
|
+
mkws_out = cmd.accurev_nofx( "mkws",
|
312
|
+
"-b", @backing_stream,
|
313
|
+
"-w", @workspace_stream,
|
314
|
+
"-l", co )
|
315
|
+
# kinda sucks:
|
316
|
+
if ( mkws_out =~ /already exists/ )
|
317
|
+
raise AccurevException.new( "Failed to checkout", mkws_out )
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
def update( to_identifier=Time.infinite )
|
322
|
+
co = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir )
|
323
|
+
unless File.exists?( co )
|
324
|
+
raise AccurevException.new( "Workspace does not exist!" )
|
325
|
+
end
|
326
|
+
updated = []
|
327
|
+
with_working_dir( co ) do
|
328
|
+
cmd = Command.instance
|
329
|
+
acresponse = cmd.accurev( "update" )
|
330
|
+
if acresponse.error
|
331
|
+
if acresponse.error =~ /workspace have been modified/
|
332
|
+
raise StaleWorkspaceException.new( "Workspace stale",
|
333
|
+
acresponse.error )
|
334
|
+
else
|
335
|
+
# some other update problem
|
336
|
+
raise AccurevException.new( "Error on update", acresponse.error )
|
337
|
+
end
|
338
|
+
end
|
339
|
+
if acresponse['element']
|
340
|
+
acresponse['element'].each do |up|
|
341
|
+
# "ac update" on a new workspace yields element locations
|
342
|
+
# with leading "/"s, which should be removed to get a proper
|
343
|
+
# relative path:
|
344
|
+
loc = up.location.sub( /^\//, "" )
|
345
|
+
yield loc if block_given?
|
346
|
+
updated << loc
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
350
|
+
return updated
|
351
|
+
end
|
352
|
+
|
353
|
+
# --- internals
|
354
|
+
|
355
|
+
# status flag mappings for "stat", "file" commands
|
356
|
+
STATUSES = {
|
357
|
+
'(backed)' => :backed,
|
358
|
+
'(external)' => :external,
|
359
|
+
'(modified)' => :modified,
|
360
|
+
'(kept)' => :kept,
|
361
|
+
'(defunct)' => :defunct,
|
362
|
+
'(missing)' => :missing,
|
363
|
+
'(stranded)' => :stranded,
|
364
|
+
'(overlap)' => :overlap
|
365
|
+
}
|
366
|
+
|
367
|
+
# private
|
368
|
+
|
369
|
+
# psuedo-accessor (cached)
|
370
|
+
def co_filepath
|
371
|
+
if @co_filepath.nil?
|
372
|
+
@co_filepath = RSCM::PathConverter.nativepath_to_filepath( @checkout_dir )
|
373
|
+
end
|
374
|
+
return @co_filepath
|
375
|
+
end
|
376
|
+
|
377
|
+
#
|
378
|
+
# Runs an `ac info` command in +@checkout_dir+, and tries to
|
379
|
+
# set +@backing_stream+ and +@workspace_stream+ from the output.
|
380
|
+
#
|
381
|
+
def attempt_init_from_info()
|
382
|
+
if File.exists?( self.co_filepath )
|
383
|
+
info = self.ac_info
|
384
|
+
if info.has_key?( "Basis" )
|
385
|
+
@backing_stream = info["Basis"]
|
386
|
+
end
|
387
|
+
if info.has_key?( "ws/ref" )
|
388
|
+
@workspace_stream = info["ws/ref"]
|
389
|
+
end
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
# Takes a status flags line (eg, "(modified)(kept)")
|
394
|
+
# and returns a list of status flags.
|
395
|
+
def map_status( status_line )
|
396
|
+
l = status_line.split( " " ).map {|x| x.trim}
|
397
|
+
end
|
398
|
+
|
399
|
+
end
|
400
|
+
|
401
|
+
end
|
402
|
+
|
403
|
+
class Time
|
404
|
+
def to_accurev
|
405
|
+
self.strftime( "%Y/%m/%d %H:%M:%S" )
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
#
|
410
|
+
# Copyright (c) 2005 Gregory D. Fast <gdf@speakeasy.net>
|
411
|
+
#
|