rscm-accurev 0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
#
|