rant 0.3.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/COPYING +504 -0
- data/README +203 -0
- data/Rantfile +104 -0
- data/TODO +19 -0
- data/bin/rant +12 -0
- data/bin/rant-import +12 -0
- data/devel-notes +50 -0
- data/doc/configure.rdoc +40 -0
- data/doc/csharp.rdoc +74 -0
- data/doc/rant-import.rdoc +32 -0
- data/doc/rant.rdoc +24 -0
- data/doc/rantfile.rdoc +227 -0
- data/doc/rubyproject.rdoc +210 -0
- data/lib/rant.rb +9 -0
- data/lib/rant/cs_compiler.rb +334 -0
- data/lib/rant/import.rb +291 -0
- data/lib/rant/import/rubydoc.rb +125 -0
- data/lib/rant/import/rubypackage.rb +417 -0
- data/lib/rant/import/rubytest.rb +97 -0
- data/lib/rant/plugin/README +50 -0
- data/lib/rant/plugin/configure.rb +345 -0
- data/lib/rant/plugin/csharp.rb +275 -0
- data/lib/rant/plugin_methods.rb +41 -0
- data/lib/rant/rantenv.rb +217 -0
- data/lib/rant/rantfile.rb +664 -0
- data/lib/rant/rantlib.rb +1118 -0
- data/lib/rant/rantsys.rb +258 -0
- data/lib/rant/rantvar.rb +82 -0
- data/rantmethods.rb +79 -0
- data/run_import +7 -0
- data/run_rant +7 -0
- data/setup.rb +1360 -0
- data/test/Rantfile +2 -0
- data/test/plugin/configure/Rantfile +47 -0
- data/test/plugin/configure/test_configure.rb +58 -0
- data/test/plugin/csharp/Hello.cs +10 -0
- data/test/plugin/csharp/Rantfile +30 -0
- data/test/plugin/csharp/src/A.cs +8 -0
- data/test/plugin/csharp/src/B.cs +8 -0
- data/test/plugin/csharp/test_csharp.rb +99 -0
- data/test/project1/Rantfile +127 -0
- data/test/project1/test_project.rb +203 -0
- data/test/project2/buildfile +14 -0
- data/test/project2/rantfile.rb +20 -0
- data/test/project2/sub1/Rantfile +12 -0
- data/test/project2/test_project.rb +87 -0
- data/test/project_rb1/README +14 -0
- data/test/project_rb1/bin/wgrep +5 -0
- data/test/project_rb1/lib/wgrep.rb +56 -0
- data/test/project_rb1/rantfile.rb +30 -0
- data/test/project_rb1/test/tc_wgrep.rb +21 -0
- data/test/project_rb1/test/text +3 -0
- data/test/project_rb1/test_project_rb1.rb +153 -0
- data/test/test_env.rb +47 -0
- data/test/test_filetask.rb +57 -0
- data/test/test_lighttask.rb +49 -0
- data/test/test_metatask.rb +29 -0
- data/test/test_rant_interface.rb +65 -0
- data/test/test_sys.rb +61 -0
- data/test/test_task.rb +115 -0
- data/test/toplevel.rf +11 -0
- data/test/ts_all.rb +4 -0
- data/test/tutil.rb +95 -0
- metadata +133 -0
data/README
ADDED
@@ -0,0 +1,203 @@
|
|
1
|
+
|
2
|
+
= Rant -- Ruby's ant
|
3
|
+
|
4
|
+
Rant is a flexible build tool written entirely in Ruby.
|
5
|
+
|
6
|
+
The equivalent to a _Makefile_ for _make_ is the _Rantfile_. An
|
7
|
+
_Rantfile_ is actually a valid Ruby script that is read in by the
|
8
|
+
_rant_ command.
|
9
|
+
|
10
|
+
Rant currently features:
|
11
|
+
* Rantfiles are written in Ruby.
|
12
|
+
* Defining custom tasks
|
13
|
+
* Automated packaging, testing and RDoc generation for Ruby
|
14
|
+
applications and libraries.
|
15
|
+
* Primitive support for compiling C# sources portably with csc, cscc
|
16
|
+
and mcs.
|
17
|
+
* A _configure_ plugin for easy environment and build-parameter
|
18
|
+
checking (but not like autoconf!) which saves data in a yaml file.
|
19
|
+
* The <em>rant-import</em> command creates a monolithic rant script,
|
20
|
+
so you don't depend on an rant installation anymore.
|
21
|
+
|
22
|
+
As programmers usually want to see code, here is a short and very
|
23
|
+
basic example of rant usage:
|
24
|
+
|
25
|
+
A file called +Rantfile+ contains the code:
|
26
|
+
|
27
|
+
file "backup/data" => "data" do |t|
|
28
|
+
sys.cp "data", t.name
|
29
|
+
end
|
30
|
+
|
31
|
+
Running rant in the directory of this file:
|
32
|
+
|
33
|
+
% rant
|
34
|
+
cp data backup/data
|
35
|
+
|
36
|
+
will ensure that the "data" file in the "backup" directory is up to
|
37
|
+
date.
|
38
|
+
|
39
|
+
== Support
|
40
|
+
|
41
|
+
The newest version of this document can be found at
|
42
|
+
http://make.rubyforge.org.
|
43
|
+
|
44
|
+
For further information, feature requests, bugreports or comments
|
45
|
+
visit the
|
46
|
+
{RubyForge site for Rant}[http://rubyforge.org/projects/make/].
|
47
|
+
|
48
|
+
Also feel free to contact the author directly by sending an email to
|
49
|
+
mailto:langstefan@gmx.at.
|
50
|
+
|
51
|
+
== Roadmap
|
52
|
+
|
53
|
+
Installing Rant::
|
54
|
+
read the section _Installation_ in this document
|
55
|
+
License::
|
56
|
+
read the section _Copying_ in this document
|
57
|
+
Invoking *rant*::
|
58
|
+
read doc/rant.rdoc[link:files/doc/rant_rdoc.html]
|
59
|
+
Writing an *Rantfile*::
|
60
|
+
read doc/rantfile.rdoc[link:files/doc/rantfile_rdoc.html]
|
61
|
+
Automation for your Ruby library/application::
|
62
|
+
read doc/rubyproject.rdoc[link:files/doc/rubyproject_rdoc.html]
|
63
|
+
Independent from Rant? The <tt>rant-import</tt> command::
|
64
|
+
read doc/rant-import.rdoc[link:files/doc/rant-import_rdoc.html]
|
65
|
+
Using the Configure plugin::
|
66
|
+
read doc/configure.rdoc[link:files/doc/configure_rdoc.html]
|
67
|
+
Compiling C#::
|
68
|
+
read doc/csharp.rdoc[link:files/doc/csharp_rdoc.html]
|
69
|
+
|
70
|
+
== Installation
|
71
|
+
|
72
|
+
Of course you need Ruby to run rant. You can get the latest Ruby
|
73
|
+
package from the {Ruby hompage}[http://www.ruby-lang.org/en/].
|
74
|
+
|
75
|
+
There are two ways to install Rant on your system:
|
76
|
+
|
77
|
+
=== Installing Rant as a RubyGem
|
78
|
+
|
79
|
+
RubyGems has to be installed on your system. Check this by trying
|
80
|
+
the _gem_ command:
|
81
|
+
% gem
|
82
|
+
If this prints a help message, RubyGems should work. Otherwise
|
83
|
+
install Rant as described in the next section.
|
84
|
+
Now the following command:
|
85
|
+
% gem install --remote rant
|
86
|
+
will download and install Rant. Depending on the RubyGems
|
87
|
+
configuration, you will probably need superuser privileges.
|
88
|
+
Then try to run:
|
89
|
+
% rant --version
|
90
|
+
which should print name and version of the _rant_ command. If this
|
91
|
+
is done, you have successfully installed Rant. Congratulations!
|
92
|
+
|
93
|
+
=== Conventional installation
|
94
|
+
|
95
|
+
First download the latest version of Rant from
|
96
|
+
http://rubyforge.org/frs/?group_id=615. Choose the .zip or .tar.gz
|
97
|
+
file, whatever you like, with the highest version number. Then unpack
|
98
|
+
the archive, cd to the new directory and run the setup.rb script. This
|
99
|
+
could look like:
|
100
|
+
% tar -xzf rant-<version>.tar.gz
|
101
|
+
% cd rant-<version>
|
102
|
+
% ruby setup.rb
|
103
|
+
Depending on your Ruby installation, you'll probably need superuser
|
104
|
+
privileges for the last command. If you wan't to install Rant in
|
105
|
+
another location than the default, run
|
106
|
+
% ruby setup.rb --help
|
107
|
+
which will show you a bunch of options for the installation.
|
108
|
+
|
109
|
+
After performing the steps listed above, try to run
|
110
|
+
% rant --version
|
111
|
+
to verify Rant was installed correctly.
|
112
|
+
|
113
|
+
If you aren't already reading this documentation in html format, you
|
114
|
+
can generate it with:
|
115
|
+
% rant doc
|
116
|
+
The output will be in doc/html.
|
117
|
+
|
118
|
+
== Copying
|
119
|
+
|
120
|
+
Copyright (C) 2005 Stefan Lang
|
121
|
+
|
122
|
+
This library is free software; you can redistribute it and/or
|
123
|
+
modify it under the terms of the GNU Lesser General Public
|
124
|
+
License as published by the Free Software Foundation; either
|
125
|
+
version 2.1 of the License, or (at your option) any later version.
|
126
|
+
|
127
|
+
This library is distributed in the hope that it will be useful,
|
128
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
129
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
130
|
+
Lesser General Public License for more details.
|
131
|
+
|
132
|
+
You should have received a copy of the GNU Lesser General Public
|
133
|
+
License along with this library; if not, write to the Free Software
|
134
|
+
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
135
|
+
|
136
|
+
---
|
137
|
+
|
138
|
+
The file COPYING[link:../../COPYING] in the Rant package contains a
|
139
|
+
copy of the LGPL. Of course your Rantfiles don't need to be licenced
|
140
|
+
under the terms of the LGPL.
|
141
|
+
|
142
|
+
== Other info
|
143
|
+
|
144
|
+
Rant was started in February 2005. It has been written and is
|
145
|
+
maintained by Stefan Lang (mailto:langstefan@gmx.at).
|
146
|
+
|
147
|
+
=== Why did you write another build tool?
|
148
|
+
|
149
|
+
Because I wasn't satisfied by any other build tool. Before I started
|
150
|
+
Rant, I had to write a program in C#. The program had to run under
|
151
|
+
Windows, but I wanted to develop under Linux. Also I decided to write
|
152
|
+
the documentation in Docbook.
|
153
|
+
|
154
|
+
So there where quite a few problems arising:
|
155
|
+
* I had to compile with cscc on Linux.
|
156
|
+
* compile with csc on Windows.
|
157
|
+
* automate PDF and HTML generation from Docbook
|
158
|
+
|
159
|
+
_Nant_ would have been ok to compile the C# sources. But it isn't
|
160
|
+
suited for more general tasks as clueing togheter other programs
|
161
|
+
(needed for Docbook processing).
|
162
|
+
|
163
|
+
Then I tried to use _Rake_ and it was the other way round. I liked the
|
164
|
+
basic concept and syntax of Rake and of course I could have written
|
165
|
+
code for Rake (e.g. with a so called _Tasklib_) to support portable C#
|
166
|
+
compilation. But it was a bit quirky and because I like to work with
|
167
|
+
Ruby, I decided to write my own build tool.
|
168
|
+
|
169
|
+
Rant has taken the basic syntax of a _task_ and some other concepts
|
170
|
+
from Rake.
|
171
|
+
So thanks to Jim Weirich, the author of
|
172
|
+
Rake[http://rubyforge.org/projects/rake].
|
173
|
+
|
174
|
+
=== Goals of Rant
|
175
|
+
|
176
|
+
* Most important is to be a very *flexible* build tool. This currently
|
177
|
+
means that you can run/use Rant in many different ways. E.g. you can
|
178
|
+
invoke it the conventional way like _make_, define tasks and run
|
179
|
+
Rant from _irb_ (the interactive Ruby shell), create an independent
|
180
|
+
script with <em>rant-import</em>, or simply use Rant as a library to
|
181
|
+
automate tasks for your application.
|
182
|
+
* *Extensible*: currently through _plugins_ and _generators_. (Think
|
183
|
+
of the +plugin+ and +import+ functions.)
|
184
|
+
* Portability: see _Platforms_ below for details
|
185
|
+
* Well scaling: Rant should work acceptable for bigger projects (from
|
186
|
+
a performance POV and for the writer of the Rantfiles).
|
187
|
+
|
188
|
+
=== Platforms
|
189
|
+
|
190
|
+
Rant was tested on:
|
191
|
+
|
192
|
+
System Ruby version
|
193
|
+
=======================================================
|
194
|
+
Linux 1.8.2
|
195
|
+
1.9
|
196
|
+
MacOS X 1.8.2
|
197
|
+
WindowsXP 1.8.2 (OneClick Installer)
|
198
|
+
|
199
|
+
It *should* run on most platforms where Ruby runs, but you never
|
200
|
+
know...
|
201
|
+
|
202
|
+
If you encounter problems with Rant on any platform (with Ruby 1.8.1
|
203
|
+
or higher) please write a bugreport!
|
data/Rantfile
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Rantfile for Rant :)
|
4
|
+
|
5
|
+
require 'rant'
|
6
|
+
|
7
|
+
import %w(rubytest rubydoc rubypackage)
|
8
|
+
|
9
|
+
task :default => :test
|
10
|
+
|
11
|
+
lib_files = FileList["lib/**/*.rb"]
|
12
|
+
dist_files = FileList["{bin,lib,test,doc}/**/*"].no_dir("html") +
|
13
|
+
FileList["*"].no_dir.no_file("InstalledFiles").no_file("Session.vim")
|
14
|
+
|
15
|
+
gen RubyPackage, "rant" do |t|
|
16
|
+
t.version = `#{Env::RUBY} run_rant --version`.split[1]
|
17
|
+
t.summary = "Rant is a Ruby based build tool."
|
18
|
+
t.files = dist_files
|
19
|
+
t.bindir = "bin"
|
20
|
+
t.executable %w(rant rant-import)
|
21
|
+
t.author = "Stefan Lang"
|
22
|
+
t.email = "langstefan@gmx.at"
|
23
|
+
t.gem_rubyforge_project = "make"
|
24
|
+
t.gem_extra_rdoc_files = FileList["**/README"].no_dir("pkg").no_dir("test") + FileList["doc/**/*.rdoc"]
|
25
|
+
t.homepage = "http://make.rubyforge.org"
|
26
|
+
desc "Create packages for distribution."
|
27
|
+
t.package_task
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "Generate documentation."
|
31
|
+
gen RubyDoc do |g|
|
32
|
+
g.dir = "doc/html"
|
33
|
+
g.files.concat FileList["**/README"].no_dir("pkg").no_dir("test")
|
34
|
+
g.files.concat FileList["doc/**/*.rdoc"]
|
35
|
+
g.opts = %w(-S -c UTF-8 --title Rant --main README)
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "Run basic tests."
|
39
|
+
gen RubyTest do |g|
|
40
|
+
g.libs << "test"
|
41
|
+
g.pattern = 'test_*.rb'
|
42
|
+
end
|
43
|
+
|
44
|
+
desc "Run first test-project.",
|
45
|
+
"Warning: writes to disc."
|
46
|
+
gen RubyTest, :testp1 do |g|
|
47
|
+
g.libs << "test"
|
48
|
+
g.test_files = ["test/project1/test_project.rb"]
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "Run second test project.",
|
52
|
+
"Warning: writes to disc"
|
53
|
+
gen RubyTest, :testp2 do |g|
|
54
|
+
g.libs << "test"
|
55
|
+
g.test_files = ["test/project2/test_project.rb"]
|
56
|
+
end
|
57
|
+
|
58
|
+
desc "Test small Ruby project."
|
59
|
+
gen RubyTest, :testrb1 do |g|
|
60
|
+
g.libs << "test"
|
61
|
+
g.test_files = %w(test/project_rb1/test_project_rb1.rb)
|
62
|
+
end
|
63
|
+
|
64
|
+
desc "Test plugins."
|
65
|
+
gen RubyTest, :testplugins do |g|
|
66
|
+
g.libs << "test"
|
67
|
+
g.test_files = FileList["test/plugin/**/test_*"]
|
68
|
+
end
|
69
|
+
|
70
|
+
desc "Run all tests and generate coverage with rcov."
|
71
|
+
task :cov do
|
72
|
+
lp = File.expand_path "lib"
|
73
|
+
sys.cd "test" do
|
74
|
+
sys %W(rcov -xts_*,tc_*,test_* -I#{lp} ts_all.rb)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
desc "Run all tests."
|
79
|
+
gen RubyTest, :tall do |g|
|
80
|
+
g.libs << "test"
|
81
|
+
g.test_files = FileList["test/**/test_*.rb"]
|
82
|
+
end
|
83
|
+
task :testall => %w(test testp1 testp2 testrb1 testplugins)
|
84
|
+
|
85
|
+
desc "Remove autogenerated files."
|
86
|
+
task :clean do
|
87
|
+
sys.rm_f %w(InstalledFiles .config bench-rant bench-depsearch)
|
88
|
+
sys.rm_rf %w(doc/html pkg test/coverage)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Just for quick visual testing of rant...
|
92
|
+
task :please_fail do |t|
|
93
|
+
sys "mix_nix_gibts"
|
94
|
+
end
|
95
|
+
|
96
|
+
# for quich rant testing
|
97
|
+
#plugin :Configure
|
98
|
+
|
99
|
+
# mainly for rant testing
|
100
|
+
source 'rantmethods.rb'
|
101
|
+
|
102
|
+
if $0 == __FILE__
|
103
|
+
Rant.run
|
104
|
+
end
|
data/TODO
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
= TODO
|
3
|
+
|
4
|
+
== C# plugin
|
5
|
+
Define the method +assembly+ for building a file with the C# compiler?
|
6
|
+
Done.
|
7
|
+
|
8
|
+
== Predefined tasks
|
9
|
+
|
10
|
+
Add a 'distclean' task that removes all files and directories
|
11
|
+
generatet by any file task.
|
12
|
+
|
13
|
+
RDoc task.
|
14
|
+
|
15
|
+
Gem task (+ one that interactively creates a gemspec).
|
16
|
+
|
17
|
+
== Java plugin
|
18
|
+
|
19
|
+
At least for the 1.0.0 release.
|
data/bin/rant
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#! /usr/local/bin/ruby
|
2
|
+
|
3
|
+
# rant -- Ruby's ant
|
4
|
+
#
|
5
|
+
# Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
|
6
|
+
#
|
7
|
+
# This program is free software.
|
8
|
+
# You can distribute/modify this program under the terms of
|
9
|
+
# the GNU LGPL, Lesser General Public License version 2.1.
|
10
|
+
|
11
|
+
require 'rant/rantlib'
|
12
|
+
exit Rant.run
|
data/bin/rant-import
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#! /usr/local/bin/ruby
|
2
|
+
|
3
|
+
# rant-import -- Create a monolithic rant script.
|
4
|
+
#
|
5
|
+
# Copyright (C) 2005 Stefan Lang <langstefan@gmx.at>
|
6
|
+
#
|
7
|
+
# This program is free software.
|
8
|
+
# You can distribute/modify this program under the terms of
|
9
|
+
# the GNU LGPL, Lesser General Public License version 2.1.
|
10
|
+
|
11
|
+
require 'rant/import'
|
12
|
+
exit Rant::RantImport.run
|
data/devel-notes
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
|
2
|
+
== Here docs
|
3
|
+
Don't use here documents in the Rant sources, imports and plugins.
|
4
|
+
They'll get messed up by the rant-import command.
|
5
|
+
|
6
|
+
== Running RDoc programmatically
|
7
|
+
require 'rdoc/rdoc'
|
8
|
+
rdoc = RDoc::RDoc.new
|
9
|
+
begin
|
10
|
+
rdoc.document(%w(like args from commandline))
|
11
|
+
rescue RDoc::RDocError
|
12
|
+
$stderr.puts "Error when running rdoc: " + $!.message
|
13
|
+
end
|
14
|
+
|
15
|
+
== Changing the behaviour of Rant from Rantfiles
|
16
|
+
Perhaps a method named like `behave' would be appropriate to to
|
17
|
+
set options of the Rant application.
|
18
|
+
|
19
|
+
== Subdirectories
|
20
|
+
Allow the use of `#' at the start of a pathname to tell rant that
|
21
|
+
it should be interpreted relative to the project's root directory.
|
22
|
+
|
23
|
+
== Directory structure of +lib/+
|
24
|
+
+lib/+ contains only two entries:
|
25
|
+
[rant.rb] Used to require rantlib and include +Rant+ for small
|
26
|
+
build scripts.
|
27
|
+
[rant/] All files matching <tt>/^rant\w+\.rb$/</tt> are considered
|
28
|
+
as Rant core. Others contain utilities, helper classes,
|
29
|
+
Generators and similar.
|
30
|
+
[rant/plugin] Each file ending in <tt>.rb</tt> in this directory is
|
31
|
+
considered to load support for one Rant plugin.
|
32
|
+
|
33
|
+
== Performance
|
34
|
+
With version 0.2.6, the big performance problem with task lookup
|
35
|
+
(caused very slow dependency resolving) is fixed.
|
36
|
+
The next performance improvement should target Rantfile reading,
|
37
|
+
especially task creation.
|
38
|
+
|
39
|
+
== RubyPackage generator
|
40
|
+
Currently, the package task(s) generated by RubyPackage doesn't
|
41
|
+
recognize (and repackage) when files/directories are removed (from the
|
42
|
+
sources).
|
43
|
+
|
44
|
+
== Unit tests
|
45
|
+
The unit tests contain many assertions of the form
|
46
|
+
assert_equal(Rant.run(...), 0)
|
47
|
+
which are wrong, because the first argument should be the expected
|
48
|
+
result!
|
49
|
+
|
50
|
+
# vim:tw=70:
|
data/doc/configure.rdoc
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
== The Configure plugin
|
3
|
+
|
4
|
+
The Configure plugin lets you define a list of checks and generates
|
5
|
+
tasks to run them. I'll show an Rantfile using the Configure plugin
|
6
|
+
and explain it afterwards.
|
7
|
+
|
8
|
+
conf = plugin :Configure do |conf|
|
9
|
+
conf.task # define a task named :configure
|
10
|
+
conf.check "a" do |c|
|
11
|
+
c.default "value_a"
|
12
|
+
c.guess { "value_a_guess" }
|
13
|
+
c.react { |val|
|
14
|
+
p val
|
15
|
+
}
|
16
|
+
end
|
17
|
+
conf.check "b" do |c|
|
18
|
+
c.default "value_b"
|
19
|
+
end
|
20
|
+
conf.check "c" do |c|
|
21
|
+
end
|
22
|
+
conf.check "d" do |c|
|
23
|
+
c.react {
|
24
|
+
}
|
25
|
+
end
|
26
|
+
conf.check "e" do |c|
|
27
|
+
c.guess { false }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
file conf["a"] do |t|
|
32
|
+
sys.touch t.name
|
33
|
+
end
|
34
|
+
|
35
|
+
== See also
|
36
|
+
|
37
|
+
Rant Overview::
|
38
|
+
README[link:files/README.html]
|
39
|
+
Writing an Rantfile::
|
40
|
+
doc/rantfile.rdoc[link:files/doc/rantfile_rdoc.html]
|