fact 0.1.1.a
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/.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
|