fact 0.1.1.a
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Gemfile +8 -0
- data/LICENSE +22 -0
- data/README.md +63 -0
- data/Rakefile +1 -0
- data/bin/fact +46 -0
- data/fact.gemspec +27 -0
- data/lib/fact/activities_cli.rb +96 -0
- data/lib/fact/clearcase.rb +168 -0
- data/lib/fact/files_cli.rb +44 -0
- data/lib/fact/version.rb +3 -0
- data/lib/fact.rb +5 -0
- data/test/tests.rb +105 -0
- metadata +80 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*~
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2011, FireAphis (github.com/FireAphis). All rights reserved.
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without modification,
|
4
|
+
are permitted provided that the following conditions are met:
|
5
|
+
|
6
|
+
- Redistributions of source code must retain the above copyright notice, this
|
7
|
+
list of conditions and the following disclaimer.
|
8
|
+
|
9
|
+
- Redistributions in binary form must reproduce the above copyright notice,
|
10
|
+
this list of conditions and the following disclaimer in the documentation
|
11
|
+
and/or other materials provided with the distribution.
|
12
|
+
|
13
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
14
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
15
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
16
|
+
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
17
|
+
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
18
|
+
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
19
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
20
|
+
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
21
|
+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
22
|
+
POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
Purpose and features
|
2
|
+
====================
|
3
|
+
|
4
|
+
FireAphisClearerTool (FACT) is a small project intended to make a life
|
5
|
+
with ClearCase a little bit happier. The project tries to achieve the
|
6
|
+
goal in two ways:
|
7
|
+
|
8
|
+
1. Create an intuitive front end for IBM Rational ClearCase SCM.
|
9
|
+
2. Create a library that simplifies the process of development of scripts
|
10
|
+
that interact with ClearCase.
|
11
|
+
|
12
|
+
IBM Rational ClearCase comes bundled with two user interfaces: one
|
13
|
+
graphical and one command line based. Both, in my humble opinion, impact
|
14
|
+
user productivity severely. The graphical interface requires unreasonable
|
15
|
+
amount of mouse clicks for simple tasks, it doesn't support keyboard
|
16
|
+
input, its output is obscure, it is inconsistent and it is ugly. The
|
17
|
+
command line tool tries to solve all the problems in the world thus having
|
18
|
+
a very complicated syntax and an enormous amount of commands and options.
|
19
|
+
|
20
|
+
From my personal experience, I tend to perform same tasks over and over
|
21
|
+
again. Each time I have to choose between tedious and cluttered GUI and
|
22
|
+
looking through my notes for the correct combination of over sophisticated
|
23
|
+
command line commands.
|
24
|
+
|
25
|
+
This tool allows to perform the most common tasks in minimal amount of
|
26
|
+
clicks and supplies only the necessary information in the most readable
|
27
|
+
format, I could think of. Hope you will enjoy it too.
|
28
|
+
|
29
|
+
|
30
|
+
CLI
|
31
|
+
---
|
32
|
+
|
33
|
+
By executing ```fact``` the user enters the CLI mode. This mode is designed
|
34
|
+
to support common use cases. It is supposed to make the job done in minimum
|
35
|
+
key presses and without the need to remember numerous commands.
|
36
|
+
|
37
|
+
Here's the current menus hierarchy of the CLI mode:
|
38
|
+
|
39
|
+
```
|
40
|
+
Undelivered activities
|
41
|
+
|
|
42
|
+
--- Activity change set
|
43
|
+
|
|
44
|
+
--- File information
|
45
|
+
|
|
46
|
+
--- Change set predecessor diff
|
47
|
+
```
|
48
|
+
|
49
|
+
Dependencies
|
50
|
+
============
|
51
|
+
|
52
|
+
The tool requires Ruby, ClearCase cleartool (comes bundled with ClearCase)
|
53
|
+
and HighLine gem (http://highline.rubyforge.org/). Cleartool has to be on
|
54
|
+
your PATH.
|
55
|
+
|
56
|
+
Tested with the following versions:
|
57
|
+
|
58
|
+
- CentOS 5.3
|
59
|
+
- Ruby 1.8.5 and 1.9.2
|
60
|
+
- HighLine 1.6.1
|
61
|
+
- IBM Rational ClearCase 7.0.1
|
62
|
+
|
63
|
+
If you run it on different versions, let me know, so I can update the list.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/bin/fact
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
# FireAphisClearerTool (FACT) is a small project intended to make a life
|
4
|
+
# with ClearCase a little bit happier. The project tries to achieve the
|
5
|
+
# goal in two ways:
|
6
|
+
#
|
7
|
+
# 1. Create an intuitive front end for IBM Rational ClearCase SCM.
|
8
|
+
# 2. Create a library that simplifies the process of development of scripts
|
9
|
+
# that interact with ClearCase.
|
10
|
+
#
|
11
|
+
# Execute +fact+ to enter the interactive mode.
|
12
|
+
# +fact+ is expected to be executed from a ClearCase view directory.
|
13
|
+
# All the commands will be handled in respect to this view.
|
14
|
+
#
|
15
|
+
# It is possible to require +fact+ to access ClearCase from Ruby code.
|
16
|
+
# Consult Fact::ClearCase for the list of the supported ClearCase operations.
|
17
|
+
|
18
|
+
require "rubygems"
|
19
|
+
require "fact"
|
20
|
+
|
21
|
+
|
22
|
+
cc = Fact::ClearCase.new
|
23
|
+
|
24
|
+
activity = Fact::Cli.choose_undelivered_activity
|
25
|
+
|
26
|
+
unless activity.nil?
|
27
|
+
# Come back every time to showing the files in the activity
|
28
|
+
loop do
|
29
|
+
file_version = Fact::Cli.choose_file_from_activity(activity)
|
30
|
+
|
31
|
+
say("Fetching the file description... ")
|
32
|
+
version_info = cc.get_version_info(file_version)
|
33
|
+
say("Done")
|
34
|
+
|
35
|
+
puts ""
|
36
|
+
Fact::Cli.show_version_info(version_info)
|
37
|
+
|
38
|
+
puts ""
|
39
|
+
if version_info[:checkout] != "" and version_info[:checkout] != cc.get_current_view
|
40
|
+
say("The file is checked out in a different view. Check it in to diff.")
|
41
|
+
elsif agree("Compare with the change set predecessor?")
|
42
|
+
say("Graphical diff is being opened in an external application.")
|
43
|
+
cc.diff_other_version(file_version[:file], file_version[:version], version_info[:changeset_predecessor])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/fact.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "fact/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "fact"
|
7
|
+
s.version = Fact::VERSION
|
8
|
+
s.authors = ["FireAphis"]
|
9
|
+
s.email = ["FireAphis@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/FireAphis/Fact"
|
11
|
+
s.summary = %q{Interactive ClearCase CLI and ClearCase wrapper API.}
|
12
|
+
s.description = %q{A small project intended to make a life with ClearCase a little bit happier. It supplies an intuitive and interactive ClearCase CLI and ClearCase wrapper API.}
|
13
|
+
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.extra_rdoc_files = ['bin/fact']
|
16
|
+
s.rdoc_options << '--main' << 'bin/fact' << '--include' << 'bin'
|
17
|
+
|
18
|
+
s.requirements << 'ClearCase ClearTool'
|
19
|
+
s.add_dependency('highline', '>= 1.6.0')
|
20
|
+
|
21
|
+
s.rubyforge_project = "fact"
|
22
|
+
|
23
|
+
s.files = `git ls-files`.split("\n")
|
24
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
25
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
26
|
+
s.require_paths = ["lib"]
|
27
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
|
2
|
+
# System libraries
|
3
|
+
require "highline/import"
|
4
|
+
|
5
|
+
# Local libraries
|
6
|
+
require "fact/clearcase"
|
7
|
+
require "fact/files_cli"
|
8
|
+
|
9
|
+
|
10
|
+
module Fact
|
11
|
+
|
12
|
+
class Cli
|
13
|
+
|
14
|
+
# Ask the user to choose from the list of all the undelivered activities
|
15
|
+
# in the current stream.
|
16
|
+
# Returns the name of the chosen activity.
|
17
|
+
#
|
18
|
+
def Cli.choose_undelivered_activity
|
19
|
+
|
20
|
+
cc = ClearCase.new
|
21
|
+
|
22
|
+
stream = cc.get_current_stream
|
23
|
+
return if stream==""
|
24
|
+
|
25
|
+
puts ""
|
26
|
+
say("The current stream is <%= color('#{stream}', BOLD) %>. Fetching the stream activities... ")
|
27
|
+
activities = cc.get_activities
|
28
|
+
say("Done.")
|
29
|
+
|
30
|
+
if activities.empty?
|
31
|
+
say("No undelivered activities.")
|
32
|
+
else
|
33
|
+
say("These are the undelivered activities in the current stream:")
|
34
|
+
|
35
|
+
return choose do |menu|
|
36
|
+
menu.prompt = "Enter the activity number: "
|
37
|
+
menu.select_by = :index
|
38
|
+
|
39
|
+
# Add a menu entry for each activity
|
40
|
+
activities.each do |activity|
|
41
|
+
menu.choice(activity[:headline]) { activity[:name] }
|
42
|
+
end
|
43
|
+
|
44
|
+
# The last entry allows graceful exit
|
45
|
+
menu.choice("Exit") { exit(true) }
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
# Asks to choose from a list of files in the activity and returns the last version of
|
54
|
+
# the file in the activity in a hash with keys :file and :version.
|
55
|
+
#
|
56
|
+
def Cli.choose_file_from_activity(activity_name)
|
57
|
+
|
58
|
+
cc = ClearCase.new
|
59
|
+
|
60
|
+
puts ""
|
61
|
+
say("Fetching the change set for the activity <%= color('#{activity_name}', BOLD) %>... ")
|
62
|
+
changeset = cc.get_activity_change_set(activity_name)
|
63
|
+
say("Done.")
|
64
|
+
|
65
|
+
if changeset.empty?
|
66
|
+
say("The changeset is empty.")
|
67
|
+
else
|
68
|
+
say("The activity contains the following files:")
|
69
|
+
|
70
|
+
# The method will return the choice from the menu
|
71
|
+
return choose do |menu|
|
72
|
+
menu.prompt = "Enter the file number: "
|
73
|
+
menu.select_by = :index
|
74
|
+
|
75
|
+
# Add a menu entry for each file in the changeset
|
76
|
+
changeset.each do |file, versions|
|
77
|
+
# Suffix contains the versions count and the check-out indicator
|
78
|
+
suffix = "version#{"s" unless versions.size<2}) #{"<%= color('CHECKED-OUT!', :red) %>" if cc.checkout_version?(versions.last)}"
|
79
|
+
menu.choice("#{file} (#{versions.size} #{suffix}") { {:file => file, :version => versions.last} }
|
80
|
+
end
|
81
|
+
|
82
|
+
# The last entry allows graceful exit
|
83
|
+
menu.choice("Exit") { exit(true) }
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
|
@@ -0,0 +1,168 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Fact
|
4
|
+
|
5
|
+
class ClearTool
|
6
|
+
def invoke(command_str)
|
7
|
+
return `cleartool #{command_str}`
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class ClearCase
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@cleartool = ClearTool.new
|
15
|
+
end
|
16
|
+
|
17
|
+
# Get the name of the current stream.
|
18
|
+
#
|
19
|
+
def get_current_stream
|
20
|
+
return @cleartool.invoke("lsstream -s").rstrip
|
21
|
+
end
|
22
|
+
|
23
|
+
# Get the name of the current view.
|
24
|
+
#
|
25
|
+
def get_current_view
|
26
|
+
return @cleartool.invoke("lsview -s -cview").rstrip
|
27
|
+
end
|
28
|
+
|
29
|
+
# Get the previous version of the version specified in the arguments.
|
30
|
+
#
|
31
|
+
def get_previous_version(file, version)
|
32
|
+
return @cleartool.invoke("desc -pred -s #{create_cc_version(file,version)}").rstrip
|
33
|
+
end
|
34
|
+
|
35
|
+
# Get all the non-obsolete activities in the current view.
|
36
|
+
# Returns an array of hashes. Each hash represents an activity and contains
|
37
|
+
# two keys: :name and :headline.
|
38
|
+
#
|
39
|
+
def get_activities
|
40
|
+
return parse_lsact_output(@cleartool.invoke('lsact -fmt "%[name]p,%[headline]p,"'))
|
41
|
+
end
|
42
|
+
|
43
|
+
# Get version information. The argument must be a hash with keys :file and :version.
|
44
|
+
# Returns a version info hash.
|
45
|
+
#
|
46
|
+
def get_version_info(file_version)
|
47
|
+
|
48
|
+
# Get the properties of the latest version of the file
|
49
|
+
version_str = create_cc_version(file_version[:file],file_version[:version])
|
50
|
+
format_str = '"version=%Sn, activity=%[activity]p, date=%Sd, type=%m, predecessor=%PVn, user=%Fu, checkout=%Tf"'
|
51
|
+
curr_version_info = parse_describe_file(@cleartool.invoke("desc -fmt #{format_str} #{version_str}"))
|
52
|
+
return if curr_version_info.nil?
|
53
|
+
|
54
|
+
# Retreive all the change set to find the earliest version of the file in the change set
|
55
|
+
change_set = get_activity_change_set(curr_version_info[:activity])
|
56
|
+
return if change_set.nil?
|
57
|
+
|
58
|
+
# Get the file name component of the file version string
|
59
|
+
file = file_version[:file]
|
60
|
+
|
61
|
+
# Get versions array for the file
|
62
|
+
versions = change_set[file]
|
63
|
+
|
64
|
+
# Adding additional information to the existing hash
|
65
|
+
curr_version_info[:name] = file
|
66
|
+
curr_version_info[:changeset_predecessor] = get_previous_version(file, versions.first)
|
67
|
+
curr_version_info[:versions_count] = versions.size
|
68
|
+
|
69
|
+
return curr_version_info
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns the changes that were made as a part of the specified activity.
|
73
|
+
# Returns a hash where the key is a file names and the value is a list of versions of
|
74
|
+
# that file. If there are no files in the activity, returns an empty hash.
|
75
|
+
#
|
76
|
+
def get_activity_change_set(activity_name)
|
77
|
+
|
78
|
+
# Get a string that is space separated list of all the versions in the activity
|
79
|
+
versions_dump = @cleartool.invoke("lsact -fmt \"%[versions]p\" #{activity_name}")
|
80
|
+
|
81
|
+
# Will convert the string into a hash of filenames and lists of version numbers
|
82
|
+
change_set = Hash.new { |hash,key| hash[key]=[] }
|
83
|
+
|
84
|
+
# Convert the string into a sorted array and iterate it
|
85
|
+
versions_dump.split(" ").sort.each do |version_str|
|
86
|
+
version = parse_cc_version(version_str)
|
87
|
+
change_set[version[:file]].push("#{version[:version]}")
|
88
|
+
end
|
89
|
+
|
90
|
+
return change_set
|
91
|
+
end
|
92
|
+
|
93
|
+
# Launches the default diff tool comparing two versions of a file.
|
94
|
+
# The first parameter is the name of an existing file. The second and the third
|
95
|
+
# parameters are strings indicating versions of the same file.
|
96
|
+
# If one of the versions is checkedout then compared with the file as it appares
|
97
|
+
# currently on the disc. Beware that if the file is checked out from a different
|
98
|
+
# view, the diff will compare wrong files.
|
99
|
+
#
|
100
|
+
def diff_other_version(file, version1, version2)
|
101
|
+
ver1 = checkout_version?(version1) ? file : create_cc_version(file,version1)
|
102
|
+
ver2 = checkout_version?(version2) ? file : create_cc_version(file,version2)
|
103
|
+
#diff_process = fork { exec "cleartool diff -gra #{ver1} #{ver2}" }
|
104
|
+
#Process.detach(diff_process)
|
105
|
+
`cleartool diff -gra #{ver1} #{ver2}`
|
106
|
+
end
|
107
|
+
|
108
|
+
# Parses a string representing ClearCase element version and converts it into a hash
|
109
|
+
# with a key for each part of the version string.
|
110
|
+
#
|
111
|
+
# version_str is expected to be of the following form:
|
112
|
+
#
|
113
|
+
# <file full path>@@<branch name>/{<version number>|CHECKEDOUT.<checkout number>}
|
114
|
+
#
|
115
|
+
# Returns a hash with the following keys: :file, :version.
|
116
|
+
#
|
117
|
+
def parse_cc_version(version_str)
|
118
|
+
if version_str =~ /(.*)@@(.+)\/(CHECKEDOUT\.)?(\d+)$/
|
119
|
+
return { :file => $1, :version => "#{$2}/#{$3}#{$4}" }
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# Build a string that is a qualified ClearCase file version.
|
124
|
+
#
|
125
|
+
def create_cc_version(file, version)
|
126
|
+
return "#{file}@@#{version}"
|
127
|
+
end
|
128
|
+
|
129
|
+
# Parse the output of the cleartool describe command. The text is expected to be of a specific
|
130
|
+
# format and not the regular cleartool describe -long.
|
131
|
+
#
|
132
|
+
def parse_describe_file(describe_str)
|
133
|
+
if describe_str =~ /version=(.*), activity=(.*), date=(.*), type=(.*), predecessor=(.*), user=(.*), checkout=(.*)$/
|
134
|
+
return { :version=>$1, :activity=>$2, :date=>$3, :type=>$4, :predecessor=>$5, :user=>$6, :checkout=>$7 }
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# Converts the textual result of the lsact command into an array of activities.
|
139
|
+
# The input string is expected to be of the following format:
|
140
|
+
#
|
141
|
+
# (<activity name>,<activity headline>,)*
|
142
|
+
#
|
143
|
+
# Returns an array of hashes. Each hash has two keys: :name and :headline.
|
144
|
+
#
|
145
|
+
def parse_lsact_output(lsact)
|
146
|
+
|
147
|
+
activities = []
|
148
|
+
|
149
|
+
# Takes the string and convers it to an array of name-headline pairs
|
150
|
+
lsact.scan(/(.*?),(.*?),/).each do |pair|
|
151
|
+
activities += [{ :name => pair[0], :headline => pair[1] }]
|
152
|
+
end
|
153
|
+
|
154
|
+
return activities
|
155
|
+
end
|
156
|
+
|
157
|
+
def checkout_version?(version)
|
158
|
+
return version =~ /CHECKEDOUT/
|
159
|
+
end
|
160
|
+
|
161
|
+
def cleartool=(new_ct)
|
162
|
+
@cleartool = new_ct
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
|
2
|
+
# System libraries
|
3
|
+
require "highline/import"
|
4
|
+
|
5
|
+
# Local libraries
|
6
|
+
require "fact/clearcase"
|
7
|
+
|
8
|
+
|
9
|
+
module Fact
|
10
|
+
|
11
|
+
class Cli
|
12
|
+
|
13
|
+
# Format and print to stdout the specified information.
|
14
|
+
# The parameter must be a hash with the following keys:
|
15
|
+
#
|
16
|
+
# :version, :name, :activity, :date, :user,
|
17
|
+
# :versions_count, :changeset_predecessor
|
18
|
+
#
|
19
|
+
def Cli.show_version_info(info)
|
20
|
+
|
21
|
+
cc = ClearCase.new
|
22
|
+
|
23
|
+
if cc.checkout_version?(info[:version])
|
24
|
+
last_ver_text = "<%= color('CHECKED-OUT!', :red) %> in #{info[:checkout]}"
|
25
|
+
else
|
26
|
+
last_ver_text = "#{info[:version]}"
|
27
|
+
end
|
28
|
+
|
29
|
+
# Spliting the path and the name so the name can be shown in bold
|
30
|
+
path = info[:name].scan(/.*\//)[0]
|
31
|
+
file_name = info[:name].scan(/\/[^\/]+$/)[0]
|
32
|
+
file_name.slice!(0) # Removing the leading slash
|
33
|
+
|
34
|
+
say("#{path}<%= color('#{file_name}', BOLD) %>")
|
35
|
+
say(" Last activity:")
|
36
|
+
say(" Activity name: #{info[:activity]}")
|
37
|
+
say(" Last version: #{last_ver_text}")
|
38
|
+
say(" created on #{info[:date]} by #{info[:user]}")
|
39
|
+
say(" #{info[:versions_count]-1} more version#{"s" unless info[:versions_count]==2} in the activity")
|
40
|
+
say(" Activity predecessor: #{info[:changeset_predecessor]}")
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
data/lib/fact/version.rb
ADDED
data/lib/fact.rb
ADDED
data/test/tests.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "test/unit"
|
5
|
+
require "fact"
|
6
|
+
|
7
|
+
class MockClearTool
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@invocations = []
|
11
|
+
@succeeded = true
|
12
|
+
end
|
13
|
+
|
14
|
+
def succeeded
|
15
|
+
@succeeded
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_invocation(command, result)
|
19
|
+
@invocations.push( { :command => command,
|
20
|
+
:result => result } )
|
21
|
+
end
|
22
|
+
|
23
|
+
def invoke(command)
|
24
|
+
next_invocation = @invocations.shift
|
25
|
+
err_msg = "Wrong invocation: expected '#{next_invocation[:command]}', actual '#{command}'"
|
26
|
+
if command != next_invocation[:command]
|
27
|
+
@succeeded = false
|
28
|
+
throw(:wrongInvocation, err_msg)
|
29
|
+
else
|
30
|
+
return next_invocation[:result]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
class ClearCaseWrapperTests < Test::Unit::TestCase
|
37
|
+
|
38
|
+
def test_parse_cc_version
|
39
|
+
cc = Fact::ClearCase.new
|
40
|
+
result = cc.parse_cc_version("/home/FireAphis/views/fireaphis_fact_1.0/vobs/fact/test/test.cpp@@/main/fact_1.0_Integ/fireaphis_fact_1.0/12");
|
41
|
+
assert_not_nil(result)
|
42
|
+
assert_equal("/home/FireAphis/views/fireaphis_fact_1.0/vobs/fact/test/test.cpp", result[:file])
|
43
|
+
assert_equal("/main/fact_1.0_Integ/fireaphis_fact_1.0/12", result[:version])
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def test_parse_lsact_output
|
48
|
+
cc = Fact::ClearCase.new
|
49
|
+
|
50
|
+
result = cc.parse_lsact_output("name_1,headline 1,")
|
51
|
+
expected = [ { :name => "name_1", :headline => "headline 1" } ]
|
52
|
+
assert_equal(expected, result)
|
53
|
+
|
54
|
+
result = cc.parse_lsact_output("name_1,headline 1,name_1,headline 1,name_1,headline 1,")
|
55
|
+
expected = [ { :name => "name_1", :headline => "headline 1" },
|
56
|
+
{ :name => "name_1", :headline => "headline 1" },
|
57
|
+
{ :name => "name_1", :headline => "headline 1" } ]
|
58
|
+
assert_equal(expected, result)
|
59
|
+
|
60
|
+
result = cc.parse_lsact_output("name_1,headline 1,name_2,headline 2,name_3,headline 3,")
|
61
|
+
expected = [ { :name => "name_1", :headline => "headline 1" },
|
62
|
+
{ :name => "name_2", :headline => "headline 2" },
|
63
|
+
{ :name => "name_3", :headline => "headline 3" } ]
|
64
|
+
assert_equal(expected, result)
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def test_parse_describe_file
|
69
|
+
cc = Fact::ClearCase.new
|
70
|
+
|
71
|
+
result = cc.parse_describe_file("version=/main/fact_1.0_Integ/fireaphis_fact_1.0/8, activity=test_fact, date=2011-05-08, type=version, predecessor=/main/fact_1.0_Integ/fireaphis_fact_1.0/7, user=FireAphis, checkout=fireaphis_fact_1.0")
|
72
|
+
expected = { :version => "/main/fact_1.0_Integ/fireaphis_fact_1.0/8",
|
73
|
+
:activity => "test_fact",
|
74
|
+
:date => "2011-05-08",
|
75
|
+
:type => "version",
|
76
|
+
:predecessor => "/main/fact_1.0_Integ/fireaphis_fact_1.0/7",
|
77
|
+
:user => "FireAphis",
|
78
|
+
:checkout => "fireaphis_fact_1.0"}
|
79
|
+
assert_equal(expected, result)
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
def test_get_activity_change_set
|
84
|
+
# Define the expected calls
|
85
|
+
ct = MockClearTool.new
|
86
|
+
ct.add_invocation('lsact -fmt "%[versions]p" test_fact', '/home/fa/c@@/main/stream/100 ' +
|
87
|
+
'/home/fa/a@@/main/stream/CHECKEDOUT.1234 ' +
|
88
|
+
'/home/fa/b@@/main/stream/100 ' +
|
89
|
+
'/home/fa/c@@/main/stream/102 ' +
|
90
|
+
'/home/fa/c@@/main/stream/101 ' +
|
91
|
+
'/home/fa/a@@/main/stream/200' )
|
92
|
+
cc = Fact::ClearCase.new
|
93
|
+
cc.cleartool = ct
|
94
|
+
|
95
|
+
change_set = {}
|
96
|
+
err = catch(:wrongInvocation) { change_set = cc.get_activity_change_set("test_fact") }
|
97
|
+
assert(ct.succeeded, err)
|
98
|
+
|
99
|
+
expected = {"/home/fa/a"=>["/main/stream/200", "/main/stream/CHECKEDOUT.1234"],
|
100
|
+
"/home/fa/b"=>["/main/stream/100"],
|
101
|
+
"/home/fa/c"=>["/main/stream/100", "/main/stream/101", "/main/stream/102"]}
|
102
|
+
assert_equal(expected, change_set)
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fact
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1.a
|
5
|
+
prerelease: 6
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- FireAphis
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-05-31 00:00:00.000000000 +03:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: highline
|
17
|
+
requirement: &83707590 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.6.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *83707590
|
26
|
+
description: A small project intended to make a life with ClearCase a little bit happier.
|
27
|
+
It supplies an intuitive and interactive ClearCase CLI and ClearCase wrapper API.
|
28
|
+
email:
|
29
|
+
- FireAphis@gmail.com
|
30
|
+
executables:
|
31
|
+
- fact
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files:
|
34
|
+
- bin/fact
|
35
|
+
files:
|
36
|
+
- .gitignore
|
37
|
+
- Gemfile
|
38
|
+
- LICENSE
|
39
|
+
- README.md
|
40
|
+
- Rakefile
|
41
|
+
- bin/fact
|
42
|
+
- fact.gemspec
|
43
|
+
- lib/fact.rb
|
44
|
+
- lib/fact/activities_cli.rb
|
45
|
+
- lib/fact/clearcase.rb
|
46
|
+
- lib/fact/files_cli.rb
|
47
|
+
- lib/fact/version.rb
|
48
|
+
- test/tests.rb
|
49
|
+
has_rdoc: true
|
50
|
+
homepage: https://github.com/FireAphis/Fact
|
51
|
+
licenses: []
|
52
|
+
post_install_message:
|
53
|
+
rdoc_options:
|
54
|
+
- --main
|
55
|
+
- bin/fact
|
56
|
+
- --include
|
57
|
+
- bin
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ! '>'
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: 1.3.1
|
72
|
+
requirements:
|
73
|
+
- ClearCase ClearTool
|
74
|
+
rubyforge_project: fact
|
75
|
+
rubygems_version: 1.6.2
|
76
|
+
signing_key:
|
77
|
+
specification_version: 3
|
78
|
+
summary: Interactive ClearCase CLI and ClearCase wrapper API.
|
79
|
+
test_files:
|
80
|
+
- test/tests.rb
|