merged my code in trunk, tried to do it with history conservation for xslt and

skin/ but I am not sure Subversion agrees with me

svn path=/trunk/; revision=62
This commit is contained in:
Frederic Peters 2007-07-31 09:02:39 +00:00
parent 233877bc39
commit 74647a8669
95 changed files with 2721 additions and 11589 deletions

2
AUTHORS Normal file
View File

@ -0,0 +1,2 @@
Frederic Peters <fpeters@0d.be>

340
COPYING Normal file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

0
ChangeLog Normal file
View File

9
INSTALL Normal file
View File

@ -0,0 +1,9 @@
The simplest way to use this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system.
2. Type `make' to create translation catalog.
3. Type `python src/lgo.py' to generate the web site.

View File

@ -1,23 +0,0 @@
DIST = ../libgo/libgo \
../libgo/*.py \
../libgo/decorators \
../libgo/doc \
../libgo/drivers \
../libgo/locators \
../libgo/Makefile \
../libgo/stats \
../libgo/findmissing
VERSION = `egrep -o '([0-9]+\.[0-9]+\.[0-9]+)' libgo`
all:
dist: clean
tar -czf libgo-$(VERSION).tar.gz $(DIST)
upload: dist
scp libgo-$(VERSION).tar.gz blog.goranrakic.com:~/www.goranrakic.com/tmp/
clean:
rm -f *.pyc */*.pyc *~ */*~ */*/*~

2
Makefile.am Normal file
View File

@ -0,0 +1,2 @@
SUBDIRS = po data

0
NEWS Normal file
View File

89
README Normal file
View File

@ -0,0 +1,89 @@
==========================================
libgo -- script to build library.gnome.org
==========================================
Installation
============
libgo is made to run from its checkout directory, there is no need for
installation.
configure and make are used to build translations.
Usage
=====
usage: lgo.py [options]
options:
-h, --help show this help message and exit
-c CONFIG, --config=CONFIG
-v, --verbose verbosity level (more -v for more verbose)
--rebuild-all rebuild all documents (even those that were already
built)
Example: python src/lgo.py -c sample.lgorc -v -v -v
Note about verbosity: xsltproc output is not redirected to /dev/null and will
amount for most of the output.
Configuration File
==================
lgo will look at ~/.lgorc, it can be overridden with -c.
sample.lgorc is a sample configuration file, src/defaults.lgorc lists all
variables and their default settings.
Notable configuration variables are:
- ftp_gnome_org_local_copy: path to local copy of ftp.gnome.org, this is
used not to download all the files that are already local.
- download_cache_dir: path to download cache directory (default:
~/.lgo/cache/)
- output_dir: path to web output (default: /var/www/library.gnome.org/)
- version_min, version_max: minimum/maximum GNOME version to have
documentation for (absolute minimum is 2.12.0).
Note about versions:
- libgo will only build the latest version of a serie,
- libgo will only build the latest version of the latest development
serie.
- modules: list of modules to use (default: None, meaning all modules);
this can be used to restrict modules to a specific subset, example:
['eog', 'gedit']
System Requirements
===================
To build everything from 2.12 to current 2.19 development version :
- disk usage:
- download cache (everything from ftp.gnome.org): 829M
- extracted files: 679M
- web site: 624M
- time:
- building and scanning all documentation: 2h40
- scanning (already built) documentation: 0h40
Mode of operation
=================
- Using http://ftp.gnome.org/pub/GNOME/teams/releng/ to download GNOME jhbuild
modulesets for requested versions
- Iterating on versions
- Downloading tarballs
- Looking for gtk-doc or gnome-doc-utils usage in tarball
- Building them
- Creating indexes

26
autogen.sh Executable file
View File

@ -0,0 +1,26 @@
#! /bin/sh
# Run this to generate all the initial makefiles, etc.
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
PKG_NAME=libgo
(test -f $srcdir/src/lgo.py) || {
echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
echo " top-level $PKG_NAME directory"
exit 1
}
which gnome-autogen.sh || {
echo "You need to install gnome-common from the GNOME CVS"
exit 1
}
REQUIRED_AUTOCONF_VERSION=2.57
REQUIRED_AUTOMAKE_VERSION=1.8
REQUIRED_INTLTOOL_VERSION=0.35.0
REQUIRED_PKG_CONFIG_VERSION=0.16.0
USE_GNOME2_MACROS=1 USE_COMMON_DOC_BUILD=yes . gnome-autogen.sh

19
configure.ac Normal file
View File

@ -0,0 +1,19 @@
AC_INIT(libgo, 0.1, fpeters@0d.be)
AC_CONFIG_SRCDIR(src/lgo.py)
AM_INIT_AUTOMAKE
GNOME_COMMON_INIT
AM_MAINTAINER_MODE
GETTEXT_PACKAGE="libgo"
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [The gettext package])
AM_GLIB_GNU_GETTEXT
IT_PROG_INTLTOOL([0.35.0])
AC_OUTPUT([
Makefile
po/Makefile.in
data/Makefile
])

18
data/catalog.xml.in Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0"?>
<msgcat>
<_msgstr msgid="homelabel">Home</_msgstr>
<_msgstr msgid="userslabel">Users</_msgstr>
<_msgstr msgid="userstext">
Even though it's extremely user-friendly, GNOME is a large and complex system,
and thus, requires some learning to use to the fullest. To make that
easier, we've provided some very useful documentation.
</_msgstr>
<_msgstr msgid="developerslabel">Developers</_msgstr>
<_msgstr msgid="developerstext">
For those who develop, or are interested in developing GNOME and applications
for GNOME. You will find developer documentation and information on how to get
involved, and much more.
</_msgstr>
<_msgstr msgid="langinfo">Available Languages:</_msgstr>
<_msgstr msgid="availableversions">Available Versions:</_msgstr>
</msgcat>

5
data/js/langcookie.js Normal file
View File

@ -0,0 +1,5 @@
if(clang = getCookie('language')) {
if(clang==lang) text = 'Preferred language ('+lang+') is loaded from a cookie.';
else text = 'Unable to display document in preferred language loaded from cookie ('+clang+'), as translation probably does not exist.';
document.write('<br/><br/>'+text+'<br/><a href="#" onclick="removeLangCookie(); return false;">Remove cookie.</a><br/>');
}

View File

@ -0,0 +1,34 @@
function setCookie(c_name,value,expiredays) {
var exdate=new Date();
exdate.setDate(exdate.getDate()+expiredays);
document.cookie=c_name+ "=" +escape(value)+ ";path=/"+
((expiredays==null) ? "" : ";expires="+exdate);
}
function getCookie(c_name) {
if (document.cookie.length>0) {
c_start=document.cookie.indexOf(c_name + "=")
if (c_start!=-1) {
c_start=c_start + c_name.length+1;
c_end=document.cookie.indexOf(";",c_start);
if (c_end==-1) c_end=document.cookie.length;
return unescape(document.cookie.substring(c_start,c_end))
}
}
return null;
}
function removeLangCookie() {
setCookie('language','',null);
if( (end=url.indexOf('.html.'+lang)) == -1) end=url.length;
window.location = url.substring(0,end);
}
var lang = document.getElementsByTagName('html')[0].lang;
var url = window.location.toString();
// explicit change of language by clicking on a link
if(url.indexOf('.html.'+lang) != -1) {
setCookie('language', lang, 30);
}

110
data/languages.xml Normal file
View File

@ -0,0 +1,110 @@
<?xml version="1.0"?>
<!-- this file has initially been created from gdm/gui/gdmlanguages.c -->
<languages>
<lang code="sq_AL">Shqip</lang>
<lang code="hy_AM">Հայերեն</lang>
<lang code="az_AZ">Azərbaycanca</lang>
<lang code="eu_ES">Euskara</lang>
<lang code="be_BY">Беларуская мова</lang>
<lang code="bn_BD">বাংলা</lang>
<lang code="bn_IN">বাংলা</lang>
<lang code="bg_BG">Български</lang>
<lang code="bs_BA">Bosanski</lang>
<lang code="ca_ES">Català</lang>
<lang code="zh_CN">中文 (中国大陆)</lang>
<lang code="zh_HK">中文 (香港)</lang>
<lang code="zh_SG">中文 (新加坡)</lang>
<lang code="zh_TW">中文 (台灣)</lang>
<lang code="hr_HR">Hrvatski</lang>
<lang code="cs_CZ">čeština</lang>
<lang code="da_DK">dansk</lang>
<lang code="nl_NL">Nederlands</lang>
<lang code="nl_BE">Nederlands (België)</lang>
<lang code="en">English</lang>
<lang code="en_US">American English</lang>
<lang code="en_AU">Australian English</lang>
<lang code="en_GB">British English</lang>
<lang code="en_CA">Canadian English</lang>
<lang code="en_IE">Irish English</lang>
<lang code="en_DK">Danish English</lang>
<lang code="en_ZA">South African English</lang>
<lang code="en_MT">Maltese English</lang>
<lang code="en_NZ">New Zealand English</lang>
<lang code="et_EE">Eesti</lang>
<lang code="fi_FI">Suomi</lang>
<lang code="fr_FR">Français</lang>
<lang code="fr_BE">Français (Belgique)</lang>
<lang code="fr_CA">Français (Canada)</lang>
<lang code="fr_LU">Français (Luxembourg)</lang>
<lang code="fr_CH">Français (Suisse)</lang>
<lang code="gl_ES">Galego</lang>
<lang code="de_DE">Deutsch</lang>
<lang code="de_AT">Deutsch (Österreich)</lang>
<lang code="de_LU">Deutsch (Luxemburg)</lang>
<lang code="de_CH">Deutsch (Schweiz)</lang>
<lang code="el_GR">Ελληνικά</lang>
<lang code="el_CY">Ελληνικά (Κύπρος)</lang>
<lang code="gu_IN">ગુજરાતી</lang>
<lang code="he_IL">עברית</lang>
<lang code="iw_IL">עברית</lang>
<lang code="hi_IN">हिंदी</lang>
<lang code="hu_HU">Magyar</lang>
<lang code="id_ID">Bahasa Indonesia</lang>
<lang code="ga_IE">Gaeilge</lang>
<lang code="it_IT">Italiano</lang>
<lang code="ja_JP">日本語</lang>
<lang code="kn_IN">ಕನ್ನಡ</lang>
<lang code="rw_RW">Kinyarwanda</lang>
<lang code="ko_KR">한국어</lang>
<lang code="lv_LV">Latviešu</lang>
<lang code="lt_LT">Lietuvių</lang>
<lang code="ms_MY">Bahasa Melayu</lang>
<lang code="ml_IN">മലയാളം</lang>
<lang code="mn_MN">Монгол</lang>
<lang code="nso_ZA">Sesotho sa Leboa</lang>
<lang code="no_NO">Norsk (bokmål)</lang>
<lang code="nn_NO">Norsk (nynorsk)</lang>
<lang code="fa_IR">فارسی</lang>
<lang code="pl_PL">Polski</lang>
<lang code="pt_PT">Português</lang>
<lang code="pt_BR">Português do Brasil</lang>
<lang code="ro_RO">Română</lang>
<lang code="ru_RU">русский</lang>
<lang code="sr_YU">српски</lang>
<lang code="sr_CS">српски</lang>
<lang code="sr_ME">српски</lang>
<lang code="sr_RS">српски</lang>
<lang code="sr_CS@Latn">srpski (latinica)</lang>
<lang code="sr_CS@ije">српски (ијекавски)</lang>
<lang code="sh_BA">srpski (Bosna i Hercegovina)</lang>
<lang code="sk_SK">Slovenský</lang>
<lang code="sl_SI">Slovenščina</lang>
<lang code="es_ES">Español</lang>
<lang code="es_AR">Español (Argentina)</lang>
<lang code="es_BO">Español (Bolivia)</lang>
<lang code="es_CL">Español (Chile)</lang>
<lang code="es_CO">Español (Colombia)</lang>
<lang code="es_CR">Español (Costa Rica)</lang>
<lang code="es_EC">Español (Ecuador)</lang>
<lang code="es_GT">Español (Guatemala)</lang>
<lang code="es_MX">Español (México)</lang>
<lang code="es_NI">Español (Nicaragua)</lang>
<lang code="es_PA">Español (Panamá)</lang>
<lang code="es_PE">Español (Perú)</lang>
<lang code="es_PY">Español (Paraguay)</lang>
<lang code="es_SV">Español (El Salvador)</lang>
<lang code="es_UY">Español (Uruguay)</lang>
<lang code="es_VE">Español (Venezuela)</lang>
<lang code="sv_SE">Svenska</lang>
<lang code="sv_FI">Svenska (Finland)</lang>
<lang code="th_TH">ไทย</lang>
<lang code="tr_TR">Türkçe</lang>
<lang code="uk_UA">Українська</lang>
<lang code="vi_VN">Việt Nam</lang>
<lang code="wa_BE">Walon</lang>
<lang code="cy_GB">Cymraeg</lang>
<lang code="xh_ZA">isiXhosa</lang>
<lang code="yi">ייִדיש</lang>
<lang code="zu_ZA">isiZulu</lang>
</languages>

223
data/pages/C/libgo.xml Normal file
View File

@ -0,0 +1,223 @@
<?xml version="1.0"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
<!ENTITY date "July 2007">
]>
<article id="index" lang="en">
<articleinfo>
<title>GNOME Library Help</title>
<publisher role="maintainer">
<publishername> GNOME Documentation Project </publishername>
</publisher>
<authorgroup>
<author>
<firstname>Goran</firstname>
<surname>Rakic</surname>
</author>
</authorgroup>
<revhistory>
<revision>
<revnumber>GNOME Library Help v0</revnumber>
<date>July 2007</date>
</revision>
</revhistory>
<abstract role="description">
<para>Information pages on library.gnome.org</para>
</abstract>
</articleinfo>
<sect1 id="about">
<title>About library.gnome.org</title>
<para>
library.gnome.org aims to be the central place for documentation related
to the GNOME project, be it for users, system administrators or
developers.
</para>
</sect1>
<sect1 id="langinfo">
<title>This web site in different languages</title>
<para>
When your request a document from a server, your language preference is
passed via HTTP Accept-Language header. This is a standard way to deliver
preferred version of page available in more then one language. It is very
important to setup your browser language preference correctly.
</para>
<sect2>
<title>What to do if page is in wrong language</title>
<para>
The usual reason is that your web browser is improperly configured.
Skip to How to set up the language settings section for more
informations. You may use this <ulink
url="http://www.cs.tut.fi/cgi-bin/run/~jkorpela/lang.cgi">nice online
tool</ulink> to see what languages does your browser request.
</para>
<para>
If your browser is configured, the problem may be that your ISP or your
internal network is using misconfigured cache or proxy server. They are
servers without any content that sits in the middle between users and
real web servers. They grab your requests for web pages and fetch the
page. After that, they forward the page to you but also make a local,
cached copy, for later requests. This can really cut down on network
traffic when many users request the same page.
</para>
<para>
Problem is when they do not understands content negotiation and keep
cached copy of a page in only one language. The only way you can fix
this is to complain to your ISP in order for them to upgrade or replace
their software.
</para>
<para>
Third problem may be that you are unable or do not want to change
browser settings. If you have JavaScript and cookies enabled, our
server will store your language preference in a cookie every time you
change language manualy by clicking on a link. The next time you click
on link to another page, your language selection will be preserved.
</para>
</sect2>
<sect2>
<title>How to set up the language settings</title>
<para>
Generaly, you should include all languages you can read in preferred
language, ordered by preference. It is good idea to include English
('en') as last item in your list, to use it as a fallback language. You
need to be careful with sub-categories of languages, en-GB will not
include en, so you need to include both en and en-GB in your list.
</para>
<variablelist>
<varlistentry>
<term>Epiphany</term>
<listitem><para>
<menuchoice>
<guimenu>Edit</guimenu>
<guimenuitem>Preferences</guimenuitem>
<guimenuitem>Languages</guimenuitem>
</menuchoice>
</para></listitem>
</varlistentry>
<varlistentry>
<term>Firefox</term>
<listitem><para>
<menuchoice>
<guimenu>Tools</guimenu>
<guimenuitem>Options</guimenuitem>
<guimenuitem>General</guimenuitem>
<guimenuitem>Languages</guimenuitem>
</menuchoice>
</para></listitem>
</varlistentry>
<varlistentry>
<term>Galeon</term>
<listitem><para>
<menuchoice>
<guimenu>Settings</guimenu>
<guimenuitem>Preferences</guimenuitem>
<guimenuitem>Rendering</guimenuitem>
<guimenuitem>Languages</guimenuitem>
</menuchoice>
</para></listitem>
</varlistentry>
<varlistentry>
<term>Mozilla / Netscape Navigator</term>
<listitem><para>
<menuchoice>
<guimenu>Edit</guimenu>
<guimenuitem>Preferences</guimenuitem>
<guimenuitem>Navigator</guimenuitem>
<guimenuitem>Languages</guimenuitem>
</menuchoice>
</para></listitem>
</varlistentry>
<varlistentry>
<term>Lynx</term>
<listitem><para>
<menuchoice>
<guimenu>O (Options)</guimenu>
<guimenuitem>Headers Transferred to Remote Servers</guimenuitem>
<guimenuitem>Preferred document language</guimenuitem>
</menuchoice>
</para></listitem>
</varlistentry>
<varlistentry>
<term>Amaya</term>
<listitem><para>
<menuchoice>
<guimenu>Edit</guimenu>
<guimenuitem>Preferences</guimenuitem>
<guimenuitem>Browsing</guimenuitem>
<guimenuitem>List of preferred languages</guimenuitem>
</menuchoice>
</para></listitem>
</varlistentry>
<varlistentry>
<term>Internet Explorer</term>
<listitem><para>
<menuchoice>
<guimenu>Tools</guimenu>
<guimenuitem>Internet Options</guimenuitem>
<guimenuitem>General</guimenuitem>
<guimenuitem>Languages</guimenuitem>
</menuchoice>
</para></listitem>
</varlistentry>
<varlistentry>
<term>Opera</term>
<listitem><para>
<menuchoice>
<guimenu>File</guimenu>
<guimenuitem>Preferences</guimenuitem>
<guimenuitem>Languages</guimenuitem>
</menuchoice>
</para></listitem>
</varlistentry>
<varlistentry>
<term>Safari</term>
<listitem><para>
<menuchoice>
<guimenu>Max OS X System preferences</guimenu>
<guimenuitem>International</guimenuitem>
<guimenuitem>Language</guimenuitem>
</menuchoice>
</para></listitem>
</varlistentry>
</variablelist>
</sect2>
<sect2>
<title>About translation</title>
<para>
All translations are available as an effort of <ulink
url="http://developer.gnome.org/projects/gtp/">Gnome Translation
Project (GTP)</ulink>.
</para>
</sect2>
</sect1>
</article>

5
data/pages/Makefile.am Normal file
View File

@ -0,0 +1,5 @@
include $(top_srcdir)/gnome-doc-utils.make
dist-hook: doc-dist-hook
DOC_MODULE = libgo

9
data/pages/libgo.omf.in Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" standalone="no"?>
<omf>
<resource>
<subject category="System|Other"/>
<type></type>
<relation seriesid="80474b20-3e15-11dc-81d8-a934f6e83b73"/>
<rights type="GNU GPL" license.version="2.0 or later" holder="Frederic Peters"/>
</resource>
</omf>

BIN
data/skin/admon-bug.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
data/skin/admon-caution.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
data/skin/admon-note.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
data/skin/admon-tip.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
data/skin/admon-warning.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 154 B

After

Width:  |  Height:  |  Size: 154 B

BIN
data/skin/dev-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 699 B

After

Width:  |  Height:  |  Size: 699 B

View File

Before

Width:  |  Height:  |  Size: 178 B

After

Width:  |  Height:  |  Size: 178 B

View File

Before

Width:  |  Height:  |  Size: 212 B

After

Width:  |  Height:  |  Size: 212 B

BIN
data/skin/gnome-16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
data/skin/icons/devhelp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 846 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 846 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

389
data/skin/lgo.css Normal file
View File

@ -0,0 +1,389 @@
body {
margin: 0px;
padding: 0px;
font-family: sans-serif;
background: white url(star.png) -100px -200px no-repeat;
height: 101%;
}
#page {
margin: 0px;
padding: 0px;
}
div.in-column {
margin: 0 0 2em 1em;
float: right;
max-width: 12em;
}
hr {
color: black;
background: black;
border: 0;
height: 1px;
width: 200px;
text-align: center;
clear: both;
}
div.body {
clear: both;
}
div.sidebar {
position: absolute;
text-align: left;
right: 0px;
top: 15ex;
width: 27ex;
padding-left: 1ex;
border-left: 1ex solid #eee;
}
div.sidebar h2 {
margin-top: 0;
padding: 5px 2ex 5px 2ex;
background: url(t.png) top left repeat-y;
font-size: 100%;
}
ul.toc {
padding: 0;
padding-left: 20px;
margin-left: 0;
margin-right: 10px;
list-style: none;
}
ul.toc li {
list-style: circle;
}
ul.toc li a {
text-decoration: none;
color: black;
}
ul.toc li a:hover {
text-decoration: underline;
}
#general {
list-style: none;
background: #2E3436 url(eneral_bg.png) 0 100% repeat-x;
text-align: right;
padding: 0 1ex;
margin: 0;
font-size: 70%;
}
#general li {
display: inline;
background: url(eneral_separator.png) 0 0 no-repeat;
padding-top: 10px;
padding-bottom: 8px;
margin-left: 0px;
margin-top: 0px;
}
#general li a {
font-weight: bold;
color: #FFFFFF;
margin: 0 2ex;
text-decoration: none;
line-height: 30px;
}
#general li a:hover {
text-decoration: underline;
}
#general .home {
float: left;
background: url(general_separator.png) 100% 0 no-repeat;
padding-top: 0;
padding-bottom: 0;
}
#general .home a {
float: left;
background: url(foot.png) 7px 50% no-repeat;
margin-left: 0;
padding-left: 27px;
}
#header {
background: #729FCF url(logo.png) 3ex 10px no-repeat;
float: left;
width: 100%;
font-size: 75%;
}
#header h1 {
margin: 0;
margin-left: 200px;
padding-top: 30px;
font-size: 150%;
}
#tabs {
background: url(bar.png) 0 100% repeat-x;
width: 100%;
float: left;
margin: 0;
padding: 0;
}
#portal-globalnav {
float: right;
list-style: none;
margin: 0;
margin-right: 3ex;
}
#portal-globalnav li {
float: left;
margin: 0;
margin-left: 0.2ex;
font-size: 2ex;
}
#portal-globalnav li a:hover {
color: #111111;
}
#portal-globalnav li a {
float: left;
text-decoration: none;
color: #555555;
background: url(tab_left.png) 0 0 no-repeat;
padding: 7px 0 7px 7px;
border-bottom: 2px solid #CCCCCC;
}
#portal-globalnav li span {
background: url(tab_right.png) 100% 0 no-repeat;
padding: 7px 28px 7px 19px;
}
#portal-globalnav li.selected a {
color: #3566A5;
background: url(tab_left.png) 0 -57px no-repeat;
border-bottom: none;
padding-top: 8px;
padding-bottom: 8px;
}
#portal-globalnav li.selected a span {
background: url(tab_right.png) 100% -57px no-repeat;
padding-top: 8px;
padding-bottom: 8px;
}
div.articleinfo h1 {
padding-top: 1ex;
color: #d40000;
}
div.articleinfo h3.abstract {
font-weight: normal;
border: 5px solid #eee;
padding: 1ex;
-moz-border-radius: 10px;
font-size: 100%;
background: white;
}
div.articleinfo dd.affiliation {
color: #a4a4a4;
margin-bottom: 1ex;
}
div.articleinfo dl {
margin-left: 1em;
}
dl.doc-index {
margin-left: 1em;
}
dl.doc-index p {
margin: 0.5ex 0;
}
dl.doc-index dt {
margin-top: 2em;
}
dl.doc-index dd {
margin-bottom: 2em;
margin-left: 1em;
}
dl.doc-index dt a {
color: #d40000;
text-decoration: none;
font-weight: bold;
font-size: 110%;
}
div.body {
background-color: transparent;
border: none;
padding: 1em;
}
div.body-sidebar {
margin-right: 27ex;
}
div.navbar {
margin: 0 29ex 0 2ex;
}
h1.title {
font-size: 1.72em;
margin: 0; padding: 0;
color: #3f3f3f;
}
h1.title a {
color: inherit;
text-decoration: none;
}
div#language {
position: absolute;
right: 2em;
top: 6ex;
}
/* from goran css */
#dev, #usr {
float: left;
margin: 70px 3% 0px 3%;
width: 42%;
padding: 5px;
}
div.sidebar #dev, div.sidebar #usr {
float: none;
width: 90%;
font-size: 90%;
}
#dev p, #usr p {
margin: 20px;
}
#usr h2 a, #dev h2 a, #usr h2 span, #dev h2 span {
display: block; width: 80%;
text-decoration: none;
padding: 10px 20px;
}
#usr h2 a, #usr h2 span { color: #ffffff; }
#dev h2 a { color: #2e3436; }
#usr h2, #dev h2 {
height: 40px;
font-size: 11pt;
-moz-border-radius: 3%;
padding: 0px;
background: none;
}
#usr h2 { background: #729fcf url(user-icon.png) 95% no-repeat; }
#dev h2 { background: #edd400 url(dev-icon.png) 95% no-repeat; }
#updated h3 { margin-bottom: 15px; }
div.sidebar h4 a {
text-decoration: none;
margin: 0px;
}
div.sidebar p.i18n {
margin-top: -15px;
}
div.sidebar fieldset {
margin-top: 30px;
border: none;
}
table#top {
margin: 1em auto;
clear: both;
border: 1px solid #faa;
background: #fee;
width: 95%;
}
div.book, div.chapter, div.refentry, div.sect1, div.index {
margin: 1em;
}
.synopsis, .classsynopsis
{
background: #eee;
border: solid 1px #aaa;
padding: 0.5em;
}
.programlisting
{
background: #eef;
border: solid 1px #aaf;
padding: 0.5em;
}
.variablelist
{
padding: 4px;
margin-left: 3em;
}
.variablelist td:first-child
{
vertical-align: top;
}
ul.i18n {
list-style: none;
}
ul.versions {
margin: 0;
padding: 0;
padding-left: 1em;
}
ul.versions li {
display: inline;
margin: 0 0.5ex;
}
h2.category {
background-position: center left;
background-repeat: no-repeat;
margin-top: 2em;
color: #006;
min-height: 32px;
}
h2.cat-accessibility-directory { padding-left: 40px; background-image: url(icons/accessibility-directory.png); }
h2.cat-gnome-util { padding-left: 40px; background-image: url(icons/gnome-util.png); }
h2.cat-gnome-joystick { padding-left: 40px; background-image: url(icons/gnome-joystick.png); }
h2.cat-gnome-graphics { padding-left: 40px; background-image: url(icons/gnome-graphics.png); }
h2.cat-gnome-globe { padding-left: 40px; background-image: url(icons/gnome-globe.png); }
h2.cat-gnome-applications { padding-left: 40px; background-image: url(icons/gnome-applications.png); }
h2.cat-gnome-other { padding-left: 40px; background-image: url(icons/gnome-other.png); }
h2.cat-gnome-devel { padding-left: 40px; background-image: url(icons/gnome-devel.png); }
h2.cat-gnome-multimedia { padding-left: 40px; background-image: url(icons/gnome-multimedia.png); }
h2.cat-gnome-system { padding-left: 40px; background-image: url(icons/gnome-system.png); }
h2.cat-api-references { padding-left: 40px; background-image: url(icons/devhelp.png); }

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

Before

Width:  |  Height:  |  Size: 160 B

After

Width:  |  Height:  |  Size: 160 B

View File

Before

Width:  |  Height:  |  Size: 928 B

After

Width:  |  Height:  |  Size: 928 B

View File

Before

Width:  |  Height:  |  Size: 914 B

After

Width:  |  Height:  |  Size: 914 B

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 317 B

After

Width:  |  Height:  |  Size: 317 B

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 215 B

After

Width:  |  Height:  |  Size: 215 B

BIN
data/skin/user-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -27,7 +27,7 @@ along with libgo; if not, write to the Free Software Foundation, Inc.,
<!-- FIXME: Shaun's styles are under LGPL, is it OK to use GPL for this? -->
<xsl:import href="/usr/share/xml/gnome/xslt/docbook/html/db2html.xsl"/>
<xsl:import href="../../common/heading.xsl"/>
<xsl:import href="heading.xsl"/>
<!-- This gets set on the command line ... -->
<xsl:param name="libgo.lang" select="''"/>
@ -92,10 +92,14 @@ along with libgo; if not, write to the Free Software Foundation, Inc.,
<!-- FIXME: when we override db2html.css, do this there -->
<xsl:template name="db2html.division.head.extra">
<link rel="stylesheet" type="text/css" href="/skin/lgo.css"/>
<link rel="icon" type="image/png" href="/skin/gnome-16.png"/>
<link rel="SHORTCUT ICON" type="image/png" href="/skin/gnome-16.png"/>
</xsl:template>
<xsl:template name="db2html.division.top">
<xsl:call-template name="libgo.header" />
<xsl:call-template name="libgo.header">
<xsl:with-param name="lang"><xsl:value-of select="$libgo.lang"/></xsl:with-param>
</xsl:call-template>
</xsl:template>
</xsl:stylesheet>

41
data/xslt/gettext.xsl Normal file
View File

@ -0,0 +1,41 @@
<?xml version='1.0' encoding='UTF-8'?>
<!--
Copyright (c) 2007 Frederic Peters <fpeters@0d.be>.
This file is part of libgo.
libgo is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
libgo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with libgo; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
xmlns:html="http://www.w3.org/1999/xhtml"
extension-element-prefixes="exsl"
version="1.0">
<xsl:template name="gettext">
<xsl:param name="lang"/>
<xsl:param name="msgid"/>
<xsl:choose>
<xsl:when test="document('../catalog.xml')/msgcat/msgstr[@msgid = $msgid and @xml:lang = $lang]">
<xsl:value-of select="document('../catalog.xml')/msgcat/msgstr[@msgid = $msgid and @xml:lang = $lang]"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="document('../catalog.xml')/msgcat/msgstr[@msgid = $msgid]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

View File

@ -0,0 +1,69 @@
<?xml version='1.0' encoding='UTF-8'?>
<!--
Copyright (c) 2007 Frederic Peters <fpeters@0d.be>.
This file is part of libgo.
libgo is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
libgo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with libgo; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xsl:exclude-result-prefixes="html"
version="1.0">
<!-- apply libgo style to HTML files previously produced by gtk-doc -->
<xsl:import href="heading.xsl"/>
<xsl:param name="libgo.lang" select="'en'"/>
<xsl:param name="libgo.channel" select="'developers'"/>
<xsl:param name="default.encoding" select="'UTF-8'"/>
<xsl:output method="html" encoding="UTF-8" indent="yes"
omit-xml-declaration="yes"
doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"
doctype-system="http://www.w3.org/TR/html4/loose.dtd"/>
<!-- identity -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="meta[@content='text/html; charset=US-ASCII']">
</xsl:template>
<xsl:template match="html:html">
<html>
<head>
<meta content="text/html; charset=utf-8" />
<link rel="stylesheet" href="/skin/lgo.css" type="text/css" />
<xsl:apply-templates select="html:head/html:title"/>
<xsl:apply-templates select="html:head/html:link[@rel != 'stylesheet']"/>
<link rel="icon" type="image/png" href="/skin/gnome-16.png"/>
<link rel="SHORTCUT ICON" type="image/png" href="/skin/gnome-16.png"/>
</head>
<body>
<xsl:call-template name="libgo.header" />
<div class="body">
<xsl:apply-templates select="html:body/*"/>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

View File

@ -23,10 +23,12 @@ along with libgo; if not, write to the Free Software Foundation, Inc.,
version="1.0">
<xsl:import href="/usr/share/gtk-doc/data/gtk-doc.xsl"/>
<xsl:import href="heading.xsl"/>
<xsl:param name="libgo.lang" select="'en'"/>
<xsl:param name="default.encoding" select="'UTF-8'"/>
<xsl:param name="chunker.output.encoding" select="'UTF-8'"/>
<xsl:param name="html.ext" select="'.html.en'"/>
<xsl:param name="html.ext" select="'.html'"/>
<!-- Create XML index file -->
<xsl:template match="bookinfo|articleinfo">
@ -47,10 +49,45 @@ along with libgo; if not, write to the Free Software Foundation, Inc.,
</xsl:call-template>
</xsl:template>
<!-- Disabling DevHelp books -->
<xsl:template name="generate.devhelp">
<xsl:template name="user.header.navigation">
<xsl:call-template name="libgo.header" />
</xsl:template>
<xsl:template name="generate.devhelp2">
<xsl:template name="user.head.content">
<xsl:if test="$gtkdoc.version">
<meta name="generator"
content="GTK-Doc V{$gtkdoc.version} (XML mode)"/>
</xsl:if>
<link rel="stylesheet" href="/skin/lgo.css" type="text/css"/>
<link rel="icon" type="image/png" href="/skin/gnome-16.png"/>
<link rel="SHORTCUT ICON" type="image/png" href="/skin/gnome-16.png"/>
<!-- copied from the html.head template in the docbook stylesheets
we don't want links for all refentrys, thats just too much
-->
<xsl:variable name="this" select="."/>
<xsl:for-each select="//part
|//reference
|//preface
|//chapter
|//article
|//appendix[not(parent::article)]|appendix
|//glossary[not(parent::article)]|glossary
|//index[not(parent::article)]|index">
<link rel="{local-name(.)}">
<xsl:attribute name="href">
<xsl:call-template name="href.target">
<xsl:with-param name="context" select="$this"/>
<xsl:with-param name="object" select="."/>
</xsl:call-template>
</xsl:attribute>
<xsl:attribute name="title">
<xsl:apply-templates select="." mode="object.title.markup.textonly"/>
</xsl:attribute>
</link>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

87
data/xslt/heading.xsl Normal file
View File

@ -0,0 +1,87 @@
<?xml version='1.0' encoding='UTF-8'?><!-- -*- indent-tabs-mode: nil -*- -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml"
version="1.0">
<xsl:import href="gettext.xsl"/>
<xsl:param name="libgo.channel">undefined</xsl:param>
<xsl:template name="libgo.header">
<xsl:param name="channel"><xsl:value-of select="$libgo.channel"/></xsl:param>
<xsl:param name="lang"><xsl:value-of select="$libgo.lang"/></xsl:param>
<div id="page">
<ul id="general">
<li id="siteaction-gnome_home" class="home">
<a href="http://www.gnome.org/" accesskey="" title="Home">Home</a>
</li>
<li id="siteaction-gnome_news">
<a href="http://news.gnome.org" accesskey="" title="News">News</a>
</li>
<li id="siteaction-gnome_projects">
<a href="http://www.gnome.org/projects/" accesskey="" title="Projects">Projects</a>
</li>
<li id="siteaction-gnome_art">
<a href="http://art.gnome.org" accesskey="" title="Art">Art</a>
</li>
<li id="siteaction-gnome_support">
<a href="http://www.gnome.org/support/" accesskey="" title="Support">Support</a>
</li>
<li id="siteaction-gnome_development">
<a href="http://developer.gnome.org" accesskey="" title="Development">Development</a>
</li>
<li id="siteaction-gnome_community">
<a href="http://www.gnome.org/community/" accesskey="" title="Community">Community</a>
</li>
</ul>
<div id="header">
<h1>library.gnome.org</h1>
<div id="control">
<div id="language">
<!-- Placeholder for a template that will probably go here -->
</div>
</div>
<div id="tabs">
<ul id="portal-globalnav">
<li id="portaltab-root">
<xsl:if test="$channel = 'home'">
<xsl:attribute name="class">selected</xsl:attribute>
</xsl:if>
<a href="/"><span>
<xsl:call-template name="gettext"><xsl:with-param name="lang"
select="@lang"/><xsl:with-param name="msgid"
select="'homelabel'"/></xsl:call-template></span></a>
</li>
<li id="portaltab-users">
<xsl:if test="$channel = 'users'">
<xsl:attribute name="class">selected</xsl:attribute>
</xsl:if>
<a href="/users/"><span>
<xsl:call-template name="gettext"><xsl:with-param name="lang"
select="@lang"/><xsl:with-param name="msgid"
select="'userslabel'"/></xsl:call-template></span></a>
</li>
<li id="portaltab-developers">
<xsl:if test="$channel = 'developers'">
<xsl:attribute name="class">selected</xsl:attribute>
</xsl:if>
<a href="/developers/"><span>
<xsl:call-template name="gettext"><xsl:with-param name="lang"
select="@lang"/><xsl:with-param name="msgid"
select="'developerslabel'"/></xsl:call-template></span></a>
</li>
<li id="portaltab-about">
<xsl:if test="$channel = 'about'">
<xsl:attribute name="class">selected</xsl:attribute>
</xsl:if>
<a href="/about/"><span>About</span></a>
</li>
</ul>
</div> <!-- end of #tabs -->
</div> <!-- end of #header -->
</div>
</xsl:template>
</xsl:stylesheet>

343
data/xslt/indexes.xsl Normal file
View File

@ -0,0 +1,343 @@
<?xml version='1.0' encoding='UTF-8'?><!-- -*- indent-tabs-mode: nil -*- -->
<!--
Copyright (c) 2006 Goran Rakic <grakic@devbase.net>.
This file is part of libgo.
libgo is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
libgo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with libgo; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
xmlns:html="http://www.w3.org/1999/xhtml"
extension-element-prefixes="exsl"
version="1.0">
<xsl:import href="heading.xsl"/>
<xsl:import href="gettext.xsl"/>
<!-- This gets set on the command line ... -->
<xsl:param name="libgo.lang" select="''"/>
<xsl:variable name="lcletters">abcdefghijklmnopqrstuvwxyz</xsl:variable>
<xsl:variable name="ucletters">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>
<xsl:output method="html" encoding="UTF-8" indent="yes"
omit-xml-declaration="yes"
doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"
doctype-system="http://www.w3.org/TR/html4/loose.dtd"/>
<xsl:namespace-alias stylesheet-prefix="html" result-prefix="#default"/>
<xsl:template name="category-title">
<xsl:param name="lang"/>
<xsl:param name="tocid"/>
<xsl:if test="document('../externals/toc.xml')//toc[@id = $tocid]/title">
<h2>
<xsl:attribute name="class">category cat-<xsl:value-of select="document('../externals/toc.xml')//toc[@id = $tocid]/@icon"/></xsl:attribute>
<xsl:choose>
<xsl:when test="document('../externals/toc.xml')//toc[@id = $tocid]/title[@xml:lang = $lang]">
<xsl:value-of select="document('../externals/toc.xml')//toc[@id = $tocid]/title[@xml:lang = $lang]"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="document('../externals/toc.xml')//toc[@id = $tocid]/title"/>
</xsl:otherwise>
</xsl:choose>
</h2>
</xsl:if>
<xsl:if test="$tocid = 'api'">
<h2 class="category cat-api-references">API References</h2>
</xsl:if>
</xsl:template>
<xsl:template name="language-label">
<xsl:param name="lang"/>
<xsl:choose>
<xsl:when test="document('../languages.xml')//lang[@code = $lang]">
<xsl:value-of select="document('../languages.xml')//lang[@code =
$lang]"/>
</xsl:when>
<xsl:when test="document('../languages.xml')//lang[substring(@code, 1, 2) = $lang]">
<xsl:value-of
select="document('../languages.xml')//lang[substring(@code, 1, 2) =
$lang]"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$lang"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="document" mode="channelindex">
<dt>
<a href="{@path}" lang="{@lang}">
<xsl:choose>
<xsl:when test="normalize-space(title)">
<xsl:value-of select="title" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@module" />
</xsl:otherwise>
</xsl:choose>
<xsl:if test="substring(@lang, 1, 2) != substring(../@lang, 1, 2)">
[<xsl:value-of select="@lang"/>]
</xsl:if>
</a>
<xsl:if test="abstract">
<dd><p><xsl:value-of select="abstract" /></p></dd>
</xsl:if>
</dt>
</xsl:template>
<xsl:template match="document" mode="modindex">
<exsl:document href="{@channel}/{@modulename}/index.html.{@lang}">
<html lang="{@lang}">
<head>
<title><xsl:value-of select="title" /> - GNOME Library</title>
<link rel="stylesheet" type="text/css" href="/skin/lgo.css"/>
<link rel="icon" type="image/png" href="/skin/gnome-16.png"/>
<link rel="SHORTCUT ICON" type="image/png" href="/skin/gnome-16.png"/>
</head>
<body>
<xsl:call-template name="libgo.header">
<xsl:with-param name="channel" select="@channel"/>
</xsl:call-template>
<div class="body body-sidebar">
<h1 class="article title"><a href="{@path}"><xsl:value-of select="title"/></a></h1>
<xsl:if test="abstract">
<p>
<xsl:value-of select="abstract" />
</p>
</xsl:if>
<xsl:if test="versions">
<p class="versions">
<xsl:call-template name="gettext"><xsl:with-param name="lang"
select="@lang"/><xsl:with-param name="msgid"
select="'availableversions'"/></xsl:call-template>
</p>
<ul class="versions">
<xsl:for-each select="versions/version">
<li><a href="{node()}/"><xsl:value-of select="."/></a></li>
</xsl:for-each>
</ul>
</xsl:if>
</div>
<div class="sidebar">
<xsl:if test="other-languages/lang">
<h4>
<xsl:call-template name="gettext"><xsl:with-param name="lang"
select="@lang"/><xsl:with-param name="msgid"
select="'langinfo'"/></xsl:call-template>
</h4>
<ul class="i18n">
<xsl:for-each select="other-languages/lang">
<li><a href="index.html.{node()}">
<xsl:call-template name="language-label">
<xsl:with-param name="lang" select="."/>
</xsl:call-template>
</a></li>
</xsl:for-each>
</ul>
<script type="text/javascript" src="/js/search-lang-and-cookies.js" />
<script type="text/javascript" src="/js/langcookie.js" />
</xsl:if>
</div>
</body>
</html>
</exsl:document>
</xsl:template>
<xsl:key name="docs-by-tocid" match="document" use="@toc_id" />
<xsl:template match="index">
<xsl:param name="channel" select="@channel"/>
<exsl:document href="{@channel}/index.html.{@lang}">
<html lang="{@lang}">
<head>
<title>
<xsl:choose>
<xsl:when test="@channel = 'users'">
GNOME Library -
<xsl:call-template name="gettext"><xsl:with-param name="lang"
select="@lang"/><xsl:with-param name="msgid"
select="'userslabel'"/></xsl:call-template>
</xsl:when>
<xsl:when test="@channel = 'developers'">
GNOME Library -
<xsl:call-template name="gettext"><xsl:with-param name="lang"
select="@lang"/><xsl:with-param name="msgid"
select="'developerslabel'"/></xsl:call-template>
</xsl:when>
<xsl:otherwise>
GNOME Library
</xsl:otherwise>
</xsl:choose>
</title>
<link rel="stylesheet" type="text/css" href="/skin/lgo.css"/>
<link rel="icon" type="image/png" href="/skin/gnome-16.png"/>
<link rel="SHORTCUT ICON" type="image/png" href="/skin/gnome-16.png"/>
</head>
<body>
<xsl:call-template name="libgo.header">
<xsl:with-param name="channel" select="@channel"/>
<xsl:with-param name="lang" select="@lang"/>
</xsl:call-template>
<div class="body body-sidebar">
<xsl:for-each select="document[not(@toc_id = preceding-sibling::document/@toc_id)]">
<xsl:sort select="@toc_id" />
<xsl:call-template name="category-title"><xsl:with-param name="lang"
select="@lang"/><xsl:with-param name="tocid" select="@toc_id"
/></xsl:call-template>
<dl class="doc-index">
<xsl:for-each select="../document[@toc_id = current()/@toc_id]">
<xsl:sort select="translate(title, $ucletters, $lcletters)"/>
<xsl:apply-templates select="." mode="channelindex"/>
</xsl:for-each>
</dl>
</xsl:for-each>
</div>
<div class="sidebar">
<xsl:if test="@channel = 'users'">
<div id="usr">
<h2><span>
<xsl:call-template name="gettext"><xsl:with-param name="lang"
select="@lang"/><xsl:with-param name="msgid"
select="'userslabel'"/></xsl:call-template>
</span></h2>
<p>
<xsl:call-template name="gettext"><xsl:with-param name="lang"
select="@lang"/><xsl:with-param name="msgid"
select="'userstext'"/></xsl:call-template>
</p>
</div>
</xsl:if>
<xsl:if test="@channel = 'developers'">
<div id="dev">
<h2><span>
<xsl:call-template name="gettext"><xsl:with-param name="lang"
select="@lang"/><xsl:with-param name="msgid"
select="'developerslabel'"/></xsl:call-template>
</span></h2>
<p>
<xsl:call-template name="gettext"><xsl:with-param name="lang"
select="@lang"/><xsl:with-param name="msgid"
select="'developerstext'"/></xsl:call-template>
</p>
</div>
</xsl:if>
<h4>
<xsl:call-template name="gettext"><xsl:with-param name="lang"
select="@lang"/><xsl:with-param name="msgid"
select="'langinfo'"/></xsl:call-template>
</h4>
<ul class="i18n">
<xsl:for-each select="//index[@channel=$channel]">
<xsl:sort select="@lang"/>
<li><a href="index.html.{@lang}">
<xsl:call-template name="language-label">
<xsl:with-param name="lang" select="@lang"/>
</xsl:call-template>
</a></li>
</xsl:for-each>
</ul>
<script type="text/javascript" src="/js/search-lang-and-cookies.js" />
<script type="text/javascript" src="/js/langcookie.js" />
</div>
</body>
</html>
</exsl:document>
</xsl:template>
<xsl:template match="home">
<exsl:document href="index.html.{@lang}">
<html lang="{@lang}">
<head>
<title>GNOME Library</title>
<link rel="stylesheet" type="text/css" href="/skin/lgo.css"/>
<link rel="icon" type="image/png" href="/skin/gnome-16.png"/>
<link rel="SHORTCUT ICON" type="image/png" href="/skin/gnome-16.png"/>
</head>
<body>
<xsl:call-template name="libgo.header">
<xsl:with-param name="channel" select="'home'"/>
<xsl:with-param name="lang" select="@lang"/>
</xsl:call-template>
<div class="body body-sidebar">
<div id="usr">
<h2><a href="users/">
<xsl:call-template name="gettext"><xsl:with-param name="lang"
select="@lang"/><xsl:with-param name="msgid"
select="'userslabel'"/></xsl:call-template>
</a></h2>
<p>
<xsl:call-template name="gettext"><xsl:with-param name="lang"
select="@lang"/><xsl:with-param name="msgid"
select="'userstext'"/></xsl:call-template>
</p>
</div>
<div id="dev">
<h2><a href="developers/">
<xsl:call-template name="gettext"><xsl:with-param name="lang"
select="@lang"/><xsl:with-param name="msgid"
select="'developerslabel'"/></xsl:call-template>
</a></h2>
<p>
<xsl:call-template name="gettext"><xsl:with-param name="lang"
select="@lang"/><xsl:with-param name="msgid"
select="'developerstext'"/></xsl:call-template>
</p>
</div>
</div>
<div class="sidebar">
<h4>
<xsl:call-template name="gettext"><xsl:with-param name="lang"
select="@lang"/><xsl:with-param name="msgid"
select="'langinfo'"/></xsl:call-template>
</h4>
<ul class="i18n">
<xsl:for-each select="//home">
<xsl:sort select="@lang"/>
<li><a href="index.html.{@lang}">
<xsl:call-template name="language-label">
<xsl:with-param name="lang" select="@lang"/>
</xsl:call-template>
</a></li>
</xsl:for-each>
</ul>
<script type="text/javascript" src="/js/search-lang-and-cookies.js" />
<script type="text/javascript" src="/js/langcookie.js" />
</div>
</body>
</html>
</exsl:document>
</xsl:template>
<xsl:template match="indexes">
<xsl:apply-templates select="node()"/>
<xsl:apply-templates select="node()" mode="modindex"/>
</xsl:template>
</xsl:stylesheet>

View File

@ -1,38 +0,0 @@
# Copyright (c) 2006 Goran Rakic <grakic@devbase.net>.
#
# This file is part of libgo.
#
# libgo is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# libgo is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with libgo; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
class modlistDecorator:
"""
modules list decorator - Modify list of items
"""
def getLocators(self):
"Load for gdu and gtkdoc locators"
return ('gdu', 'gtkdoc',)
def getCriteria(self):
"Special glob"
return ('/items',)
def modSubdirs(self, items, module, makefile_path, release, locator):
for m,r in items.copy():
if m in ('gnomemeeting','procman','jhbuild'):
items.remove( (m,r) )
return items

View File

@ -1,46 +0,0 @@
# Copyright (c) 2006 Goran Rakic <grakic@devbase.net>.
#
# This file is part of libgo.
#
# libgo is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# libgo is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with libgo; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import sys, re
from os.path import dirname
from makefileutils import valre
class varinsubdirDecorator:
"""
variables in subdir decorator - Remove any undefined variable from
list of subdirs
"""
def getLocators(self):
"Load for gdu and gtkdoc locators"
return ('gdu', 'gtkdoc',)
def getCriteria(self):
"For every Makefile.am"
return ('*Makefile.am',)
def modSubdirs(self, subdirs, module, makefile_path, release, locator):
for s in subdirs[:]:
v = valre.match(s)
if v:
subdirs.remove(s)
if locator.verbose:
print >> sys.stderr, " Warning: Ignored undefined variable %s in\n %s/Makefile.am\n (module %s, %s release)" % (v.group(1),dirname(makefile_path),module,release)
return subdirs

View File

@ -1,38 +0,0 @@
# Copyright (c) 2006 Goran Rakic <grakic@devbase.net>.
#
# This file is part of libgo.
#
# libgo is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# libgo is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with libgo; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
class ignorepoDecorator:
"""
ignore po decorator - Remove po directory from subdirs as it does
not have Makefile.am. libgo can work without
it but this will turn off useless warnings
"""
def getLocators(self):
"Load for gdu and gtkdoc locators"
return ('gdu', 'gtkdoc',)
def getCriteria(self):
"For every Makefile.am"
return ('*Makefile.am',)
def modSubdirs(self, subdirs, module, makefile_path, release, locator):
if 'po' in subdirs:
subdirs.remove('po')
return subdirs

View File

@ -1,36 +0,0 @@
# Copyright (c) 2006 Goran Rakic <grakic@devbase.net>.
#
# This file is part of libgo.
#
# libgo is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# libgo is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with libgo; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import os.path
class gduekigaDecorator:
"""
fix DOC_MODULE for ekiga - Replace @PACKAGE_NAME@ with 'ekiga'
"""
def getLocators(self):
"Load for gdu locator"
return ('gdu',)
def getCriteria(self):
"For ekiga*/help/Makefile.am"
return (os.path.join('ekiga*', 'help', 'Makefile.am'),)
def modDocobj(self, obj, module, makefile_path, release, locator):
obj.getFuncData(0)[0]['DOC_MODULE'] = 'ekiga'
return obj

View File

@ -1,295 +0,0 @@
libgo 0.1.2 — © 2006, Goran Rakic
ABOUT INTERNALS
Documents are located using "locators". For general locators like gdu
(gnome-doc-utils) or gtkdoc (gtk-doc API references) additional tweaking
can be done using "decorators". Locator must be stored in locators
directory, and defined as class named after its module with 'Locator'
sufix. On loading, module is imported and class initialized. Dictionary
containing locator arguments is passed to locator's constructor. There is
a big note in file 'libgo' on how you can add new options to be passed to
your locator.
Locator class must define getList() method without arguments that returns
list of document objects located. "Document objects" (or docobj for short)
does not have to be fully initialized (some of required properties can be
empty) but it must be capable to finish initialization and do build
process itself. For example of locator implementation you can look at gdu
locator in locators/gdu.py and/or read a section about it in this file.
Of locators, gdu locator is implemented. It can use GNOME's CVS or SVN or
CVS image obtained with jhbuild to access files and selection is done with
command line arguments and access via SVN is default.
Locator can abstract IO operators using a driver for loading files into
cache. Like locator, driver also must be a class, named after module in
which it is located with a 'Driver' suffix. On loading, module is
imported and class is initialized. Unlike locator, driver does not need
to implement any specific interface but it need to be compatible with
locator that is using it.
For example, CVS/SVN and dummy drivers defines same interface as they are
used from gdu and gtkdoc locators:
class dummyDriver:
def getBranches(self, module)
Get a list of branches for a given module. For CVS this is
done by listing Tags and Branches for main ChangeLog file in
a module and searching for gnome-X-Y branches where X is >=2
and Y is even. SVN has native support for listing branches
implemented. List of branches can be tweaked with decorators
so GEDIT-2-8 can become gnome-2-8, etc. You can read more
about branches in separate section bellow
def updateFiles(self, files, basedestdir, branch=None)
Update list of files located in cache in basedestdir for a
branch/tag specified in branch. If branch is None, unstable
HEAD/trunk branch is used. Return tuple of list of updated
files and list of files that don't exist on source.
def getListing(self, path=None, branch=None)
Get list of directories and files in path for branch/tag in
branch. If branch is None, unstable HEAD/trunk branch is
used.
def getModules(self, branch=None)
Return list of modules for branch/tag in branch. If branch
is None, unstable HEAD/trunk branch is used.
Currently, only dummy driver is implemented. Dummy driver is using
jhbuild source dir as a replacement for HEAD branch from cvs.gnome.org
and can access only files for unstable branch. You can notice that dummy
driver can work offline, and CVS/SVN drivers will need access to GNOME's
CVS/SVN server.
Decorators can be implemented for other locators as criteria and
functions for applying decorators are locatator specific. Decorators are
located in decorators directory, in modules named in a form of N-name.py
where N is a number starting at 1. Number in a prefix enforce decorator
loading sequence so cascade decorators can be written. Like locators and
drivers, decorators are implemented as classes named after its module
without N- prefix and having 'Decorator' suffix.
Decorators must provide interface for loading by implementing following
methods:
def getLocators(self):
return tuple of locators on which to
apply this decorator
def getCriteria(self):
return criteria to be used with locator
specific decorator selection function
libgo will load all decorators on initialization, and create instances.
There is a function in utils module to get only decorators for a given
locator. get_decorators(locator) function will return list of tuples
of decorator name, its criteria and instance. Locator now can implement
selection/filter function that will return instances of decorators to
apply on some docobj and interface how docobj or locator interanal state
can be modified. You can refer to section about gdu locator to see how
gdu locator is using Makefile.am path as a criteria for selecting
decorators and to see which interface is implemented by decorators for
gdu locator.
And now something about "Document objects" (or docobjs for short). They
are needed to provide abstraction for building documentation. In short,
document object have a list of callable functions (builder functions)
which is instanced by locators and decorators and that can be called in
sequence to do all the dirty work of getting XHTML output in outputdir.
One builder function can append another builder function to a list to be
called and there is a way to pass some additional data to builder
functions.
Document object also have some properties stored (which can be initialized
with one of a builder functions) like list of languages, urlname (short
ASCII name for urls), branch,... Properties of docobj and it's interface
are documented in docobj module.
For example, with gdu locator there are two functions for every docobj,
one to fetch all files (xml, omf, po, figures,...) using driver and other
to call xml2po and xsltproc utilities. First function take a dictionary
with Makefile.am variables (DOC_MODULE, DOC_LINGUAS...) and populate
docobj's properties and second takes no arguments.
GDU LOCATOR [ SOME PARTS ARE NOT IMPLEMENTED ]
In short, gdu locators loads list of modules, for every module fetch list
of branches (stable branches and unstable HEAD/trunk branch) and load main
Makefile.am files for each branch of every module.
Recursively, it load sub directories from Makefile.am's SUBDIR variable
and load Makefile.am from them. When all Makefile.am files are loaded,
it looks for those using gnome-doc-utils and use info from Makefile to
create docobj.
Criteria for decorators is list of globs and selection function load
decorator if Makefile.am path matches any glob from a list. Decorators
can implement following methods:
def modBranches(self, branches, makefile_path):
Return new list of branches for a given main
module (special glob '/module/')
def modSubdirs(self, subdirs, makefile_path, branch):
Return new list of subdirs for given Makefile.am
Used also for modifing list of modules when
special glob '/' is used.
def modDocobj(self, obj, makefile_path, branch):
Return new or updated document object
def buildDocobj(self, makefile_path, branch):
Do not try to build docobj with gdu locator but
use object returned from decorator. Only lastest
decorator in sequence that is implementing this
method is called and only later decorators from
a sequence are used for modSubdirs/modDocobj calls
modDocobj and buildDocobj can return None, and if docobj is None after
calling all decorators from a sequence docobj is ignored. You can look
at implemented decorators to get better picture.
Decorators are implemented to remove modules that does not have main
Makefile.am file (using special '/' path in glob criterita) and to remove
po directory from list of subdirs (as it does not have main Makefile.am
file). Locator can work without theese decorators but will display many
unnecesary warnings about missing Makefile.am files.
Decorators that are needed are the one to remove undefined variable from
SUBDIR value in Makefile.am (where undefined means that it is not defined
in same file or it is defined in a conditional statement) and one for
ekiga to replace @PACKAGE_NAME@ with ekiga as DOC_MODULE value. There
will be a need for a few more decorators to handle some other special
cases.
gdu locator can handle cases when some required file is missing (when it
will skip over incorrect document) or when PO file is missing (when it
will remove that language from DOC_LINGUAS and continue).
It will rebuilt only docs that are updated or everything if XSLT files or
templates for static content are changed from last rebuilt.
RELEASES
As library.gnome.org presents documentation for both lastest and past
releases of GNOME platform, docobjs continain information about release
branch for documentation item. Locators, can implement their own internal
representations for releases (gdu is using CVS/SVN tags/branches returned
from driver's getBranchees(module) method), but when filling general
docobj's properites there are some rules:
'release' is tuple of uppercase string representing part of GNOME
platform and indetifier of release. For example valid releases
are ('GNOME','2.14'), ('GTK','2.10')... Archived documentation is
grouped by first value from a tuple and sorted by other. After
selecting one release only documentats and categories for that release
is presented to library.gnome.org users.
'is_lastest' is True if document is from lastest stable release
Documents for lastest releases are displayed by default, merged
together whatever part they belong.
'is_unstable' is True if document is from unstable (HEAD/trunk) branch
LOCALIZATION [ NOT YET IMPLEMENTED ]
Documentation localization is part of GNOME Documentation project and is
not an issue to solve using this program. This section is about
localization of static content in libgo output like "Annotation" or
"Recently updated" strings.
LOCALIZING STYLESHEETS
Basic styles used are from GNOME Documentation Project and are localized
as a part of gnome-doc-utils CVS module.
Additional stylesheets used are localized in a same way to produce
l10n.xml file from l10n.xml.in by merging it with po/LANG.po file from
libgo CVS module.
LOCALIZING STATIC CONTENT
JAVASCRIPT SCRIPTS
js/langcookie.js.in # save/delete langauge cookie, display a note
# if language prefs are loaded from cookie
js/annotations.js.in # support for annotations in UI (add new tab under
# table of content and define behaviors)
Output is written as js/langcookie.js.LANG.js generated from
*.in file merged with po/LANG.po
TEMPLATES
tmpl/index.in # main page -> /
# listing one update per channel
tmpl/user.in # main page for user channel -> /user/
tmpl/developer.in # and for developer channel -> /developer/
# listing updates and docs/categories in /
tmpl/user_list.in # cats/subcats/docs listings for users...
tmpl/developer_list.in # ...and for developers
tmpl/user_arch.in # past releases listing for users...
tmpl/developer_arch.in # ...and for developers
Templates are merged with po/LANG.po file to produce localized
templates and are used for creating index files.
CREATING INDEX FILES [ NOT YET IMPLEMENTED ]
Index file are rebuilt on every execution of libgo program.
XML INDEX FILES
As a part of XSLT transformation, index.LANG.xml files, containing
localized name and abstract of a document are generated and located in
same dir as XHTML files of a document.
/user/unstable/applets/accessories/clock/index.sr.xml:
<?xml version="1.0"?>
<name>Упуство за програмче часовника</name>
<abstract>Програмче часовника приказује време и датум на панелу.</abstract>
LIST OF RECENTLY UPDATED DOCUMENTS
After rebuilding updated documents, index files for browsing documentation
are rebuilt. First, list of documents to include as recently updated is
generated for each language on which at least one document exist. For all
languages except English, list of recently updated documents is divided
in two parts, one for localized documents and other for not yet localized
documents and one of theese can be empty.
Unix timestamp of last change in a document (stored in docobj) is
multiplied with importance factor and list of top 2 documents from each
channel is created for English language. Next, for every other language,
if there is no localized document in each lists, lastest localized
document from a channel (if there is any) is founded and stored. Now,
everything is ready for generating index XHTML files.
XHTML INDEX FILES
Localized index templates are loaded and info on updated documents (from
XML index files) is included and XHTML index files are written to output
directory.

View File

@ -1,59 +0,0 @@
libgo 0.1.2 — © 2006, Goran Rakic
REQUIREMENTS
* Python
* xsltproc (part of libxslt)
* gnome-doc-utils (XSLT stylesheets and xml2po program installed)
ABOUT
libgo is simple Python tool to create content for library.gnome.org
website, a location to display documentation of GNOME platform for
users and developers with rich user experience and place where users
can interact with documentation by writing and sharing annotations,
reporting bugs and learn how they can get involved in process of writing
and translating documentation.
Documents to include are located using concept of "locators". I will
try to create locators to include user documentation and API references
for programs and libraries located in GNOME CVS server for current and
past releases of GNOME platform. More about locators and how they work,
you can find in ABOUT INTERNALS section in file HACKING.
USAGE INSTRUCTIONS
libgo /var/www/libgo
Generate library.gnome.org content. Write output to
/var/www/libgo directory. This does not work as only dummy driver
is implemented. (see next command)
libgo -d ~/jhbuild/gnome/ /var/www/libgo
Request usage of dummy driver with jhbuild's CVS HEAD image
located in ~/jhbuild/gnome directory. Can be used offline.
EXIT STATUS
0 Successful program execution.
1 Usage error.
2 Locator loading error.
3 Driver loading error.
4 Decorator loading error.
5 Driver runtime error.
6 Locator runtime error.
16 Only dummy driver is implemented (temporary error code)

View File

@ -1,56 +0,0 @@
== HIGH PRIORITY ==
locators/gtkdoc.py:
Implement gtkdoc locator for building stable API references from tarballs
(later, new driver for accessing XML files in build brigade output or new
item finder for gftp/gftpimg for including latest development tarballs can
be implemented)
locators/gtkdoc/gtkdoc.xslt
Implement styles for transforming DocBook generated by gtkdoc to XHTML
libgo:
indexutils.py:
Create localized index files in outputdir
(browse by module, channel, gnome release)
locators/gdu/gdu.xslt:
TOC in every file, use index-info (or first?) chunk as index
Internationalization
Mockup design, support for annotations (hooks in documents)
== MEDIUM PRIORITY ==
support for unversioned documents:
For locating with other locators
support for annotations:
JavaScript implementation and CGI annotation manager
write missing decorators for gnome-doc-utils, etc.
== LOW PRIORITY ==
drivers/gftpimg.py:
Implement this driver and a tool to convert gftp cache to gftpimg source
(fetching what is missing, but needed, from FTP)
locators/gdu.py:
Replace basename with escaping for files in commands
locators/gdu/gdu.xslt:
Configurable path to gnome-doc-utils XSLT styles
*.py:
Security audit, check command and shutil.rmtree, open, os.makedirs,
os.copyfile, shutil.copy2, os.unlink, os.rename arguments to not allow
writing outside output directory
Review source code comments to reflect recent changes:
- using exceptions for error handling
- always using item = (module,release)
- ...
Rewrite README and HACKING files, add something on exception handling in
drivers/locators.

View File

@ -1,17 +0,0 @@
GNOME platform language bindings
bindings/c++
Doxygen -> HTML
HTML output included in tarball
http://www.gtkmm.org/docs/gtkmm-2.4/docs/
bindings/python
???
http://www.pygtk.org/reference.html
bindings/perl
perldoc / pod?
bindings/java
javadoc??
http://java-gnome.sourceforge.net/docs/javadoc/index.html

View File

@ -1,73 +0,0 @@
.cache/
gnome/
bug-buddy/
unstable/ <- managed with cvs, svn or jhbuild driver
2.14.0/ <- managed with gftp or gftpimg driver
...
dasher/ dir mod/ver (and archive mod-ver.tar.gz in
unstable/ ../.gftp/) can exist if mod/ver is part of
4.0.4/ some GNOME release (I will put .gnome-X-Y
... file inside it to mark that) when it should
evince/ stay there forever, or if it is fetched as
unstable/ lastest stable release for its major sometimes
0.5.2/ in the past when it should be removed (together
... with an archive) when new one is available. I
gedit/ don't think that there can be race condition
unstable/ so when new version is available, I will remove
2.14.4/ dir and archive if it does not have .gnome-X-Y
bug-buddy-2.14.0/ file in it. Decorators can append function to
dasher-4.0.4/ docobj to write/remove this file if special
evince-0.5.2/ care is needed.
gedit-2.14.4/
.gftp/
tmp/
evince-0.5.2/ <- temp dir with extracted archive, cleared
with gftp.clearCache(module) or with
gftp.__del__ for all extracted but not
cleared archives. If it is left here then
something is strange and I should delete
../evince-0.5.2.tar.gz and refetch it again
dasher-4.0.4.tar.gz <- temp archive, will be moved to ../ after
successfull extraction to ./dasher-4.0.4
bug-buddy-2.14.0.tar.gz <- tar.gz archives are stored in gftp cache
gedit-2.14.4.tar.gz
this can be reused with makeftpimg.py to
create an image of GNOME FTP without
refetching archives. image can be used
with gftpimg driver for local/offline
access
gdu module should list releases of gnome, and for every release pull a list of
archives, then pull one by one archive, update main Makefile.am, process it and
then go for all subdirs and update Makefile.am files in them. If Makefile.am
using gnome-doc-utils is found, create docobj and start building of document
when any additional files will be updated and stored to cache.
File paths can be gedit-2.14.4/Makefile.am and gftp/gftpimg driver will know
to which archive do they belong and how to place them in cache (for this
example as gedit/2.14.4/Makefile.am).
For unstable release from version control, gdu module should load list of
modules and for every module update main Makefile.am, then again go for
subdirs, create docobj and start building of document. File path can be
gedit-unstable/Makefile.am and cvs/svn/jhbuild driver will know where to
write it in cache.
Now when gtkdoc module is run, it will check for list of modules on GNOME FTP
and for every module find it's lastest release for every major and then
update main Makefile.am from it. File path will again be in form of
gedit-2.14.4/Makefile.am. If dir gedit/2.14.4 does not exist in cache,
it will check if previous minor release of gedit 2 exists and if it does
and it is not included in GNOME (there is no .gnome-X-Y file in it) it
will delete it from a cache. As gdu will be run before gtkdoc locator,
all archives from some GNOME release will be asigned to GNOME release.
This way we will not refetch anything except that archives will be extracted
twice. I can escape this by not clearing .gftp/tmp/ in gdu, and clear it
after gtkdoc as every tar that is updated will be left there.

View File

@ -1,47 +0,0 @@
Using :pserver: CVS root, 5 files in a time
goran@limun:~/Projects/libgo$ time ./script
U unstable/criawips/API_DISCUSSION
U unstable/criawips/AUTHORS
U unstable/criawips/ChangeLog
U unstable/criawips/NEWS
U unstable/criawips/README
real 0m17.334s
user 0m0.012s
sys 0m0.012s
Using :pserver: CVS root, file-by-file
goran@limun:~/Projects/libgo$ time ./script
U unstable/API_DISCUSSION
U unstable/AUTHORS
U unstable/ChangeLog
U unstable/NEWS
U unstable/README
real 0m52.425s
user 0m0.024s
sys 0m0.036s
Using local CVS root, 5 files in a time
goran@limun:~/Projects/libgo$ time ./script
U unstable/test/API_DISCUSSION
U unstable/test/AUTHORS
U unstable/test/ChangeLog
U unstable/test/NEWS
U unstable/test/README
real 0m3.347s
user 0m0.016s
sys 0m0.000s
using local CVS root, file by file
goran@limun:~/Projects/libgo$ time ./script
U unstable/API_DISCUSSION
U unstable/AUTHORS
U unstable/ChangeLog
U unstable/NEWS
U unstable/README
real 0m4.446s
user 0m0.004s
sys 0m0.040s

File diff suppressed because it is too large Load Diff

View File

@ -1,368 +0,0 @@
Using output directory '/home/goran/Projects/libgo/output/'
Loading decorators... modlist, varinsubdir, ignorepo, gduekiga
Loading locators...
----------------------------------------------------------------------------
gdu locator
Warning: jhbuild driver will use last modification timestamps as last update
of a document. Indexes can be very odd if you have a new image.
Loaded decorators... modlist, varinsubdir, ignorepo, gduekiga
Processing unstable releases of modules
Warning: Ignored undefined variable @PYTHON_SUBDIR@ in
/Makefile.am
(module libxml2, unstable release)
Warning: Ignored undefined variable @PYTHON_SUBDIR@ in
/Makefile.am
(module libxslt, unstable release)
Warning: po-properties/Makefile.am
is missing (module gtk+, unstable release)
Warning: Ignored undefined variable $(gdktarget) in
gdk/Makefile.am
(module gtk+, unstable release)
Warning: Ignored undefined variable @PYTHON_SUBDIR@ in
/Makefile.am
(module gamin, unstable release)
Warning: Ignored undefined variable $(BUILD_ENGINES) in
engines/Makefile.am
(module gtk-engines, unstable release)
Warning: Ignored undefined variable $(BUILD_THEMES) in
themes/Makefile.am
(module gtk-engines, unstable release)
Starting gdu default builder bootstrap...
> xsltproc --load-trace /home/goran/Projects/libgo/locators/gdu/xslt/db2html.xsl
Building gnome-doc-make (unstable release)...
> xsltproc /home/goran/Projects/libgo/locators/gdu/xslt/db2html.xsl /home/goran/Projects/libgo/output/.cache/gnome/gnome-doc-utils/unstable/doc/gnome-doc-make/C/gnome-doc-make.xml
Error: xsltproc crashed on doc/gnome-doc-make/C/gnome-doc-make.xml
Module: gnome-doc-utils (unstable release)
xsltproc error output:
Unmatched element: include
No cross reference formatter found for filename elements
runtime error: file /usr/share/xml/gnome/xslt/docbook/html/db2html-inline.xsl line 97 element attribute
xsl:attribute : node already has children
runtime error: file /usr/share/xml/gnome/xslt/docbook/common/db-xref.xsl line 42 element call-template
xsl:call-template : template format.tooltip.mailto not found
runtime error: file /usr/share/xml/gnome/xslt/docbook/common/db-xref.xsl line 42 element call-template
xsl:call-template : template format.tooltip.mailto not found
no result for /home/goran/Projects/libgo/output/.cache/gnome/gnome-doc-utils/unstable/doc/gnome-doc-make/C/gnome-doc-make.xml
--------------------------------------------------------------------
Error: Unable to build document gnome-doc-make unstable
Removing it from documentation list
Building gnome-doc-xslt (unstable release)...
> xsltproc /home/goran/Projects/libgo/locators/gdu/xslt/db2html.xsl /home/goran/Projects/libgo/output/.cache/gnome/gnome-doc-utils/unstable/doc/xslt/C/gnome-doc-xslt.xml
Error: xsltproc crashed on doc/xslt/C/gnome-doc-xslt.xml
Module: gnome-doc-utils (unstable release)
xsltproc error output:
Unmatched element: include
Unmatched element: include
Unmatched element: include
Unmatched element: include
Unmatched element: include
Unmatched element: include
Unmatched element: include
Unmatched element: include
Unmatched element: include
--------------------------------------------------------------------
Error: Unable to build document gnome-doc-xslt unstable
Removing it from documentation list
Building fdl (unstable release)...
Building gpl (unstable release)...
Building lgpl (unstable release)...
Building gnome-feedback (unstable release)...
Warning: libdb/dist/Makefile.am
is missing (module evolution-data-server, unstable release)
Warning: Makefile.am
is missing (module gnome-python, unstable release)
Building clock (unstable release)...
Building fish (unstable release)...
Building window-list (unstable release)...
Building workspace-switcher (unstable release)...
Building gnome-terminal (unstable release)...
Warning: Ignored undefined variable @sysdeps_dir@ in
sysdeps/Makefile.am
(module libgtop, unstable release)
Warning: Ignored undefined variable $(SUB_DIRS) in
/Makefile.am
(module gucharmap, unstable release)
Building gucharmap (unstable release)...
Building char-palette (unstable release)...
Building geyes (unstable release)...
Building command-line (unstable release)...
Building stickynotes_applet (unstable release)...
Building mixer_applet2 (unstable release)...
Building multiload (unstable release)...
Building drivemount (unstable release)...
> xsltproc /home/goran/Projects/libgo/locators/gdu/xslt/db2html.xsl /home/goran/Projects/libgo/output/.cache/gnome/gnome-applets/unstable/drivemount/help/C/drivemount.xml
Error: xsltproc crashed on drivemount/help/C/drivemount.xml
Module: gnome-applets (unstable release)
xsltproc error output:
Unmatched element: citerefentry
Unmatched element: refentrytitle
--------------------------------------------------------------------
Error: Unable to build document drivemount unstable
Removing it from documentation list
Building gweather (unstable release)...
Building trashapplet (unstable release)...
Building battstat (unstable release)...
Building accessx-status (unstable release)...
Building gswitchit (unstable release)...
Building cpufreq-applet (unstable release)...
Warning: Ignored undefined variable $(NULL) in
/Makefile.am
(module nautilus, unstable release)
Warning: Ignored undefined variable $(TYPING_BREAK) in
/Makefile.am
(module gnome-control-center, unstable release)
Building control-center (unstable release)...
Warning: Ignored undefined variable $(THEMUS) in
vfs-methods/Makefile.am
(module gnome-control-center, unstable release)
Warning: Ignored undefined variable $(FONTILUS) in
vfs-methods/Makefile.am
(module gnome-control-center, unstable release)
Building bug-buddy (unstable release)...
Warning: Ignored undefined variable @PROGRAMS_VUMETER@ in
/Makefile.am
(module gnome-media, unstable release)
Warning: Ignored undefined variable @PROGRAMS_GSTMIXER@ in
/Makefile.am
(module gnome-media, unstable release)
Warning: Ignored undefined variable @PROGRAMS_GNOME_CD@ in
/Makefile.am
(module gnome-media, unstable release)
Warning: Ignored undefined variable @PROGRAMS_GRECORD@ in
/Makefile.am
(module gnome-media, unstable release)
Warning: Ignored undefined variable @PROGRAMS_GSTPROPS@ in
/Makefile.am
(module gnome-media, unstable release)
Building gedit (unstable release)...
> xsltproc /home/goran/Projects/libgo/locators/gdu/xslt/db2html.xsl /home/goran/Projects/libgo/output/.cache/gnome/gedit/unstable/help/C/gedit.xml
Error: xsltproc crashed on help/C/gedit.xml
Module: gedit (unstable release)
xsltproc error output:
Unmatched element: citerefentry
Unmatched element: refentrytitle
Unmatched element: citerefentry
Unmatched element: refentrytitle
--------------------------------------------------------------------
Error: Unable to build document gedit unstable
Removing it from documentation list
Warning: Ignored undefined variable $(SPELL_PLUGIN_DIR) in
plugins/Makefile.am
(module gedit, unstable release)
Building eog (unstable release)...
Building gnome-system-log (unstable release)...
Building gnome-search-tool (unstable release)...
Building gnome-dictionary (unstable release)...
Building baobab (unstable release)...
Building gfloppy (unstable release)...
Building gnome-netstatus (unstable release)...
Building gcalctool (unstable release)...
Building zenity (unstable release)...
Building epiphany (unstable release)...
Warning: Ignored undefined variable @SUBDIRS@ in
/Makefile.am
(module gob, unstable release)
Warning: Ignored undefined variable $(gamelist) in
/Makefile.am
(module gnome-games, unstable release)
Warning: Ignored undefined variable $(allgames) in
/Makefile.am
(module gnome-games, unstable release)
Building user-guide (unstable release)...
> xsltproc /home/goran/Projects/libgo/locators/gdu/xslt/db2html.xsl /home/goran/Projects/libgo/output/.cache/gnome/gnome-user-docs/unstable/gnome2-user-guide/C/user-guide.xml
Error: xsltproc crashed on gnome2-user-guide/C/user-guide.xml
Module: gnome-user-docs (unstable release)
xsltproc error output:
Unmatched element: include
Unmatched element: include
Unmatched element: include
Unmatched element: include
Unmatched element: include
Unmatched element: include
Unmatched element: include
Unmatched element: include
Unmatched element: include
--------------------------------------------------------------------
Error: Unable to build document user-guide unstable
Removing it from documentation list
Building gnome-access-guide (unstable release)...
Building system-admin-guide (unstable release)...
Building file-roller (unstable release)...
Building boot-admin (unstable release)...
Building network-admin (unstable release)...
Building services-admin (unstable release)...
Building time-admin (unstable release)...
Building users-admin (unstable release)...
Building gnome-nettool (unstable release)...
> xsltproc /home/goran/Projects/libgo/locators/gdu/xslt/db2html.xsl /home/goran/Projects/libgo/output/.cache/gnome/gnome-nettool/unstable/help/C/gnome-nettool.xml
Error: xsltproc crashed on help/C/gnome-nettool.xml
Module: gnome-nettool (unstable release)
xsltproc error output:
Unmatched element: citerefentry
Unmatched element: refentrytitle
Unmatched element: citerefentry
Unmatched element: refentrytitle
Unmatched element: citerefentry
Unmatched element: refentrytitle
--------------------------------------------------------------------
Error: Unable to build document gnome-nettool unstable
Removing it from documentation list
Building sound-juicer (unstable release)...
> xsltproc /home/goran/Projects/libgo/locators/gdu/xslt/db2html.xsl /home/goran/Projects/libgo/output/.cache/gnome/sound-juicer/unstable/help/sound-juicer/C/sound-juicer.xml
Error: xsltproc crashed on help/sound-juicer/C/sound-juicer.xml
Module: sound-juicer (unstable release)
xsltproc error output:
Unmatched element: include
--------------------------------------------------------------------
Error: Unable to build document sound-juicer unstable
Removing it from documentation list
Warning: Ignored undefined variable $(plugins_enabled) in
plugins/Makefile.am
(module evolution, unstable release)
Warning: Ignored undefined variable $(all_plugins_base) in
plugins/Makefile.am
(module evolution, unstable release)
Warning: Ignored undefined variable $(all_plugins_standard) in
plugins/Makefile.am
(module evolution, unstable release)
Warning: Ignored undefined variable $(all_plugins_experimental) in
plugins/Makefile.am
(module evolution, unstable release)
Building ekiga (unstable release)...
Building evince (unstable release)...
Building dasher (unstable release)...
Building gnome-keyring-manager (unstable release)...
Building fast-user-switch-applet (unstable release)...
Warning: Ignored undefined variable $(GLADE_GNOME_DIR) in
glade/Makefile.am
(module glade, unstable release)
Warning: Ignored undefined variable $(GLADE_GNOME_DB_DIR) in
glade/Makefile.am
(module glade, unstable release)
Processing stable releases of modules
Fetching info on GNOME releases and modules
Listing modules . . . . . . . . . . . . . . . . . . . . . . . . . . done
Listing GNOME modules . done
Warning: Modules from GNOME releases, not included in stable modules list
Appended: 'evince-0.5', 'gnome-doc-utils-0.6', 'gnome-keyring-0.4', 'gnome-mag-0.12', 'gnome-speech-0.4', 'gnome-volume-manager-1.5', 'gnopernicus-1.1', 'gst-plugins-base-0.10', 'gst-plugins-good-0.10', 'gstreamer-0.10', 'libgail-gnome-1.1', 'scrollkeeper-0.3', 'startup-notification-0.8', 'vino-2.13', 'vte-0.12', 'pessulus-0.9', 'evince-0.4', 'gnome-doc-utils-0.4', 'gnome-keyring-0.4', 'gnome-mag-0.12', 'gnome-speech-0.3', 'gnopernicus-0.11', 'gst-plugins-0.8', 'gstreamer-0.8', 'libgail-gnome-1.1', 'scrollkeeper-0.3', 'startup-notification-0.8', 'vte-0.11', 'gcalctool-5.5', 'gnome-doc-utils-0.2', 'gnome-keyring-0.4', 'gnome-mag-0.12', 'gnome-speech-0.3', 'gnopernicus-0.10', 'gst-plugins-0.8', 'gstreamer-0.8', 'gtkhtml-3.5', 'libgail-gnome-1.1', 'librsvg-2.9', 'scrollkeeper-0.3', 'startup-notification-0.8', 'vte-0.11', 'gnome-keyring-0.4', 'gnome-mag-0.11', 'gnome-nettool-0.99', 'gnome-speech-0.3', 'gnopernicus-0.9', 'gok-0.11', 'gst-plugins-0.8', 'gstreamer-0.8', 'gtk-engines-2.2', 'gtksourceview-1.1', 'libgail-gnome-1.1', 'nautilus-media-0.8', 'scrollkeeper-0.3', 'startup-notification-0.8', 'vte-0.11'
> RETR /pub/GNOME/sources/gtkhtml/3.5/gtkhtml-3.5.7.tar.gz
Error: Unable to get MD5 for archive gtkhtml-3.5.7.tar.gz
Error: MD5 missmatch for updated archive, deleted.
Archive: gtkhtml-3.5.7.tar.gz
Trying once more...
> RETR /pub/GNOME/sources/gtkhtml/3.5/gtkhtml-3.5.7.tar.gz
Error: Unable to get MD5 for archive gtkhtml-3.5.7.tar.gz
Error: MD5 missmatch for updated archive, deleted.
Archive: gtkhtml-3.5.7.tar.gz
Skiping module gtkhtml (3.5 release)
47 documentation items found
----------------------------------------------------------------------------
Done building of 47 documentation items
Starting creating indexes...
['es', 'fr', 'uk', 'sv', 'fi', 'pa', 'zh_CN', 'it', 'ru', 'de', 'ja', 'ko', 'nl', 'sr', 'zh_TW', 'bg', 'pt_BR', 'el', 'eu', 'zh_HK']
['user']
index.en.xhtml
fdl
index.es.xhtml
fdl (Is localized)
index.fr.xhtml
fdl (Is localized)
index.uk.xhtml
fdl (Is localized)
index.sv.xhtml
fdl (Is localized)
index.fi.xhtml
fdl (Not localized)
index.pa.xhtml
fdl (Not localized)
index.zh_CN.xhtml
fdl (Not localized)
index.it.xhtml
fdl (Not localized)
index.ru.xhtml
fdl (Not localized)
index.de.xhtml
fdl (Not localized)
index.ja.xhtml
fdl (Not localized)
index.ko.xhtml
fdl (Not localized)
index.nl.xhtml
fdl (Not localized)
index.sr.xhtml
fdl (Not localized)
index.zh_TW.xhtml
fdl (Not localized)
index.bg.xhtml
fdl (Not localized)
index.pt_BR.xhtml
fdl (Not localized)
index.el.xhtml
fdl (Not localized)
index.eu.xhtml
fdl (Not localized)
index.zh_HK.xhtml
fdl (Not localized)

View File

@ -1,39 +0,0 @@
Output size: 48.1MB
Cache size: 61.2MB
gftp cache size: 709.0MB
There are 125 doc items (56 doc modules, with 2.2 releases in average),
each one taking about 394.0KB of disk space.
Largest module is file-roller, with 3 releases and 8.0MB in total size.
Document items failed to build:
gnome-doc-utils/unstable/doc/gnome-doc-make
gnome-doc-utils/unstable/doc/xslt
gnome-doc-utils/0.6/doc/gnome-doc-make
gnome-doc-utils/0.6/doc/xslt
gnome-doc-utils/0.4/doc/gnome-doc-make
gnome-doc-utils/0.4/doc/xslt
gnome-doc-utils/0.2/doc/gnome-doc-make
gnome-doc-utils/0.2/doc/xslt
gnome-applets/unstable/drivemount/help
gnome-applets/2.12/drivemount/help
gnome-applets/2.14/drivemount/help
gedit/unstable/help
gedit/2.14/help
gnome-user-docs/unstable/gnome2-user-guide
gnome-nettool/unstable/help
sound-juicer/unstable/help/sound-juicer
sound-juicer/2.12/help/sound-juicer
Document translations failed to build:
There are no failed documents.
Also, look at libgo output for error messages about skipped doc items.
They are not included in the list above.
Some doc items can be removed from current building list, but
are still in cache (and can be included in list of failed items).

232
docobj.py
View File

@ -1,232 +0,0 @@
# Copyright (c) 2006 Goran Rakic <grakic@devbase.net>.
#
# This file is part of libgo.
#
# libgo is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# libgo is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with libgo; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# doc object - Clas that represents documentation item and have all the
# informations to build XHTML output
import sys, types
from string import lower
def get_langs(docobjs):
"Take a list of docobjs and return a list of languages"
langs = []
for d in docobjs:
for l in d['languages']:
if not l in langs:
langs.append(l)
print langs
return langs
def get_channels(docobjs):
"Take a list of docobjs and return list of channels"
channels = []
for d in docobjs:
if not d['channel'] in channels:
channels.append(d['channel'])
print channels
return channels
def get_updates(docobjs, num, channel, lang = None):
"""
Returns list with num of last updated docobjs from a channel, avaibile
on selected language. docobjs list must be sorted by update timestamp
"""
updates = []
for d in docobjs:
if len(updates) < num:
if d['channel'] == channel:
if not lang or lang in d['languages']:
updates.append(d)
else:
break
return updates
class docobj:
"""
Document object (docobj) is created by locator or decorator and can be
modified by other decorators. In locator/decorator code it is initialized
with 'obj[VAR] = VALUE' where VAR and VALUE may be some of:
General properites:
urlname ASCII name of document used for URL, must be unique
(like $DOC_MODULE value, 'dasher')
channel channel to present doc in ('user' or 'developer')
category document category (subcats separated with '|')
group group name (like 'GNOME' or 'Glib')
group_release group release tuple - list of releases, is_in_latest
(like (['2.12','2.14'], True))
release release tuple - release, is_latest
(like ('4.0.4', True))
is_unstable = False True or False
(if True, release and group_release are None)
languages = [] list of lang codes. Languages can be added item by
item or with list of langs. Duplicates are ignored
and 'en' is not valid value to include
importance = 0.5 importance factor, float from [0,1]
updated = {'en':0} Unix timestamp of last update, per language
For English, it's 0 by default, and it must exist
Some or all of general properites can be empty before building, but
then builder functions must know how to initialize them.
You can use 'obj[VAR]' syntax to access general object properites.
Builder function:
builder_func Callable function to be appended to a list of output
building functions or tuple of callable function and
some data to be used from a function.
Note that function will receive two args, its index in
a list as integer and docobj instance itself, so
function can access its own data with:
def myBuilderFunc(i, obj):
print obj.getFuncData(i)
Data can be None, and it is None if only callable can
be passed as VALUE.
On request, building process is started by calling first function
from a list. If it returns 0 (all OK), the process continues by
calling next function from a list.
For accessing, use 'obj["builder_funcs"]' instead which returns
tuple of two lists, one with functions and the other with arguments.
"""
def __init__(self):
self.objdata ={'importance':1, 'is_latest':False, 'is_unstable':False,
'languages':[], 'updated':{'en':0}}
self.__builder_funcs = []
self.__funcs_data = []
def __setitem__(self, key, val):
if key in ('urlname', 'category', 'group'):
self.objdata[key] = val
elif key == 'updated':
if type(val) == types.DictType and 'en' in val:
self.objdata['updated'] = val
else:
print >> sys.stderr, " Warning: updated must be a dictionary, and 'en' must exist as key, ignored"
elif key == 'release':
if type(val) == types.TupleType and len(val) == 2:
self.objdata['release'] = val
elif key == 'group_release':
if type(val) == types.TupleType and len(val) == 2 and type(val[0]) == types.ListType:
self.objdata['group_release'] = val
elif key == 'is_unstable':
self.objdata['is_unstable'] = val and True
elif key == 'channel':
if val == 'developer' or val == 'user':
self.objdata[key] = val
else:
print >> sys.stderr, " Warning: channel must be 'user' or 'developer', ignored"
elif key == 'importance':
if val >= 0 and val <= 1:
self.objdata[key] = val
else:
print >> sys.stderr, " Warning: importance factor must be a number from [0,1], ignored"
elif key == 'languages':
if 'en' in val:
print >> sys.stderr, " Warning: 'en' is not a valid item in list of languages, ignored"
if type(val) == types.ListType:
self.objdata['languages'].extend(val)
else:
self.objdata['languages'].append(val)
elif key == 'builder_func':
if callable(val):
self.__builder_funcs.append(val)
self.__funcs_data.append(None)
elif callable(val[0]):
self.__builder_funcs.append(val[0])
self.__funcs_data.append(val[1])
else:
print >> sys.stderr, " Warning: builder function is not callable, ignored"
def __getitem__(self, key):
if key in ('urlname', 'channel', 'category', 'importance', 'release', 'group', 'group_release', 'is_unstable', 'updated'):
if key in self.objdata:
return self.objdata[key]
else:
return None
elif key == 'languages':
i = 0; langs = self.objdata['languages'][:]
for l in langs:
if l in langs[:i]:
self.objdata['languages'].remove(l)
i+=1
return self.objdata['languages']
elif key == 'builder_funcs':
return (self.__builder_funcs, self.__funcs_data)
else:
raise KeyError, "Unknown doc object property %s" % key
def __repr__(self):
"Fancy printing of docobj state"
from string import replace
return """
<Instance of %s, address %s>:
General properties:
CHANNEL: %s
URLNAME: %s
RELEASE: %s (latest: %s, unstable: %s)
CATEGORY: %s
LANGUAGES: %s
GROUP NAME: %s
GROUP RELEASE: %s (latest: %s, unstable: %s)
UPDATED: %s
IMPORTANCE: %s
Builder functions:
%s
Builder functions data:
%s
--------------------------------------------------------
""" % (self.__class__.__name__, id(self), self.objdata.get('channel', ''), self.objdata.get('urlname', ''), "", "","", replace(self.objdata.get('category', ''),'|',' > '), str(self.objdata.get('languages', '')), "", self.objdata.get('release', ''), str(self.objdata.get('is_latest', '')), str(self.objdata.get('is_unstable', '')), "", str(self.objdata.get('importance', '')), str(self.__builder_funcs), str(self.__funcs_data))
def build(self):
"Start building of docobj by calling builder functions"
i = 0
while i<len(self.__builder_funcs):
self.__builder_funcs[i](i,self)
i+=1
def getFuncData(self, i):
"Return data to be accessed by builder function"
return self.__funcs_data[i]

View File

@ -1,290 +0,0 @@
# Copyright (c) 2006 Goran Rakic <grakic@devbase.net>.
#
# This file is part of libgo.
#
# libgo is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# libgo is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with libgo; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import sys, types, os, urllib2, re, shutil, locale, time
from os.path import isfile, isdir, abspath, dirname, basename
from calendar import timegm
import utils
class cvsDriver:
"CVS driver - use CVS version control to access files"
# Dictionary mapping CVS name to CVS root and ViewCVS url to use instead
# 'cvs co -c' (if url is None, command output is parsed and used)
roots = {
'gnome': (':pserver:anonymous@anoncvs.gnome.org:2401/cvs/gnome',
'http://cvs.gnome.org/viewcvs/')
}
def __init__(self, cachedir, name, verbose = False):
"""
cvsDriver(cachedir, name, [verbose]) where:
- cachedir is location of cache where to write files.
gdu and gtkdoc locators are using outputdir/.cache/gnome as
cachedir path.
- name is one of keys from cvsDriver.roots and that is a
dictrionary mapping name to (CVS root, url) where url is url
of ViewCVS to use instead 'cvs co -c' and can be None when
command output is parsed and used.
- if verbose is True, driver will print a line from time to time
Note: If you are using some other CVS server than GNOME's, update
content of cvsDriver.roots dictionary!
"""
if not name in cvsDriver.roots:
raise ValueError, "Unknown cvs name %s.\nPlease update cvsDriver.roots before initializing cvs driver." % name
self.cachedir = cachedir
self.root, self.viewcvsurl = cvsDriver.roots[name]
self.verbose = verbose
def getLastUpdate(self, module, files, release):
"""
Return lastest update Unix timestamp of files in list.
If list is empty or all files are missing, 0 is returned.
Release is just for compatibility and is ignored.
"""
last = 0
if type(files) == types.StringType:
files = [files]
for f in files:
dst = dirname(self.cachedir+'/'+module+'/unstable/'+f)
name = basename(f)
if isfile(dst+'/CVS/Entries'):
e = open(dst+'/CVS/Entries')
try:
while True:
line = e.readline()
if not line:
break
line = line.split('/')
if len(line)==6 and line[1] == name:
# Use Jan, Feb,...
locale.setlocale(locale.LC_ALL, 'C')
try:
# This is in UTC
ms = timegm(time.strptime(line[3]))
except ValueError, e:
locale.resetlocale(locale.LC_ALL)
raise RuntimeError,"Invalid last mod date (%s): %s" % (line[3], e)
else:
locale.resetlocale(locale.LC_ALL)
if ms > last:
last = ms
break
finally:
e.close()
return last
def updateFiles(self, module, files, release):
"""
Updates cached versions of files in a list.
Returns list of updated files.
Release is just for compatibility and is ignored.
"""
if type(files) == types.StringType:
files = [files]
prevdir = abspath(os.curdir)
curdir = prevdir
# We need to checkout file by file as cvs will complain
# that it can't expand modules if any file is missing!
for f in files:
dst = self.cachedir+'/'+module+'/unstable/'+f
tmp = dirname(dst)
i = tmp.rfind('/')
cvsdir = tmp[i+1:]
newdir = tmp[:i]
if curdir != newdir:
if not isdir(newdir):
os.makedirs(newdir)
os.chdir(newdir)
curdir = newdir
cmd = ['cvs', '-z5', '-d', self.root, 'co', '-Pnd', cvsdir, module+'/'+f]
err, out = utils.cmd(cmd, self.verbose, True)
if 'U '+cvsdir+'/'+basename(f) in out or 'P '+cvsdir+'/'+basename(f) in out:
pass
elif err or out:
if 'cannot expand modules' in err or 'has disappeared' in err:
# Remove nonexisting file
if isfile(dst):
os.unlink(dst)
elif 'there is no repository' in err:
# Remove nonexisting directory
if isdir(tmp):
shutil.rmtree(tmp)
elif '? ' in err:
pass
else:
error = "cvs command crashed, error output:\n%s" % err
if out:
error+="\noutput:\n%s" % out
raise RuntimeError, error
os.chdir(prevdir)
def clearCache(self, module, release):
"""
clearCache(module, release)
Dummy function, for compatibility
"""
pass
def getItems(self):
"Returns list of items (module,release='unstable') in CVS Root"
if self.viewcvsurl:
return self.__getItemsFromViewCVS()
else:
return self.__getItemsFromCVS()
__linkre = re.compile('<a name="(.+)" href="/viewcvs/.+" title="Download ')
def __getItemsFromViewCVS(self):
"Returns list of items (module,release='unstable') parsed from ViewCVS"
items = set()
try:
sock = urllib2.urlopen(self.viewcvsurl)
try:
while True:
line = sock.readline()
if not line:
break
v = cvsDriver.__linkre.match(line)
if v:
items.add( (v.group(1),'unstable') )
finally:
sock.close()
except urllib2.URLError, e:
raise RuntimeError, "Unable to list items:\n%s" % e
return items
def __getItemsFromCVS(self):
"Returns list of (module,release='unstable') parsed from cvs co -c"
items = set()
cmd = ['cvs', '-z5', '-d', self.root, 'co -c']
err, out = utils.cmd(cmd, self.verbose, True)
if err:
error = "cvs command crashed, error output:\n%s" % err
if out:
error+="\noutput:\n%s" % out
raise RuntimeError, error
#
# Notes on tricky parsing...
#
#
# mname [ options ] dir [ files... ]
# mname [ options ] &module...
# mname -a aliases...
# mname -a !first-dir/sdir first-dir
#
# - If module has only other modules included, skip it
# and use includes instead (gnome, glibwww,...)
#
# - If module is included in some other module that is not
# skiped, skip it (like gtkmm-doc, included from gnome--).
# Module can still be included several times from other
# modules, like macros, included from many modules. If speed
# is important, it can be removed latter using decorator.
#
# - If module has alias, use it instead module
# (use gnome-system-monitor instead procmon)
# See BUG stated below about this!
#
amps = [] # list of modules included using & into some other
# module that is included and can be skiped latter
j = 0
buf = ''
lines = out.splitlines()[:-1]
while j < len(lines):
buf += lines[j].strip()
j+=1
# process and empty buffer if next line does not
# have leading space or this is the last line
if j == len(lines) or lines[j][0] != ' ':
line = buf.split()
try:
module = line[0]
mamps = []
i = 1
# Bug: Alias can be list of modules and can have list of
# directories to exclude from alias. I don't know if
# -d path or &module can be in list of aliases.
#
# This code will only work for simple aliases
# (like gnomemeeting -a ekiga) and simple aliases
# only are used in Gnome CVS
# use alias if it is defined
if line[i] == '-a':
module = line[i+1]
# don't del line[i] and del line[i+1] so module
# gets included (something will leftout)
else:
while i < len(line):
d = line[i]
# ignore module options and its argument
if d in ('-e', '-o', '-t', '-d', '-s'):
del line[i]; del line[i+1]
# includes some other module
elif d[0] == '&':
if not d in amps:
mamps.append(d[1:])
del line[i]
# next
else:
i+=1
# if something left out...
if len(line) > 1:
if not (module,'unstable') in items:
items.set((module,'unstable'))
amps += mamps
except ValueError, e:
print >> sys.stderr, " Warning: Invalid line in cvs co -c output, skipping\n Line: %s" % buf
pass
buf = ''
# Remove included modules
for m,r in items.copy():
if m in amps:
items.remove((m,r))
return items

View File

@ -1,717 +0,0 @@
# Copyright (c) 2006 Goran Rakic <grakic@devbase.net>.
#
# This file is part of libgo.
#
# libgo is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# libgo is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with libgo; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import sys, ftplib, os, md5, time, shutil, types, glob
from os.path import isfile, isdir, dirname, abspath, join
from datetime import datetime
from stat import ST_MTIME
import time
import utils
class gftpDriver:
"""
GNOME FTP driver - fetch files from stable releases from
tarballs on mirror of ftp.gnome.org
"""
def __init__(self, cachedir, stamp, verbose=False,
server='ftp.gnome.org', path='/pub/GNOME/'):
"""
gftpDriver(cachedir, stamp, [verbose, server, path]) where:
- cachedir is location of cache where to write files.
gdu and gtkdoc locators are using outputdir/.cache/gnome as
cachedir path. gftp will use cachedir/../gftp for archives cache
- stamp is a name sufix to use as stamp file. As more than one
locator can share same cachedir, they must use different
stamp files to know when files are updated from an archive
and if archive need to be extracted again. Stamp files are
written to cachedir/module/release/stamp-f[stamp].
- server is FTP server (default ftp.gnome.org)
- path is path to mirror of /pub/GNOME/ directory on server
- if verbose is True, gftp will print a line from time to time
Note: If you are using some other FTP server than default, make
sure that __dirparser method is working correctly!
"""
self.cachedir = cachedir
self.gftpcachedir = abspath(join(cachedir, '..', 'gftp'))
self.stamp = 'stamp-f' + stamp
self.verbose = verbose
if not isdir(self.gftpcachedir):
os.makedirs(self.gftpcachedir)
if not isdir(join(self.gftpcachedir, 'tmp')):
os.makedirs(join(self.gftpcachedir, 'tmp'))
self.server = server
self.path = path
self.sock = None
self.items = {} # {(module,release): datetime of last mod}
self.updated = set() # list of items (module, release) for which
# __updatearchive was called in this run
self.extracted = set() # list of (module,release) that should
# reflect what is in .cache/gftp/tmp
def __del__(self):
"Disconnects from FTP and clears gftp tmp cache"
self.__disconnect()
for module,release in self.extracted:
self.__clearprogress()
print >> sys.stderr, " Warning: Cleaning %s (%s release) from tmp cache" % (module,release)
self.clearCache(module, release)
def __connect(self):
"Open a connection to FTP server"
try:
self.sock = ftplib.FTP(self.server)
self.sock.login()
except ftplib.all_errors, e:
self.__clearprogress()
raise IOError, "Unable to open connection (%s)" % e
def __disconnect(self):
"""
Close FTP link, link is reastablished if it is needed.
It is called from desctructor if link is still active.
"""
if self.sock:
try:
self.sock.quit()
self.sock = None
except ftplib.all_errors:
pass
# Print fancy progress while browsing FTP
__progressactive = False
__progressprinted = False
__progressmsg = False
def __clearprogress(self):
if gftpDriver.__progressprinted:
gftpDriver.__progressprinted = False
print
def __startprogress(self, msg = None):
if msg:
gftpDriver.__progressmsg = True
print msg,
gftpDriver.__progressactive = True
def __stopprogress(self):
if gftpDriver.__progressmsg:
print "done"
else:
print
gftpDriver.__progressactive = False
def __printprogress(self):
if self.verbose and gftpDriver.__progressactive:
print '.',
gftpDriver.__progressprinted = True
__lstcounter = 0
def __nlistdir(self, path):
if self.verbose:
if not gftpDriver.__lstcounter % 15:
self.__printprogress()
gftpDriver.__lstcounter+=1
l = []
self.sock.cwd(path)
l = self.sock.nlst()
self.sock.cwd('/')
return l
def __listdir(self, path):
if self.verbose:
if not gftpDriver.__lstcounter % 15:
self.__printprogress()
gftpDriver.__lstcounter+=1
lines = []
self.sock.dir(path, lines.append)
return [self.__dirparser(line) for line in lines]
__months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
def __dirparser(self, line):
"""
Parse line returned from LIST call
If you are using some other FTP server, make sure
that __dirparser is working correctly!
"""
words = line.split(None, 8)
if len(words) < 6:
raise ValueError, "Directory listing line is too short (%s)"%line
filename = words[-1].lstrip()
i = filename.find(" -> ")
if i >= 0:
# words[0] had better start with 'l'...
filename = filename[:i]
isdir = words[0][0] == 'd'
words[-4] = gftpDriver.__months.index(words[-4])+1
return filename, isdir, words[-4:-1]
__default_starting_date = datetime(1970, 1, 1)
def __liststable(self, path, starting = None):
"""
Return list of stable major.minor releases. If starting is a release
string, or datetime object only newer, if any, releases are returned.
Latest stable release (if any) is appended to end of a list. List is
not ordered.
"""
releases = []
smaj = 0
smin = 0
date = gftpDriver.__default_starting_date
if type(starting) == types.StringType:
sg, sv = starting.split('.')
if sg.isdigit() and sv.isdigit():
smaj = int(sg)
smin = int(sv)
elif starting:
date = starting
lmaj = smaj
lmin = smin
for (f,d,t) in self.__listdir(path):
if d and '.' in f:
sg, sv = f.split('.')
if sg.isdigit() and sv.isdigit():
maj = int(sg)
min = int(sv)
if min%2==0 and maj>0:
if maj>smaj or (maj==smaj and min>=smin):
if ':' in t[-1]:
h, m = t[2].split(':')
y = time.gmtime()[0]
else:
h, m = 0,0
y = t[2]
# This is in UTC
ms = datetime(int(y),int(t[0]),
int(t[1]),int(h),int(m))
if ms >= date:
lmaj = maj
lmin = min
releases.append(f)
if releases:
# there must be at least one - smaj.smin and it is newest
releases.append(str(lmaj)+'.'+str(lmin))
return releases
def __isgreatermicro(self, old, new):
"Returns True if one micro release is greater then other"
inew = []
for n in new:
if not n.isdigit():
return False
inew.append(int(n))
if not old:
return True
iold = [int(o) for o in old]
pad = [0]*abs(len(old)-len(new))
if pad:
if len(old)>len(new):
inew += pad
else:
iold += pad
for i in range(len(inew)):
if inew[i] > iold[i]:
return True
return False
def __latestmicro(self, module, release):
"""
Get latest micro release and create self.items[(module,release)]
datetime object as last mod time of archive in listing
"""
latest, latest_time = None, None
path = self.path+'sources/'+module+'/'+release
try:
lines = self.__listdir(path)
except ftplib.all_errors+(ValueError,), e:
raise RuntimeError, "Unable to list archives (%s)" % e
for (f,d,t) in lines:
if f[-7:] == '.tar.gz':
version = f[f.rfind('-'):-7] # from last '-' to '.tar.gz'
m = version.split('.')[2:] # without major.minor
if self.__isgreatermicro(latest, m):
latest, latest_time = m, t
# There are no archives in directory
if latest == None:
raise RuntimeError, "There are no archives for this release"
else:
try:
t = latest_time
if ':' in t[-1]:
h, m = t[2].split(':')
y = time.gmtime()[0]
else:
h, m = 0,0
y = t[2]
# This is in UTC
ms = datetime(int(y),int(t[0]),int(t[1]),int(h),int(m))
except ValueError, e:
raise RuntimeError, "Failed creating last mod datetime: %s" % e
self.items[(module,release)] = ms
latest = ".".join(latest)
return latest
def __md5(self, filename):
"Calculate md5 sum of a file"
md5h = md5.new()
a = open(filename)
try:
while True:
buf = a.read(4096)
if not buf:
break
md5h.update(buf)
return md5h.hexdigest()
finally:
a.close()
def __getmd5(self, module, release, micro):
"""
Get MD5 hash for archive
Returns None in case of error.
"""
h = None
sarchive = module+'-'+release
if micro: sarchive += '.'+micro
f1 = self.path+'sources/'+module+'/'+release+'/'+sarchive
sarchive += '.tar.gz'
# 1: normal 2: scrollkeeper,gtk-engines 3: gtkhtml
for f in (f1+'.md5sum', f1+'.tar.gz.md5',f1+'.tar.md5sum'):
md5h = []
try:
self.sock.retrlines('RETR '+f, md5h.append)
except ftplib.error_perm:
pass # move to next
else:
for l in md5h:
try:
ha, fi = l.split()
except ValueError, e:
raise RuntimeError, "Invalid line in %s" % basename(f)
if sarchive == fi:
h = ha
if not h:
raise RuntimeError, "Archive missing from %s" % basename(f)
else:
return h
# still no luck?
if not h:
raise RuntimeError, "MD5 file missing"
def __updatearchive(self, module, release):
"Update archive in gftp cache"
try:
micro = self.__latestmicro(module, release)
except RuntimeError, e:
raise RuntimeError, "Unable to find latest micro: %s" % e
archive = module+'-'+release # module: gedit
sarchive = archive # release: 2.14
if micro: sarchive +='.'+micro # micro: 4
# extracted in cache, tmp archive, archive in cache
tmp = join(self.gftpcachedir, 'tmp', archive + '.tar.gz') # tmp/gedit-2.14.tar.gz
arc = join(self.gftpcachedir, archive + '.tar.gz') # gedit-2.14.tar.gz
refresh = True
ms = self.items[(module,release)]
if isfile(tmp):
print >> sys.stderr, " Warning: Archive %s.tar.gz is still in archives cache.\n There must be a crash during last update, refreshing" % sarchive
elif isfile(arc):
# Do we have up to date archive in gftp cache?
# syshackers told me not to depend on micro numbers
# and this make things easier (I don't need to remove old micro)
md = datetime.utcfromtimestamp(os.stat(arc)[ST_MTIME])
if md >= ms:
refresh = False
if refresh:
f = self.path+'sources/'+module+'/'+release+'/'+sarchive+'.tar.gz'
if self.verbose:
print "> RETR %s" % f
try:
a = open(tmp, 'wb')
self.sock.retrbinary('RETR '+f, a.write)
except:
a.close()
if isfile(tmp): os.unlink(tmp)
raise
else:
a.close()
try:
md5d = self.__md5(tmp)
md5s = self.__getmd5(module, release, micro)
except ftplib.all_errors+(RuntimeError,), e:
raise IOError, "Unable to get MD5 checksums: %s" % e
if md5d != md5s:
if isfile(tmp): os.unlink(tmp)
raise RuntimeError, "MD5 missmatch"
else:
os.rename(tmp, arc)
self.updated.add( (module,release) )
def __extractarchive(self, module, release):
"Tries to extract archive to tmp cache"
archive = module+'-'+release
dst = join(self.gftpcachedir, 'tmp', archive) # tmp/gedit-2.14
arc = join(self.gftpcachedir, archive + '.tar.gz') # gedit-2.14.tar.gz
os.makedirs(dst)
cmd = ['tar', '--strip-components=1', '-C', dst, '-xzf', arc]
error = utils.cmd(cmd, self.verbose)
if error:
# clean up so archive can be refetched
if isfile(arc): os.unlink(arc)
if isdir(dst): shutil.rmtree(dst, True)
raise RuntimeError, "tar command crashed, error output:\n%s"%error
# Write down that archive is extracted
# usefull when more than one locator is using same cache as
# we can check this file if we need to reextract archive again
stampdir = join(self.cachedir, module, release)
if not isdir(stampdir):
os.makedirs(stampdir)
utils.touch(join(stampdir, self.stamp))
# Add it so we can clean latter
self.extracted.add((module,release))
return 0
def clearCache(self, module, release):
"""
clearCache(module, release)
Clear extracted archive from gftp. If not before, cache is
cleared when gftp's destructor is called.
"""
if (module,release) in self.extracted:
d = join(self.gftpcachedir, 'tmp', module + '-' + release)
if isdir(d):
shutil.rmtree(d, True)
self.extracted.remove((module,release))
def getGnomeItems(self, sections = None, starting = None):
"""
getGnomeItems(sections = None, starting = None)
Returns a tuple of two dictionaries, both with GNOME release as a key
and list of items as values. ({gnome_release:[(module,release),...]}
First one is for past GNOME releases, and second is for latest
GNOME release where latest release is latest stable major.minor number
from /pub/GNOME/[sections]/ with all four, or just sections of interest
as sections.
If starting is a major.minor release (like '2.8') only latter or equal
releases are returned (what can be empty list). Starting can also be
a datetime object.
sections can be a list or tuple of GNOME sections (like 'admin' or
'desktop') of interest. There is a hack implemented for supporting
listing items from 'bindings' section.
"""
self.__startprogress(" Listing GNOME modules")
items = {}
lmaj = 0
lmin = 0
try:
self.__connect()
for section in sections:
# Don't accept 'sources' or 'teams'
# and about 'bindings', see FIXME comment below
if not section in ('admin', 'desktop', 'platform'):
print >> sys.stderr, " Warning: Browsing of %s is not supported." % section
continue
releases = self.__liststable(self.path + section, starting)
for release in releases[:-1]:
if not release in items:
items[release] = set()
if release == releases[-1]:
g, v = release.split('.')
maj = int(g)
min = int(v)
if maj>lmaj or (maj==lmaj and min>lmin):
lmaj = maj
lmin = min
# Find minor version of this section
path = self.path+section+'/'+release+'/'
latest = 0
for f in self.__nlistdir(path):
m = f[f.rfind('.')+1:]
if m.isdigit() and int(m) > latest:
latest = int(m)
path += release+'.'+str(latest)+'/sources/'
# FIXME: Currently there are no locator for bindings API
# references, and there are some problems with Perl
# bindings. They are way to many "hacks" so listing of
# bindings must be defined as another method
# Hack to support listing of bindings
# subsections = ['']
# if section == 'bindings':
# subsections = self.__nlistdir(path)
# subsections.remove('MD5SUMS-for-bz2')
# subsections.remove('MD5SUMS-for-gz')
#
# # Perl modules are not in /sources and they are using
# # "strange" version numbers. I can addsomething
# # like getPerlBindingsItems or make public general
# # methods like __listdir when locator for perldoc is
# # written...
# subsections.remove('perl')
#
# for subs in subsections:
# spath = path
# if subs: spath += subs
# # now use spath instead path in for loop
for f in self.__nlistdir(path):
if f[-7:] == '.tar.gz':
# gedit-2.14.3.tar.gz -> gedit-2.14
i = f.rfind('-')
module = f[:i]
ver = '.'.join(f[i+1:-7].split('.')[:2])
items[release].add((module,ver))
except ftplib.all_errors+(ValueError,), e:
self.__disconnect()
self.__stopprogress()
raise RuntimeError, "Unable to list GNOME modules: %s" % e
else:
self.__disconnect()
self.__stopprogress()
if lmaj > 0:
latest_release = str(lmaj)+'.'+str(lmin)
latest_items = {latest_release:items[latest_release]}
del items[latest_release]
else:
raise RuntimeError, "Unable to locate latest stable GNOME release"
return items, latest_items
def getItems(self, starting = None):
"""
getItems(starting = None)
Returns a tuple of two lists. One is list of stable items
(module,release) without latest stable releases and other is list of
latest stable releases of items.
If starting is datetime object, only releases after that time, if any,
are returned. Latest stable release (if any) is appended to the end.
Starting also can be major.minor release string.
"""
self.__startprogress(" Listing modules")
items = set()
latest_items = set()
try:
self.__connect()
for f in self.__nlistdir(self.path+'sources'):
releases = self.__liststable(self.path+'sources/'+f, starting)
for release in releases[:-1]:
if release == releases[-1]:
latest_items.add((f,release))
else:
items.add((f,release))
except ftplib.all_errors+(ValueError,), e:
self.__disconnect()
self.__stopprogress()
raise RuntimeError, "Unable to list modules: %s" % e
else:
self.__stopprogress()
self.__disconnect()
return items, latest_items
def getLastUpdate(self, module, files, release):
"""
getLastUpdate(self, module, files, release)
Return lastest update Unix timestamp of files in list.
If list is empty or all files are missing, 0 is returned.
"""
if type(files) == types.StringType:
files = [files]
last = 0
# /gedit-2.14/Makefile.am -> /gedit/2.14/Makefile.am
src = join(self.cachedir, module, release)
# we used copy2 to keep mod times from tarballs
for f in files:
if isfile(join(src, f)):
# FIXME: Is this UTC???
# Or it is in whatever timezone developer is using
ms = os.stat(join(src, f))[ST_MTIME]
if ms > last:
last = ms
return last
def updateFiles(self, module, files, release):
"""
updateFiles(module, files, release)
request list of files to be updated and stored in cache, returns a list
of updated files.
First, updateFiles check if item (module, release) is already extracted
in gftp tmp cache (item is included in self.extracted list) and if it
is not it will try to update it first checking if item not already
updated (included in self.updated) and if it is not, it will call
__updatearchive method. This method will check if archive on FTP
server is newer than archive in gftp cache (if it exists) and if it
is, method will fetch the archive, validate it against its MD5 sum
and move it to gftp cache. If MD5 check fails or archive can not be
fetched, it will try once more and then give up.
Next, updateFiles check if archive in gftp cache is newer then a stamp
of last update of sources in cache and if it is it will call
__extractarchive method to extract archive to gftp tmp cache, include
it in self.extracted list and update stamp file.
If archive is extracted, updateFiles will check for every file does it
need to be updated. If it does, file will be copied with preserving
last mod time to cache and included in list of updated files.
Extracted archive will be preserved in gftp cache until clearCache or
gftp's destructor is called.
"""
if type(files) == types.StringType:
files = [files]
archive = module + '-' + release
arc = join(self.gftpcachedir, archive + '.tar.gz')
src = join(self.gftpcachedir, 'tmp', archive)
dst = join(self.cachedir, module, release)
# If archive is not extracted...
if not (module, release) in self.extracted:
# If archive is still in tmp cache, than last update from it
# must failed. We don't know what locator failed, so we remove
# all stamps. Now, whichever it was, it will extract archive
# again next time. This will also include this request...
if isdir(src):
print >> sys.stderr, " Warning: Archive %s.tar.gz is still extracted in tmp cache (%s).\n There must be a crash during last extraction, cleaning" % (archive, src)
shutil.rmtree(src, True)
for stamp in glob.glob(join(self.cachedir, '*', '*', 'stamp-f*')):
os.unlink(stamp)
# We want to call __update archive only once for each item
if not (module, release) in self.updated:
try:
self.__connect()
self.__updatearchive(module,release)
except ftplib.all_errors+(RuntimeError,), e:
self.__disconnect()
raise RuntimeError, "Unable to update %s.tar.gz:\n%s" % (archive,e)
else:
self.__disconnect()
# If archive has newer timestamp than our stamp file, extract it
extract = True
# This is in local time
arcs = os.stat(arc)[ST_MTIME]
if isfile(join(dst, self.stamp)):
arcd = os.stat(join(dst, self.stamp))[ST_MTIME]
if arcd >= arcs:
extract = False
if extract:
try:
self.__extractarchive(module,release)
except (IOError,RuntimeError), e:
raise RuntimeError, "Unable to extract %s.tar.gz:\n%s" % (archive,e)
# If it is extracted, update files
if (module, release) in self.extracted:
# Dummy check, src/* still can be damaged, but who cares :)
if not isdir(src):
self.extracted.remove( (module,release) )
raise RuntimeError, "Module %s (%s release) is included in list of extracted archives, but directory is missing from tmp cache." % (module,release)
for g in files:
founded = glob.glob(join(src, g))
existing = glob.glob(join(dst, g))
for f in founded:
f = f[len(src):].lstrip(os.sep)
update = True
# See FIXME not on getLastUpdate
# Is this UTC or it is in dev's timezone?
ms = os.stat(join(src, f))[ST_MTIME]
if isfile(join(dst, f)):
md = os.stat(join(dst, f))[ST_MTIME]
if md > ms:
print >> sys.stderr, " Warning: Newer timestamp in source than in destination, update forced\n Module %s, file: %s" % (module,f)
elif md == ms:
update = False
if update:
try:
if not isdir(join(dst, dirname(f))_:
os.makedirs(join(dst, dirname(f)))
shutil.copy2(join(src, f), join(dst, f))
except IOError, e:
if isfile(join(dst, f)):
os.unlink(join(dst, f))
raise
# Remove nonexisting file, won't prune directories...
for f in existing:
f = f[len(dst):].lstrip(os.sep)
if join(src, f) not in founded:
os.unlink(join(dst, f))

View File

@ -1,431 +0,0 @@
# Copyright (c) 2006 Goran Rakic <grakic@devbase.net>.
#
# This file is part of libgo.
#
# libgo is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# libgo is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with libgo; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import sys, os, time, shutil, types, glob
from os.path import isfile, isdir, dirname, abspath, join
from datetime import datetime
from stat import ST_MTIME
import time
import utils
class gftpimgDriver:
"""
GNOME FTP image driver - fetch files from local mirror of
ftp.gnome.org/pub/GNOME directory. Does not cache
archives, just extract them when files are
requested. Use modtime of a directory to check if
archive need to be reextracted.
"""
def __init__(self, cachedir, location, stamp, verbose=False):
"""
gftpimgDriver(cachedir, location, stamp, [verbose]) where:
- cachedir is location of cache where to write files.
gdu and gtkdoc locators are using outputdir/.cache/gnome as
cachedir path. gftpimg will use cachedir/../gftpimg as tmp
cache for extracting files
- location where image of /pub/GNOME directory from
ftp.gnome.org is located
- stamp is a name sufix to use as stamp file. As more than one
locator can share same cachedir, they must use different
stamp files to know when files are updated from an archive
and if archive need to be extracted again. Stamp files are
written to cachedir/module/release/stamp-f[stamp].
- if verbose is True, gftpimg will print a line from time to time
"""
self.cachedir = cachedir
self.gftpimgcachedir = abspath(join(cachedir, '..', 'gftpimg'))
self.location = location
self.stamp = 'stamp-f'+stamp
self.verbose = verbose
if not isdir(self.location):
raise ValueError, "Source location is not a directory." % location
self.extracted = set() # list of (module,release) that should
# reflect what is in .cache/gftp/tmp
def __del__(self):
"clears tmp cache"
for module,release in self.extracted:
print >> sys.stderr, " Warning: Cleaning %s (%s release) from tmp cache" % (module,release)
self.clearCache(module, release)
__default_starting_date = datetime(1970, 1, 1)
def __liststable(self, path, starting = None):
"""
Return list of stable major.minor releases. If starting is a release
string, or datetime object only newer, if any, releases are returned.
Latest stable release (if any) is appended to end of a list. List is
not ordered.
"""
releases = []
smaj = 0
smin = 0
date = gftpimgDriver.__default_starting_date
if type(starting) == types.StringType:
sg, sv = starting.split('.')
if sg.isdigit() and sv.isdigit():
smaj = int(sg)
smin = int(sv)
elif starting:
date = starting
lmaj = smaj
lmin = smin
for f in os.listdir(path):
if isdir(join(path, f)) and '.' in f:
sg, sv = f.split('.')
if sg.isdigit() and sv.isdigit():
maj = int(sg)
min = int(sv)
if min%2==0 and maj>0:
if maj>smaj or (maj==smaj and min>=smin):
# Create in UTC
ms = os.stat(join(path, f))[ST_MTIME]
ms = datetime.fromtimestamp(ms-time.timezone)
if ms >= date:
lmaj = maj
lmin = min
releases.append(f)
if releases:
# there must be at least one - smaj.smin and it is newest
releases.append(str(lmaj)+'.'+str(lmin))
return releases
def __isgreatermicro(self, old, new):
"Returns True if one micro release is greater then other"
inew = []
for n in new:
if not n.isdigit():
return False
inew.append(int(n))
if not old:
return True
iold = [int(o) for o in old]
pad = [0]*abs(len(old)-len(new))
if pad:
if len(old)>len(new):
inew += pad
else:
iold += pad
for i in range(len(inew)):
if inew[i] > iold[i]:
return True
return False
def __latestmicro(self, module, release):
"Get latest micro release"
latest = None
path = join(self.location, 'sources', module, release)
try:
lines = os.listdir(path)
except IOError, e:
raise RuntimeError, "Unable to list archives (%s)" % e
for f in lines:
if isfile(join(path, f)) and f[-7:] == '.tar.gz':
version = f[f.rfind('-'):-7] # from last '-' to '.tar.gz'
m = version.split('.')[2:] # without major.minor
if self.__isgreatermicro(latest, m):
latest = m
if latest == None:
raise RuntimeError, "There are no archives for this release"
latest = '.'.join(latest)
return latest
def __extractarchive(self, module, release, micro):
"Tries to extract archive to tmp cache"
archive = module+'-'+release
dst = join(self.gftpimgcachedir, module, release)
if micro: archive += '.'+micro
arc = join(self.location, 'sources', module, release, archive+'.tar.gz')
os.makedirs(dst)
cmd = ['tar', '--strip-components=1', '-C', dst, '-xzf', arc]
error = utils.cmd(cmd, self.verbose)
if error:
if isdir(dst):
shutil.rmtree(dst, True)
raise RuntimeError, "tar command crashed, error output:\n%s"%error
# Write down that archive is extracted
# usefull when more than one locator is using same cache as
# we can check this file if we need to reextract archive again
stampdir = join(self.cachedir, module, release)
if not isdir(stampdir):
os.makedirs(stampdir)
utils.touch(join(stampdir, self.stamp))
# Add it so we can clean latter
self.extracted.add((module, release))
return 0
def clearCache(self, module, release):
"""
clearCache(module, release)
Clear extracted archive from gftpimg cache.
If not before, cache is cleared when destructor is called.
"""
if (module,release) in self.extracted:
d = join(self.gftpimgcachedir, module, release)
if isdir(d):
shutil.rmtree(d, True)
self.extracted.remove((module,release))
def getGnomeItems(self, sections = None, starting = None):
"""
getGnomeItems(sections = None, starting = None)
Returns a tuple of two dictionaries, both with GNOME release as a key
and list of items as values. ({gnome_release:[(module,release),...]}
First one is for past GNOME releases, and second is for latest
GNOME release where latest release is latest stable major.minor number
from /pub/GNOME/[sections]/ with all four, or just sections of interest
as sections.
If starting is a major.minor release (like '2.8') only latter or equal
releases are returned (what can be empty list). Starting can also be
a datetime object.
sections can be a list or tuple of GNOME sections (like 'admin' or
'desktop') of interest. There is a hack implemented for supporting
listing items from 'bindings' section.
"""
items = {}
lmaj = 0
lmin = 0
try:
for section in sections:
# Don't accept 'sources' or 'teams', and about 'bindings', see
# FIXME comment in getGnomeItems method of gftp driver
if not section in ('admin', 'desktop', 'platform'):
print >> sys.stderr, " Warning: Browsing of %s is not supported." % section
continue
releases = self.__liststable(join(self.location, section), starting)
for release in releases[:-1]:
if not release in items:
items[release] = set()
if release == releases[-1]:
g, v = release.split('.')
maj = int(g)
min = int(v)
if maj>lmaj or (maj==lmaj and min>lmin):
lmaj = maj
lmin = min
# Find minor version of this section
path = join(self.location, section, release)
latest = 0
for f in os.listdir(path):
if isdir(join(path, f)):
m = f[f.rfind('.')+1:]
if m.isdigit() and int(m) > latest:
latest = int(m)
path = join(path, release + '.' + str(latest), 'sources')
for f in os.listdir(path):
if isfile(join(path, f)) and f[-7:] == '.tar.gz':
# gedit-2.14.3.tar.gz -> gedit-2.14
i = f.rfind('-')
module = f[:i]
ver = '.'.join(f[i+1:-7].split('.')[:2])
items[release].add((module,ver))
except IOError, e:
raise RuntimeError, "Unable to list GNOME modules: %s" % e
if lmaj > 0:
latest_release = str(lmaj)+'.'+str(lmin)
latest_items = {latest_release:items[latest_release]}
del items[latest_release]
else:
raise RuntimeError, "Unable to locate latest stable GNOME release"
return items, latest_items
def getItems(self, starting = None):
"""
getItems(starting = None)
Returns a tuple of two lists. One is list of stable items
(module,release) without latest stable releases and other is list of
latest stable releases of items.
If starting is datetime object, only releases after that time, if any,
are returned. Latest stable release (if any) is appended to the end.
Starting also can be major.minor release string.
"""
items = set()
latest_items = set()
try:
for f in os.listdir(join(self.location, 'sources')):
if not isdir(join(self.location, 'sources', f)):
continue
releases=self.__liststable(join(self.location, 'sources', f), starting)
for release in releases[:-1]:
if release == releases[-1]:
latest_items.add((f, release))
else:
items.add((f, release))
except IOError, e:
raise RuntimeError, "Unable to list modules: %s" % e
return items, latest_items
def getLastUpdate(self, module, files, release):
"""
getLastUpdate(self, module, files, release)
Return lastest update Unix timestamp of files in list.
If list is empty or all files are missing, 0 is returned.
"""
if type(files) == types.StringType:
files = [files]
last = 0
# /gedit-2.14/Makefile.am -> /gedit/2.14/Makefile.am
src = join(self.cachedir, module, release)
# we used copy2 to keep mod times from tarballs
for f in files:
if isfile(join(src, f)):
# FIXME: Is this UTC???
# Or it is in whatever timezone developer is using
ms = os.stat(join(src, f))[ST_MTIME]
if ms > last:
last = ms
return last
def updateFiles(self, module, files, release):
"""
updateFiles(module, files, release)
request list of files to be updated and stored in cache, returns a list
of updated files.
First, updateFiles check if item (module, release) is already extracted
in gftpimg tmp cache (is included in self.extracted list) and if it
is not it will check if archive in gftp cache is newer then a stamp
of last update of sources in cache and if it is it will call
__extractarchive method to extract archive to gftpimg tmp cache and
include it in self.extracted list and update stamp file.
If archive is extracted, updateFiles will check for every file does it
need to be updated. If it does, file will be copied with preserving
last mod time to cache and included in list of updated files.
Extracted archive will be preserved in gftpimg cache until clearCache
or destructor is called.
"""
if type(files) == types.StringType:
files = [files]
try:
micro = self.__latestmicro(module, release)
except RuntimeError, e:
raise RuntimeError, "Unable to find latest micro: %s" % e
dst = join(self.cachedir, module, release)
archive = module+'-'+release
src = join(self.gftpimgcachedir, module, release)
if micro: archive+= '.' + micro
arc = join(self.location, 'sources', module, release, archive + '.tar.gz')
# If archive is not extracted...
if not (module, release) in self.extracted:
# If archive is still in tmp cache, than last update from it
# must failed. We don't know what locator failed, so we remove
# all stamps. Now, whichever it was, it will extract archive
# again next time. This will also include this request...
if isdir(src):
print >> sys.stderr, " Warning: Archive %s.tar.gz is still extracted in tmp cache (%s).\n There must be a crash during last extraction, cleaning" % (archive, src)
shutil.rmtree(src, True)
for stamp in glob.glob(join(self.cachedir, '*', '*', 'stamp-f*')):
os.unlink(stamp)
# If archive has newer timestamp than our stamp file, extract it
extract = True
# This is in local time
arcs = os.stat(arc)[ST_MTIME]
if isfile(join(dst, self.stamp)):
arcd = os.stat(join(dst, self.stamp))[ST_MTIME]
if arcd >= arcs:
extract = False
if extract:
try:
self.__extractarchive(module,release,micro)
except (IOError,RuntimeError), e:
raise RuntimeError, "Unable to extract %s.tar.gz:\n%s" % (archive, e)
# If it is extracted, update files
if (module, release) in self.extracted:
# Dummy check, src/* still can be damaged, but who cares :)
if not isdir(src):
self.extracted.remove( (module,release) )
raise RuntimeError, "Module %s (%s release) is included in list of extracted archives, but directory is missing from tmp cache." % (module,release)
for g in files:
founded = glob.glob(join(src, g))
existing = glob.glob(join(dst, g))
for f in founded:
f = f[len(src):].lstrip(os.sep)
update = True
# See FIXME not on getLastUpdate
# Is this UTC or it is in dev's timezone?
ms = os.stat(join(src, f))[ST_MTIME]
if isfile(join(dst, f)):
md = os.stat(join(dst, f))[ST_MTIME]
if md > ms:
print >> sys.stderr, " Warning: Newer timestamp in source than in destination, update forced\n Module %s, file: %s" % (module,f)
elif md == ms:
update = False
if update:
try:
if not isdir(join(dst, dirname(f))):
os.makedirs(join(dst, dirname(f)))
shutil.copy2(join(src, f), join(dst, f))
except IOError, e:
if isfile(join(dst, f)):
os.unlink(join(dst, f))
raise
# Remove nonexisting file, won't prune directories...
for f in existing:
f = f[len(dst):].lstrip(os.sep)
if join(src, f) not in founded:
os.unlink(join(dst, f))

View File

@ -1,156 +0,0 @@
# Copyright (c) 2006 Goran Rakic <grakic@devbase.net>.
#
# This file is part of libgo.
#
# libgo is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# libgo is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with libgo; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import sys, types, time, os, glob
from os.path import isfile, isdir, dirname, abspath, join
from stat import ST_MTIME
import shutil
import utils
class jhbuildDriver:
"""
jhbuild driver - Pull files from static jhbuild's image of HEAD/trunk
branch of GNOME version control system
Interface is fully compatible with SVN/CVS drivers
"""
def __init__(self, cachedir, location):
"""
jhbuildDriver(cachedir, location) where:
- cachedir is location of cache where to write files.
gdu and gtkdoc locators are using outputdir/.cache/gnome as
cachedir path.
- location is location of jhbuild checkout dir
Note: jhbuild driver will use last modification timestamps as last
update of a document. Indexes can be very odd if you have
a new CVS image.
"""
self.location = abspath(location)
self.cachedir = cachedir
if not isdir(self.location):
raise ValueError, "Source location is not a directory." % location
print >> sys.stderr, """
Warning: jhbuild driver will use last modification timestamps as last update
of a document. Indexes can be very odd if you have a new image.
"""
def getLastUpdate(self, module, files, release):
"""
Return lastest update Unix timestamp of files in list.
If list is empty or all files are missing, 0 is returned.
Release is just for compatibility and is ignored.
"""
if type(files) == types.StringType:
files = [files]
last = 0
src = join(self.location, module)
for f in files:
if isfile(join(src, f)):
# This is in local time, convert to UTC
ms = os.stat(join(src, f))[ST_MTIME]
if ms > last:
last = ms
return last-time.timezone
def updateFiles(self, module, files, release):
"""
Update cached versions of files in a list
Return list of updated files
Release is just for compatibility and is ignored.
"""
if type(files) == types.StringType:
files = [files]
# ms > md so if md does not exist, it will be updated
src = join(self.location, module); ms = 1
dst = join(self.cachedir, module, 'unstable'); md = 0
for g in files:
founded = glob.glob(join(src, g))
existing = glob.glob(join(dst, g))
for f in founded:
f = f[len(src):].lstrip(os.sep)
update = True
# See FIXME not on getLastUpdate
# Is this UTC or it is in dev's timezone?
ms = os.stat(join(src, f))[ST_MTIME]
if isfile(join(dst, f)):
md = os.stat(join(dst, f))[ST_MTIME]
if md > ms:
print >> sys.stderr, " Warning: Newer timestamp in source than in destination, update forced\n Module %s, file: %s" % (module,f)
elif md == ms:
update = False
if update:
try:
if not isdir(join(dst, dirname(f))):
os.makedirs(join(dst, dirname(f)))
shutil.copy2(join(src, f), join(dst, f))
except IOError, e:
if isfile(join(dst, f)):
os.unlink(join(dst, f))
raise
# Remove nonexisting file, won't prune directories...
for f in existing:
f = f[len(dst):].lstrip(os.sep)
if join(src, f) not in founded:
os.unlink(join(dst, f))
def clearCache(self, module, release):
"""
clearCache(module, release)
Dummy function, for compatibility
"""
pass
def getItems(self):
"Returns list of items (module,'unstable')"
svnroot = '://svn.gnome.org/svn/'
dirs = []
try:
listing = os.listdir(self.location)
for l in listing:
if l[0] == '.': continue
if isdir(join(self.location, l)): dirs.append(l)
except IOError, e:
raise RuntimeError, "Unable to list modules: %s" % e
items = set()
for d in dirs:
if isfile(join(self.location, d, '.svn', 'entries')):
try:
uri = utils.svn_get_uri(join(self.location, d))
if svnroot in uri:
items.add( (d,'unstable') )
except IOError, e:
raise RuntimeError, "Unable to determine SVN URI in %s: %s" % (d, e)
return items

View File

@ -1,187 +0,0 @@
# Copyright (c) 2006 Goran Rakic <grakic@devbase.net>.
#
# This file is part of libgo.
#
# libgo is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# libgo is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with libgo; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import sys, types, os, urllib2, re, time, locale
from os.path import isfile, isdir, dirname
from stat import ST_MTIME
from calendar import timegm
class viewcvsDriver:
"ViewCVS driver - use ViewCVS to access files in CVS root via HTTP"
# Dictionary mapping CVS name to CVS root and ViewCVS url
# CVS root can be none and is ignored (present for compatibility)
roots = {
'gnome': (None, 'http://cvs.gnome.org/viewcvs/')
}
def __init__(self, cachedir, name, verbose = False):
"""
viewcvsDriver(cachedir, name, [verbose]) where:
- cachedir is location of cache where to write files.
gdu and gtkdoc locators are using outputdir/.cache/gnome as
cachedir path.
- name is one of keys from viewcvsDriver.roots and that is a
dictrionary mapping name to (None, url) where url is url
of ViewCVS to use.
- if verbose is True, driver will print a line from time to time
Note: If you are using some other CVS server than GNOME's, update
content of viewcvsDriver.roots dictionary!
"""
if not name in viewcvsDriver.roots:
raise ValueError, "Unknown cvs name %s\nPlease update viewcvsDriver.roots before initializing viewcvs driver." % name
self.cachedir = cachedir
whatever, self.viewcvsurl = viewcvsDriver.roots[name]
self.verbose = verbose
self.files = {}
def getLastUpdate(self, module, files, release):
"""
Return lastest update Unix timestamp of files in list.
If list is empty or all files are missing, 0 is returned.
Release is just for compatibility and is ignored.
"""
last = 0
if type(files) == types.StringType:
files = [files]
for f in files:
if (module,f) in self.files and self.files[(module,f)] > last:
last = self.files[(module,f)]
return last
__lmre = re.compile('^<br><i>([a-zA-Z]{3}) ([a-zA-Z]{3})[ ]+([0-9]{1,2}) ([0-9]{2}):([0-9]{2}):([0-9]{2}) ([0-9]{4}) UTC</i> \(.+\) by <i>.+</i>$')
__w = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
__m = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
def updateFiles(self, module, files, release):
"""
Updates cached versions of files in a list.
Returns list of updated files.
Release is just for compatibility and is ignored.
"""
if type(files) == types.StringType:
files = [files]
for f in files:
dst = self.cachedir+'/'+module+'/unstable/'+f
url = self.viewcvsurl+'*checkout*/'+module+'/'+f
update = False
if not (module,f) in self.files:
modurl = self.viewcvsurl+module+'/'+f+'?view=markup'
try:
if self.verbose:
print "> MODTIME %s" % module+'/'+f
sock = urllib2.urlopen(modurl)
try:
while True:
line = sock.readline()
if not line:
break
v = viewcvsDriver.__lmre.match(line)
if v:
date = v.group(1)+' '+v.group(2)+' '+v.group(3)+' '+v.group(4)+':'+v.group(5)+':'+v.group(6)+' '+v.group(7)
locale.setlocale(locale.LC_ALL, 'C')
try:
# This is in UTC
ms = timegm(time.strptime(date))
except ValueError, e:
locale.resetlocale(locale.LC_ALL)
raise RuntimeError,"Invalid last mod date (%s): %s" % (date, e)
else:
locale.resetlocale(locale.LC_ALL)
self.files[(module,f)] = ms
break
finally:
sock.close()
except urllib2.URLError, e:
if e.code == 404:
# Remove nonexisting file, won't prune directories
if isfile(dst):
os.unlink(dst)
else:
raise RuntimeError, "Failed getting last mod date for %s: %s" % (f,e)
else:
if not (module, f) in self.files:
raise RuntimeError, "Last mod date for %s not found" % f
else:
if isfile(dst):
# This in local time, convert it to UTC
md = os.stat(dst)[ST_MTIME]-time.timezone
if ms > md:
update = True
else:
update = True
if update:
if not isdir(dirname(dst)):
os.makedirs(dirname(dst))
try:
if self.verbose:
print "> GET %s" % module+'/'+f
sock = urllib2.urlopen(url)
a = open(dst,'w')
try:
data = sock.read()
a.write(data)
finally:
sock.close()
a.close()
except urllib2.URLError, e:
raise IOError, "Failed reading %s\n%s" % (url,e)
def clearCache(self, module, release):
"""
clearCache(module, release)
Dummy function, for compatibility
"""
pass
__linkre = re.compile('<a name="(.+)" href="/viewcvs/.+" title="Download ')
def getItems(self):
"Returns list of items (module,release='unstable') parsed from ViewCVS"
items = set()
try:
sock = urllib2.urlopen(self.viewcvsurl)
try:
while True:
line = sock.readline()
if not line:
break
v = viewcvsDriver.__linkre.match(line)
if v:
items.add( (v.group(1),'unstable') )
finally:
sock.close()
except urllib2.URLError, e:
raise RuntimeError, "Unable to open URL:\n%s" % e
return items

View File

@ -1,62 +0,0 @@
#!/usr/bin/python
import sys, os, os.path, ftplib
# Find what is missing in local ftp image (when there is a link
# from one GNOME release, but archive is not in sources) and
# output list of links for download
items = []
path = os.path.abspath(sys.argv[1])
for s in ('desktop','admin','platform'):
count = 0
for root, dirs, files in os.walk(os.path.join(path,s)):
for line in files:
if line[-7:] == '.tar.gz':
i = line.rfind('-')
j = line[i+1:-7].split('.')
d = os.path.join(path,'sources',line[:i],j[0]+'.'+j[1],line)
if not os.path.isfile(d):
link = d.replace(path+'/sources','/pub/GNOME/sources')
dest = d
items.append( (link,dest) )
count += 1
print " ",
if count == 0:
print "No items",
elif count == 1:
print "1 item",
else:
print count,"items",
print "in section",s
print
for link, dest in items:
print 'ftp://ftp.gnome.org'+link
print
for link, dest in items:
print 'mv',os.path.basename(dest),dest
sys.exit(1)
total = len(items)
current = 1
for link,dest in items:
dir = os.path.dirname(dest)
if not os.path.isdir(dir):
os.makedirs(dir)
sock = ftplib.FTP('ftp.gnome.org')
sock.login()
f = open('tmp','w')
print "%s/%s > RETR %s" % (current,total,link)
sock.retrbinary('RETR '+link, f.write)
f.close()
sock.quit()
os.rename('tmp', dest)
current += 1

View File

@ -1,243 +0,0 @@
#!/usr/bin/python
# Copyright (c) 2006 Goran Rakic <grakic@devbase.net>.
#
# This file is part of libgo.
#
# libgo is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# libgo is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with libgo; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Functions for creating indexes
import docobj
import os
import os.path
import re
import sys
import xml.dom.minidom
import locale
import shutil
import subprocess
_ = lambda x: x
blacklist = ['agave', 'alexandria', 'galeon', 'fdl', 'gpl', 'lgpl']
xslt = os.path.join(os.path.abspath(os.path.dirname(__file__)),
'locators', 'common', 'indexes.xsl')
class Documentation(object):
def xml_print(self, xmldoc, idx):
doc = xmldoc.createElement('document')
doc.setAttribute('url', self.url)
doc.setAttribute('title', self.title)
doc.setAttribute('module', self.module)
doc.setAttribute('filepath', self.filepath)
doc.setAttribute('version', self.version)
doc.setAttribute('lang', self.lang)
doc.setAttribute('section', self.section)
if self.abstract:
doc.setAttribute('abstract', self.abstract)
idx.appendChild(doc)
def getNodeTextChild(node):
rc = ''
for textnode in node.childNodes:
if textnode.nodeType == textnode.TEXT_NODE:
rc = rc + textnode.data
return rc.encode('utf-8')
docs = {} # indexed on module
languages = {}
def create_indexes(docobjs, outputdir):
"Create XHTML indexes in outputdir"
if not outputdir.endswith('/'):
outputdir += '/'
impl = xml.dom.minidom.getDOMImplementation()
xmldoc = impl.createDocument(None, "indexes", None)
out = xmldoc.documentElement
for base, dirs, filenames in os.walk(outputdir):
if not 'index.xml.en' in filenames:
continue
if base == '.':
continue
try:
ign, module, version = base.rsplit(os.path.sep, 2)
section = ign[len(outputdir)-1:].lstrip(os.path.sep)
if section: section += os.path.sep
except ValueError:
continue
if module in blacklist:
continue
for filename in filenames:
if not filename.startswith('index.xml.'):
continue
doc = Documentation()
doc.lang = filename.rsplit('.')[-1]
doc.filepath = os.path.join(base, filename)
doc.module = module
doc.version = version
doc.section = section
doc.url = doc.filepath[len(outputdir)-1:].replace('.xml', '.html')
content = file(doc.filepath).read()
dom = xml.dom.minidom.parseString(content)
try:
doc.title = getNodeTextChild(dom.getElementsByTagName('title')[0])
except IndexError:
print 'failed to get title for', doc.module, doc.lang
continue
try:
doc.abstract = getNodeTextChild(dom.getElementsByTagName('abstract')[0])
except IndexError:
doc.abstract = None
if not docs.has_key((section, module)):
docs[(section, module)] = []
docs[(section, module)].append(doc)
languages[doc.lang] = True
def cmpv(x, y):
return cmp(x.version.split('.'), y.version.split('.'))
for lang in languages.keys():
idx = xmldoc.createElement('index')
idx.setAttribute('lang', lang)
out.appendChild(idx)
documents = []
documents_en = []
for (section, module) in docs.keys():
versions = docs[(section, module)]
versions.sort(cmpv)
in_lang = [x for x in versions if x.lang == lang]
if in_lang:
if in_lang[-1].version != versions[-1].version:
# latest version in this language is older than in English,
# include it as is nevertheless
pass
d = in_lang[-1]
documents.append(d)
else:
# not available in this language, fallback to English
d = [x for x in versions if x.lang == 'en'][-1]
documents_en.append(d)
try:
# will fail most of the time, it requires lang -> locale mapping
locale.setlocale(locale.LC_COLLATE, lang)
except locale.Error:
pass
documents.sort(lambda x,y: locale.strcoll(x.title, y.title))
documents_en.sort(lambda x,y: locale.strcoll(x.title, y.title))
for d in documents:
d.xml_print(xmldoc, idx)
for d in documents_en:
d.xml_print(xmldoc, idx)
for (section, module) in docs.keys():
langs = {}
versions = docs[(section, module)]
versions.sort(cmpv)
for v in versions:
langs[v.lang] = True
for lang in langs.keys():
m = xmldoc.createElement('module')
m.setAttribute('lang', lang)
m.setAttribute('modulename', module)
m.setAttribute('section', section)
out.appendChild(m)
in_lang = [x for x in versions if x.lang == lang]
in_lang.reverse()
if in_lang[0].version != 'unstable' or len(in_lang) < 2:
in_lang[0].xml_print(xmldoc, m)
del in_lang[0]
else:
in_lang[1].xml_print(xmldoc, m)
del in_lang[1]
if in_lang:
pass
vers = xmldoc.createElement('versions')
m.appendChild(vers)
for d in in_lang:
ver = xmldoc.createElement('version')
text = xmldoc.createTextNode(d.version)
ver.appendChild(text)
vers.appendChild(ver)
xlangs = xmldoc.createElement('langs')
m.appendChild(xlangs)
for l in langs.keys():
lang = xmldoc.createElement('lang')
text = xmldoc.createTextNode(l)
lang.appendChild(text)
xlangs.appendChild(lang)
# Create them HTML files
cmd = ['xsltproc', '--nonet', '--xinclude', '--output', outputdir, xslt, '-']
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True)
p.stdin.write(xmldoc.toxml())
p.stdin.flush()
p.stdin.close()
p.wait()
print p.stdout.read()
f = open(os.path.join(outputdir, "debug.xml"), "w+")
f.write(xmldoc.toprettyxml())
f.close()
if __name__ == '__main__':
try:
outputdir = sys.argv[1]
except IndexError:
print >> sys.stderr, 'Usage: indexutils.py OUTPUTDIR'
sys.exit(1)
output_skin_dir = os.path.join(outputdir, 'skin')
if os.path.isdir(output_skin_dir):
shutil.rmtree(output_skin_dir)
shutil.copytree(os.path.join(os.path.dirname(__file__), 'skin'), output_skin_dir)
create_indexes(None, outputdir)

191
libgo
View File

@ -1,191 +0,0 @@
#!/usr/bin/python -u
# Copyright (c) 2006 Goran Rakic <grakic@devbase.net>.
#
# This file is part of libgo.
#
# libgo is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# libgo is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with libgo; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# libgo -- generate library.gnome.org contents
VERSION = "0.1.9"
import sys, getopt, re, traceback
from os.path import abspath, isdir, basename, dirname, join
from glob import glob
import shutil
import indexutils
from utils import load_decorators
#
# Note about command line args for locators:
#
# If you want to add new command line option for your locator you need to
# update usage text below, update getopt.getopt call to include your option,
# update locargs dictionary to create new variable and then update opt,args
# iteration to set its value if cmd line option is used. On locargs
# dictionary updating, do not add additional locators to ('*') key, and if you
# ever add additional locator to some other tuple please make an update of
# every usage of the old tuple in opt, arg iteration or somewhere else in
# code before loading locators
#
def usage(display_help = False):
"Display usage/help info"
print >> sys.stderr, "Usage: %s [OPTIONS] OUTPUTDIR" % (sys.argv[0])
if(display_help):
print >> sys.stderr, """
OPTIONS may be some of:
Driver selection:
-j --jhbuild = LOCATION Location of local jhbuild's image to be
used instead GNOME CVS/SVN server (note
that you should use lastest moduleset,
and still some modules can be missing)
-f --ftp = LOCATION Location of local GNOME ftp image to be
used instead ftp.gnome.org/pub/GNOME
-c --cvs Request usage of CVS instead of SVN
-u --viewcvs Use ViewCVS and HTTP for file access
Please, do not use different drivers with same output directory! CVS driver
expect files not to change (what jhbuild/viewcvs driver will do), and using
ftp and ftpimg driver in the same directory three, will mess up stamp files.
Even using -r option won't help then.
Usefull options:
-r --rebuild-all Rebuild everything
-V --verbose Print external commands before executing
And the usual ones:
-v --version Output version of the libgo-generate program
-h --help Output this message
"""
sys.exit(1)
locargs = { # Read a note above before changing!!!
'*' : { # pass to all locators
'output_location' : '', # outputdir
'cache_location' : '', # outputdir/.cache/locatorname
'rebuild_all' : False,
'verbose' : False,
},
('gdu','gtkdoc') : { # pass only to listed locators
'jhbuild_location' :None,
'gftpimg_location' :None,
'forceCVS' :False,
'forceViewCVS' :False
}
}
# Process command line arguments
args = sys.argv[1:]
try: opts,args = getopt.getopt(args,'j:f:curVvh',['jhbuild=', 'ftp=', 'cvs', 'viewcvs', 'rebuild-all', 'verbose', 'version', 'help'])
except getopt.GetoptError: usage(True)
for opt, arg in opts:
if opt in ('-j', '--jhbuild'):
locargs[('gdu','gtkdoc')]['jhbuild_location'] = arg
elif opt in ('-f', '--ftp'):
locargs[('gdu','gtkdoc')]['gftpimg_location'] = arg
elif opt in ('-c', '--cvs'):
locargs[('gdu','gtkdoc')]['forceCVS'] = True
elif opt in ('-u', '--viewcvs'):
locargs[('gdu','gtkdoc')]['forceViewCVS'] = True
elif opt in ('-r', '--rebuild-all'):
locargs['*']['rebuild_all'] = True
elif opt in ('-V', '--verbose'):
locargs['*']['verbose'] = True
elif opt in ('-v', '--version'):
print VERSION
sys.exit(0)
elif opt in ('-h', '--help'):
usage(True)
# Last argument must be an output dir
if len(args)>0: outputdir = args[-1]
else: usage()
# Check if output dir exists
outputdir = abspath(outputdir)
locargs['*']['cache_location'] = join(outputdir, '.cache')
if not isdir(outputdir):
print >> sys.stderr, "Error: Output directory %s does not exist or is not a directory." % outputdir
sys.exit(1)
# Set output directory as
print "Using output directory %s/" % outputdir
locargs['*']['output_location'] = outputdir
# FIXME: implement CVS/SVN drivers
if not (locargs[('gdu','gtkdoc')]['forceCVS'] or locargs[('gdu','gtkdoc')]['jhbuild_location'] or locargs[('gdu','gtkdoc')]['forceViewCVS']):
print >> sys.stderr, "SVN driver is not yet implemented."
sys.exit(15)
# Create output skin directory
# FIXME: Move this somewhere else?
if isdir(join(outputdir, 'skin')): shutil.rmtree(join(outputdir, 'skin'))
shutil.copytree(join(abspath(dirname(__file__)), 'skin'), join(outputdir, 'skin'))
# Load decorators
print "Loading decorators...",
decorators = load_decorators()
print ", ".join(decorators)
# List of objects representing modules for docs to be built
docobjs = []
# Load and start locators
print "Loading locators..."
sys.path.append(join(dirname(__file__), 'locators'))
for f in glob(join(dirname(__file__), 'locators', '*.py')):
print
try:
Name = basename(f[:-3])
# do some fancy printing...
print ' '+'-'*76+' '
print " %s locator" % Name
Module = __import__(Name)
Class = getattr(Module, '%sLocator' % Name)
except:
print >> sys.stderr, "Error: Unable to load %s locator" % Name
traceback.print_exc()
sys.exit(2)
# Prepare locator arguments for passing to locator
locator_args = locargs['*']
for l in locargs.keys():
if Name in l:
for v in locargs[l].keys():
locator_args[v] = locargs[l][v]
Instance = Class(locator_args)
objs = Instance.getList()
founded = len(objs)
print " %d documentation items found" % len(objs)
docobjs += objs
builded = len(docobjs)
print
print ' '+'-'*76+' '
print "Done building of %d documentation items" % builded
print "Starting creating indexes..."
# FIXME: implement building indexes
# TODO: implement rebuilding indexes without locating everything
indexutils.create_indexes(docobjs, outputdir)

View File

@ -1,55 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?><!-- -*- indent-tabs-mode: nil -*- -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml"
version="1.0">
<xsl:template name="libgo.header">
<div id="page">
<ul id="general">
<li id="siteaction-gnome_home" class="home">
<a href="http://www.gnome.org/" accesskey="" title="Home">Home</a>
</li>
<li id="siteaction-gnome_news">
<a href="http://news.gnome.org" accesskey="" title="News">News</a>
</li>
<li id="siteaction-gnome_projects">
<a href="http://www.gnome.org/projects/" accesskey="" title="Projects">Projects</a>
</li>
<li id="siteaction-gnome_art">
<a href="http://art.gnome.org" accesskey="" title="Art">Art</a>
</li>
<li id="siteaction-gnome_support">
<a href="http://www.gnome.org/support/" accesskey="" title="Support">Support</a>
</li>
<li id="siteaction-gnome_development">
<a href="http://developer.gnome.org" accesskey="" title="Development">Development</a>
</li>
<li id="siteaction-gnome_community">
<a href="http://www.gnome.org/community/" accesskey="" title="Community">Community</a>
</li>
</ul>
<div id="header">
<h1>library.gnome.org</h1>
<div id="control">
<div id="language">
<!-- Placeholder for a template that will probably go here -->
</div>
</div>
<div id="tabs">
<ul id="portal-globalnav">
<li id="portaltab-root"> <!-- class="selected"> -->
<a href="/"><span>Home</span></a></li>
<li id="portaltab-users" class="plain"><a href="/"><span>Users</span></a></li>
<li id="portaltab-developers" class="plain"><a href="/"><span>Developers</span></a></li>
<li id="portaltab-get-involved" class="plain"><a href="http://gnome.jardigrec.eu/en/get-involved"><span>Get involved</span></a></li>
<li id="portaltab-about" class="plain"><a href="/about"><span>About</span></a></li>
</ul>
</div> <!-- end of #tabs -->
</div> <!-- end of #header -->
</div>
</xsl:template>
</xsl:stylesheet>

View File

@ -1,143 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?><!-- -*- indent-tabs-mode: nil -*- -->
<!--
Copyright (c) 2006 Goran Rakic <grakic@devbase.net>.
This file is part of libgo.
libgo is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
libgo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with libgo; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
xmlns:html="http://www.w3.org/1999/xhtml"
extension-element-prefixes="exsl"
version="1.0">
<xsl:import href="heading.xsl"/>
<xsl:output method="html"/>
<xsl:namespace-alias stylesheet-prefix="html" result-prefix="#default"/>
<xsl:template match="document">
<dt>
<a href="{@url}" lang="{@lang}">
<xsl:choose>
<xsl:when test="normalize-space(@title)">
<xsl:value-of select="@title" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@module" />
</xsl:otherwise>
</xsl:choose>
</a>
<xsl:if test="@abstract">
<dd><p><xsl:value-of select="@abstract" /></p></dd>
</xsl:if>
</dt>
</xsl:template>
<xsl:template match="document" mode="modindex">
<h1 class="article title">
<a href="{@url}" lang="{@lang}">
<xsl:choose>
<xsl:when test="normalize-space(@title)">
<xsl:value-of select="@title" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@module" />
</xsl:otherwise>
</xsl:choose>
</a>
</h1>
<xsl:if test="@abstract">
<p><xsl:value-of select="@abstract" /></p>
</xsl:if>
</xsl:template>
<xsl:template match="versions" mode="modindex">
<p>Other versions:
<xsl:apply-templates select="node()"/>
</p>
</xsl:template>
<xsl:template match="version" mode="modindex">
<a href="{.}/">
<xsl:value-of select="node()"/>
</a>
<xsl:if test="count(following-sibling::*)">
<xsl:text> - </xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="langs" mode="modindex">
<p>Other languages:
<xsl:apply-templates select="node()"/>
</p>
</xsl:template>
<xsl:template match="lang">
<a href="index.html.{.}" lang="{.}">
<xsl:value-of select="node()"/>
</a>
<xsl:if test="count(following-sibling::*)">
<xsl:text> - </xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="module">
<exsl:document href="{@section}{@modulename}/index.html.{@lang}">
<html>
<head>
<title><xsl:value-of select="@modulename" /> - GNOME Library</title>
<link rel="stylesheet" type="text/css" href="/skin/lgo.css"/>
</head>
<body>
<xsl:call-template name="libgo.header" />
<div class="body">
<xsl:apply-templates select="node()" mode="modindex"/>
</div>
</body>
</html>
</exsl:document>
</xsl:template>
<xsl:template match="index">
<exsl:document href="index.html.{@lang}">
<html>
<head>
<title>GNOME Library</title>
<link rel="stylesheet" type="text/css" href="/skin/lgo.css"/>
</head>
<body>
<xsl:call-template name="libgo.header" />
<div class="body">
<dl class="doc-index">
<xsl:apply-templates select="node()"/>
</dl>
</div>
</body>
</html>
</exsl:document>
</xsl:template>
<xsl:template match="indexes">
<xsl:apply-templates select="node()"/>
</xsl:template>
</xsl:stylesheet>

View File

@ -1,92 +0,0 @@
#!/usr/bin/env python
# Copyright (c) 2006 Goran Rakic <grakic@devbase.net>.
#
# This file is part of libgo.
#
# libgo is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# libgo is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with libgo; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import sys, re
varre = re.compile('^([a-zA-Z0-9_]+)[\s]*=[\s]*(.*)')
valre = re.compile('((\$\(|\@){1}([a-zA-Z0-9_]+)(\)|\@){1})')
# Bug: valre will accept $(T@ and @T) as variables to substitute
# but it will work correctly for any valid Makefile.am
def read(filename):
"""
Read Makefile/Makefile.am into dictionary
Unrecognized lines (ones that don't define variable)
are added to dictionary using numeric IDs as a keys.
"""
# Bug: Fails at conditional defs like:
# if HAVE_CUPS
# CUPS_DIR = cups
# else
# CUPS_DIR =
# endif
# ... when it will use value from top down branch
# and will propagate it to all other variables in substitutuion
variables = {}
lines = []
num = 0
fp = open(filename, 'r')
try:
while 1:
buf = fp.readline()
if not buf:
break
if buf[-1] == '\n':
if len(buf)==1:
continue
elif buf[-2] == '\\':
lines.append(buf[:-2].strip())
continue
else:
buf = buf[:-1]
lines.append(buf.strip())
line = ' '.join(lines)
lines = []
v = varre.match(line)
if v:
name, value = v.group(1, 2)
i = value.find('#')
else:
# This will include all non definition lines
# that are not empty and numerate them with numbers
value = line.strip()
i = value.find('#')
if value and (i>0 or i==-1):
num += 1
name = num
else:
continue
if name:
# Remove any trailing comment
if i >= 0: value = value[:i] # slice
# Substitute defined variables in value
var = valre.findall(value)
for v in var:
if v[2] in variables:
value = value.replace(v[0], variables[v[2]])
variables[name] = value.strip()
finally:
fp.close()
return variables

12
po/ChangeLog Normal file
View File

@ -0,0 +1,12 @@
2007-07-24 gettextize <bug-gnu-gettext@gnu.org>
* Makefile.in.in: New file, from gettext-0.16.1.
* boldquot.sed: New file, from gettext-0.16.1.
* en@boldquot.header: New file, from gettext-0.16.1.
* en@quot.header: New file, from gettext-0.16.1.
* insert-header.sin: New file, from gettext-0.16.1.
* quot.sed: New file, from gettext-0.16.1.
* remove-potcdate.sin: New file, from gettext-0.16.1.
* Rules-quot: New file, from gettext-0.16.1.
* POTFILES.in: New file.

3
po/LINGUAS Normal file
View File

@ -0,0 +1,3 @@
# please keep this list sorted alphabetically
#
fr

2
po/POTFILES.in Normal file
View File

@ -0,0 +1,2 @@
# List of source files which contain translatable strings.
data/catalog.xml.in

51
po/fr.po Normal file
View File

@ -0,0 +1,51 @@
# French translation of libgo
# Copyright (C) 2007 Free Software Foundation, Inc.
# This file is distributed under the same license as the libgo package.
# Frederic Peters <fpeters@0d.be>, 2007.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: libgo 0.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-07-25 11:45+0200\n"
"PO-Revision-Date: 2007-07-24 19:53+0200\n"
"Last-Translator: Frederic Peters <fpeters@0d.be>\n"
"Language-Team: GNOME French Team <gnomefr@traduc.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: data/catalog.xml.in.h:1
msgid "Available Languages:"
msgstr "Langues disponibles :"
#: data/catalog.xml.in.h:2
msgid "Available Versions:"
msgstr "Versions disponibles :"
#: data/catalog.xml.in.h:3
msgid "Developers"
msgstr "Développeurs"
#: data/catalog.xml.in.h:4
msgid ""
"Even though it's extremely user-friendly, GNOME is a large and complex "
"system, and as such, requires some learning to utilize to the fullest. To "
"make that easier, we've provided some very useful documentation."
msgstr ""
#: data/catalog.xml.in.h:5
msgid ""
"For those who develop, or are interested in developing GNOME, and "
"applications for GNOME. You will find developer documentation and "
"information on how to get involved plus much more."
msgstr ""
#: data/catalog.xml.in.h:6
msgid "Home"
msgstr "Accueil"
#: data/catalog.xml.in.h:7
msgid "Users"
msgstr "Utilisateurs"

6
sample.lgorc Normal file
View File

@ -0,0 +1,6 @@
version_min = '2.18.0'
version_max = None
modules = ['eog', 'gedit', 'alacarte', 'glib']

View File

@ -1,281 +0,0 @@
body {
margin: 0px;
padding: 0px;
font: sans-serif;
background: white url(/skin/star.png) -100px -200px no-repeat;
height: 101%;
}
#page {
margin: 0px;
padding: 0px;
}
#footer p {
text-align: center;
}
#footer {
font-size: small;
clear: both;
margin-top: 2em;
padding: 1em 0 1em 0;
color: #aaaaaa;
}
#footer a {
color: #aaaaff;
}
#footer a:visited {
color: #ffaaaa;
}
div.in-column {
margin: 0 0 2em 1em;
float: right;
max-width: 12em;
}
hr {
color: black;
background: black;
border: 0;
height: 1px;
width: 200px;
text-align: center;
clear: both;
}
div.body {
clear: both;
}
div.sidebar {
position: absolute;
text-align: left;
right: 0px;
top: 15ex;
width: 27ex;
padding-left: 1ex;
border-left: 1ex solid #eee;
}
div.sidebar h2 {
margin-top: 0;
padding: 5px 2ex 5px 2ex;
background: url(/skin/t.png) top left repeat-y;
font-size: 100%;
}
ul.toc {
padding: 0;
padding-left: 20px;
margin-left: 0;
margin-right: 10px;
list-style: none;
}
ul.toc li {
list-style: circle;
}
ul.toc li a {
text-decoration: none;
color: black;
}
ul.toc li a:hover {
text-decoration: underline;
}
#general {
list-style: none;
background: #2E3436 url(/skin/general_bg.png) 0 100% repeat-x;
text-align: right;
padding: 0 1ex;
margin: 0;
font-size: 70%;
}
#general li {
display: inline;
background: url(/skin/general_separator.png) 0 0 no-repeat;
padding-top: 10px;
padding-bottom: 8px;
margin-left: 0px;
margin-top: 0px;
}
#general li a {
font-weight: bold;
color: #FFFFFF;
margin: 0 2ex;
text-decoration: none;
line-height: 30px;
}
#general li a:hover {
text-decoration: underline;
}
#general .home {
float: left;
background: url(/skin/general_separator.png) 100% 0 no-repeat;
padding-top: 0;
padding-bottom: 0;
}
#general .home a {
float: left;
background: url(/skin/foot.png) 7px 50% no-repeat;
margin-left: 0;
padding-left: 27px;
}
#header {
background: #729FCF url(/skin/logo.png) 3ex 10px no-repeat;
float: left;
width: 100%;
font-size: 75%;
}
#header h1 {
margin: 0;
margin-left: 200px;
padding-top: 30px;
font-size: 150%;
}
#tabs {
background: url(/skin/bar.png) 0 100% repeat-x; /* */
width: 100%;
float: left;
margin: 0;
padding: 0;
}
#portal-globalnav {
float: right;
list-style: none;
margin: 0;
margin-right: 3ex;
}
#portal-globalnav li {
float: left;
margin: 0;
margin-left: 0.2ex;
font-size: 2ex;
}
#portal-globalnav li a:hover {
color: #111111;
}
#portal-globalnav li a {
float: left;
text-decoration: none;
color: #555555;
background: url(/skin/tab_left.png) 0 0 no-repeat;
padding: 7px 0 7px 7px;
border-bottom: 2px solid #CCCCCC;
}
#portal-globalnav li span {
background: url(/skin/tab_right.png) 100% 0 no-repeat;
padding: 7px 28px 7px 19px;
}
#portal-globalnav li.selected a {
color: #3566A5;
background: url(/skin/tab_left.png) 0 -57px no-repeat;
border-bottom: none;
padding-top: 8px;
padding-bottom: 8px;
}
#portal-globalnav li.selected span {
background: url(/skin/tab_right.png) 100% -57px no-repeat;
padding-top: 8px;
padding-bottom: 8px;
}
div.articleinfo h1 {
padding-top: 1ex;
color: #d40000;
}
div.articleinfo h3.abstract {
font-weight: normal;
border: 5px solid #eee;
padding: 1ex;
-moz-border-radius: 10px;
font-size: 100%;
background: white;
}
div.articleinfo dd.affiliation {
color: #a4a4a4;
margin-bottom: 1ex;
}
div.articleinfo dl {
margin-left: 1em;
}
dl.doc-index {
padding-top: 2em;
}
dl.doc-index p {
margin: 0.5ex 0;
}
dl.doc-index dt {
margin-top: 2em;
}
dl.doc-index dd {
margin-bottom: 2em;
margin-left: 1em;
}
dl.doc-index dt a {
color: #d40000;
text-decoration: none;
font-weight: bold;
font-size: 110%;
}
div.body {
background-color: transparent;
border: none;
padding: 1em;
}
div.body-sidebar {
margin-right: 27ex;
}
div.navbar {
margin: 0 29ex 0 2ex;
}
h1.title {
font-size: 1.72em;
margin: 0; padding: 0;
color: #3f3f3f;
}
h1.title a {
color: inherit;
text-decoration: none;
}

34
src/config.py Normal file
View File

@ -0,0 +1,34 @@
import os
import traceback
from errors import FatalError
_defaults_file = os.path.join(os.path.dirname(__file__), 'defaults.lgorc')
_default_lgorc = os.path.join(os.environ['HOME'], '.lgorc')
_known_keys = ['ftp_gnome_org_local_copy',
'private_dir', 'download_cache_dir', 'output_dir',
'version_min', 'version_max', 'modules', 'blacklist']
class Config:
def __init__(self, filename=_default_lgorc):
config = {
'__file__': _default_lgorc,
}
try:
execfile(_defaults_file, config)
except:
traceback.print_exc()
raise FatalError('could not load config defaults')
if os.path.exists(filename):
config['__file__'] = filename
try:
execfile(filename, config)
except:
traceback.print_exc()
raise FatalError('could not load config file')
for name in _known_keys:
setattr(self, name, config[name])

26
src/defaults.lgorc Normal file
View File

@ -0,0 +1,26 @@
import os
# local access to ftp.gnome.org
ftp_gnome_org_local_copy = None
# private work directory
private_dir = os.path.join(os.environ['HOME'], '.lgo')
# where to cache downloaded files
download_cache_dir = os.path.join(private_dir, 'cache')
# where to output library.gnome.org files
output_dir = '/var/www/library.gnome.org/'
# minimum GNOME version to download
version_min = None
# maximum GNOME version to download
version_max = None
# modules to generate docs (leave as None to build all modules)
modules = None
# documents to blacklist
blacklist = ['gpl', 'lgpl', 'fdl']

3
src/errors.py Normal file
View File

@ -0,0 +1,3 @@
class FatalError(Exception):
pass

716
src/lgo.py Normal file
View File

@ -0,0 +1,716 @@
#! /usr/bin/env python
import os
import re
import urllib2
from cStringIO import StringIO
from optparse import OptionParser
import logging
import elementtree.ElementTree as ET
import tarfile
import glob
import tempfile
import stat
import subprocess
try:
import html5lib
except ImportError:
html5lib = None
from config import Config
class Document:
channel = None # one of ('users', 'developers')
module = None
path = None
category = None
toc_id = None
title = None # indexed on language, most recent version
abstract = None # indexed on language, most recent version
languages = None
versions = None
def create_element(self, parent, language):
if not language in self.languages:
return
doc = ET.SubElement(parent, 'document')
if language == 'C':
language = 'en'
doc.set('modulename', self.module)
doc.set('path', self.path)
ET.SubElement(doc, 'title').text = self.title.get(language) or self.module
if self.abstract.has_key(language):
ET.SubElement(doc, 'abstract').text = self.abstract.get(language)
doc.set('lang', language)
doc.set('channel', self.channel)
if self.category:
doc.set('category', self.category)
if self.toc_id:
doc.set('toc_id', self.toc_id)
langs = ET.SubElement(doc, 'other-languages')
for l in self.languages:
if l == language or l == 'C':
continue
ET.SubElement(langs, 'lang').text = l
if self.versions:
versions = ET.SubElement(doc, 'versions')
for v in self.versions:
ET.SubElement(versions, 'version').text = v
class Formatter(logging.Formatter):
def format(self, record):
return '%c: %s' % (record.levelname[0], record.msg)
class FtpDotGnomeDotOrg:
def __init__(self, config):
self.config = config
if self.config.ftp_gnome_org_local_copy:
self.ftp_gnome_org_local_copy = self.config.ftp_gnome_org_local_copy
self.download = self.download_local
self.listdir = self.listdir_local
else:
self.ftp_gnome_org_cache_dir = os.path.join(
config.download_cache_dir, 'ftp.gnome.org')
if not os.path.exists(self.ftp_gnome_org_cache_dir):
os.makedirs(self.ftp_gnome_org_cache_dir)
def download(self, filename):
cache_filename = os.path.join(self.ftp_gnome_org_cache_dir, filename)
cache_dir = os.path.split(cache_filename)[0]
if not os.path.exists(cache_dir):
os.makedirs(cache_dir)
if os.path.exists(cache_filename) and os.stat(cache_filename)[stat.ST_SIZE]:
logging.info('using cache of ftp://ftp.gnome.org/%s' % filename)
return (cache_filename, open(cache_filename))
logging.info('downloading ftp://ftp.gnome.org/%s' % filename)
try:
open(cache_filename, 'w').write(
urllib2.urlopen('ftp://ftp.gnome.org/' + filename).read())
except IOError:
raise
return (cache_filename, open(cache_filename))
def download_local(self, filename):
local_filename = os.path.join(self.ftp_gnome_org_local_copy, filename)
return (local_filename, open(local_filename))
def listdir(self, dirname):
l = []
for line in urllib2.urlopen('ftp://ftp.gnome.org/' + dirname):
l.append(line.strip().split()[-1])
return l
def listdir_local(self, dirname):
return os.listdir(os.path.join(self.ftp_gnome_org_local_copy, dirname))
def download(url, cache = False):
s = urllib2.urlopen(url).read()
return s
class Lgo:
data_dir = os.path.join(os.path.dirname(__file__), '../data')
db2html_xsl_file = os.path.join(data_dir, 'xslt', 'db2html.xsl')
gtkdoc_xsl_file = os.path.join(data_dir, 'xslt', 'gtk-doc.xsl')
gtkdoc_fixup_xsl_file = os.path.join(data_dir, 'xslt', 'gtk-doc-fixup.xsl')
indexes_xsl_file = os.path.join(data_dir, 'xslt', 'indexes.xsl')
javascript_dir = os.path.join(data_dir, 'js')
skin_dir = os.path.join(data_dir, 'skin')
rebuild_all = False
def __init__(self):
self.documents = []
parser = OptionParser()
parser.add_option('-c', '--config', dest = 'config')
parser.add_option('-v', '--verbose',
action = 'count', dest = 'verbose', default = 0,
help = 'verbosity level (more -v for more verbose)')
parser.add_option('--rebuild-all',
action = 'store_true', dest = 'rebuild_all',
help = 'rebuild all documents (even those that were already built)')
options, args = parser.parse_args()
logging.basicConfig(level = 10 + logging.CRITICAL - options.verbose*10,
formatter = Formatter())
logging.getLogger().handlers[0].setFormatter(Formatter())
self.rebuild_all = options.rebuild_all
if options.config:
self.config = Config(filename = options.config)
else:
self.config = Config()
self.get_yelp_categories()
self.copy_static_files()
self.process_releases()
self.generate_indexes()
self.generate_static_pages()
def get_yelp_categories(self):
logging.info('Getting categories from Yelp')
filename = FtpDotGnomeDotOrg(self.config).download(
'pub/GNOME/sources/yelp/2.18/yelp-2.18.1.tar.bz2')[0]
tar = tarfile.open(filename, 'r')
done = 0
for tarinfo in tar:
filename = os.path.basename(tarinfo.name)
if filename == 'scrollkeeper.xml':
scrollkeeper_data = tar.extractfile(tarinfo).read()
done += 1
elif filename == 'toc.xml':
open(os.path.join(self.data_dir, 'externals', 'toc.xml'), 'w').write(
tar.extractfile(tarinfo).read())
done += 1
if done == 2:
break
yelp_toc_tree = ET.fromstring(scrollkeeper_data)
self.toc_mapping = {}
for subtoc in yelp_toc_tree.findall('toc'):
sub_id = subtoc.attrib['id']
for subject in subtoc.findall('subject'):
self.toc_mapping[subject.attrib['category']] = sub_id
def copy_static_files(self):
if not os.path.exists(os.path.join(self.config.output_dir, 'js')):
os.makedirs(os.path.join(self.config.output_dir, 'js'))
if not os.path.exists(os.path.join(self.config.output_dir, 'skin')):
os.makedirs(os.path.join(self.config.output_dir, 'skin'))
if not os.path.exists(os.path.join(self.config.output_dir, 'skin/icons')):
os.makedirs(os.path.join(self.config.output_dir, 'skin/icons'))
for src in glob.glob('%s/*.js' % self.javascript_dir):
dst = os.path.join(self.config.output_dir, 'js', os.path.basename(src))
open(dst, 'w').write(open(src, 'r').read())
for src in glob.glob('%s/*.css' % self.skin_dir) + \
glob.glob('%s/*.png' % self.skin_dir):
dst = os.path.join(self.config.output_dir, 'skin', os.path.basename(src))
open(dst, 'w').write(open(src, 'r').read())
for src in glob.glob('%s/icons/*.png' % self.skin_dir):
dst = os.path.join(self.config.output_dir, 'skin/icons', os.path.basename(src))
open(dst, 'w').write(open(src, 'r').read())
def process_releases(self):
'''Download GNOME releases'''
self.ftp_gnome_org = FtpDotGnomeDotOrg(self.config)
releases = self.ftp_gnome_org.listdir('pub/GNOME/teams/releng/')
def version_cmp(x, y):
return cmp([int(j) for j in x.split('.')], [int(k) for k in y.split('.')])
for i, r in enumerate(releases[:]):
if self.config.version_min and version_cmp(r, self.config.version_min) < 0:
continue
if self.config.version_max and version_cmp(r, self.config.version_max) > 0:
continue
if i < len(releases)-1 and releases[i+1].startswith(re.match(r'\d+\.\d+\.', r).group()):
# next release has the same major.minor version number, so skip
# this one and get the newer one later
logging.debug('skipping release %s, not the last in serie' % r)
continue
if int(r.split('.')[1]) % 2 == 1:
# odd release, development, skip unless this is the current
# development serie
if not releases[-1].startswith(re.match(r'\d+\.\d+\.', r).group()):
logging.debug('skipping release %s, not the last in serie' % r)
continue
if version_cmp(r, '2.19.0') < 0:
url = 'pub/GNOME/teams/releng/%(r)s/gnome-%(r)s.modules'
else:
# from 2.19.0, the jhbuild moduleset structure changed
url = 'pub/GNOME/teams/releng/%(r)s/gnome-suites-%(r)s.modules'
logging.info('Getting GNOME release: %s' % r)
moduleset = self.ftp_gnome_org.download(url % {'r': r})[1]
self.process_moduleset(moduleset)
def process_moduleset(self, moduleset):
'''Download tarballs from a module set'''
tree = ET.parse(moduleset)
for tarball in tree.findall('tarball'):
if self.config.modules is not None and not tarball.attrib['id'] in self.config.modules:
continue
href = tarball.find('source').attrib['href']
if href.startswith('http://download.gnome.org/') or href.startswith(
'http://ftp.gnome.org/'):
href = href.replace('http://download.gnome.org/', 'pub/GNOME/')
href = href.replace('http://ftp.gnome.org/', '')
try:
filename = self.ftp_gnome_org.download(href)[0]
except IOError:
logging.error('error downloading %s' % href)
continue
else:
logging.warning('should download %s' % href)
continue
logging.info('processing module %s' % tarball.attrib['id'])
self.process_module(filename)
def process_module(self, filename):
mtime = os.stat(filename)[stat.ST_MTIME]
tar = tarfile.open(filename, 'r')
for tarinfo in tar:
if os.path.split(tarinfo.name)[-1] == 'Makefile.am':
fd = tar.extractfile(tarinfo)
s = fd.read()
if 'DOC_MODULE' in s and 'include $(top_srcdir)/gnome-doc-utils.make' in s:
logging.debug('found usage of gnome-doc-utils in %s' % tarinfo.name)
self.process_gnome_doc_utils_module(tar, tarinfo, mtime)
elif 'include $(top_srcdir)/gtk-doc.make' in s:
logging.debug('found usage of gtk-doc in %s' % tarinfo.name)
self.process_gtk_doc_module(tar, tarinfo, mtime)
tar.close()
def process_gnome_doc_utils_module(self, tar, tarinfo, mtime_source):
dirname = os.path.split(tarinfo.name)[0]
makefile_am = tar.extractfile(tarinfo).read()
makefile_am = makefile_am.replace('\\\n', ' ')
doc_module = re.findall(r'DOC_MODULE\s?=\s?(.*)', makefile_am)[0].strip()
if not doc_module:
return
if doc_module == '@PACKAGE_NAME@':
# ekiga has this, use another way, looking at omf files
try:
omf_file = [x.name for x in tar.getmembers() if \
x.name.startswith(dirname) and x.name.endswith('.omf.in')][0]
except IndexError:
logging.error('failed to get DOC_MODULE for %s' % tarinfo.name)
doc_module = os.path.split(omf_file)[-1][:-len('.omf.in')]
if doc_module in self.config.blacklist:
return
try:
doc_linguas = re.findall(r'DOC_LINGUAS\s+=[\t ](.*)', makefile_am)[0].split()
except IndexError:
doc_linguas = ['C']
try:
doc_figures = re.findall('DOC_FIGURES\s+=\s+(.*)', makefile_am)[0].split()
except IndexError:
doc_figures = []
ext_dirname = os.path.join(self.config.private_dir, 'extracts')
if not os.path.exists(ext_dirname):
os.makedirs(ext_dirname)
logging.debug('extracting %s out of %s' % (dirname, tar.name))
for tarinfo in tar.getmembers():
if not os.path.split(tarinfo.name)[0].startswith(dirname):
continue
dest = os.path.join(ext_dirname, tarinfo.name)
if os.path.exists(dest):
continue
if tarinfo.isdir() and not os.path.exists(dest):
os.makedirs(dest)
elif tarinfo.isreg():
if not os.path.exists(os.path.dirname(dest)):
os.makedirs(os.path.dirname(dest))
open(dest, 'w').write(tar.extractfile(tarinfo).read())
# get category from omf file
category = None
omf_file = glob.glob(os.path.join(ext_dirname, dirname) + '/*.omf.in')
if omf_file:
try:
category = ET.parse(omf_file[0]).find('resource/subject').attrib['category']
except (IndexError, KeyError):
pass
channel = 'users'
if category and category.startswith('GNOME|Development'):
channel = 'developers'
version = os.path.splitext(tar.name)[0].split('-')[-1]
one_dot_version = re.match(r'\d+\.\d+', version).group()
web_output_dir = os.path.join(self.config.output_dir, channel,
doc_module, one_dot_version)
logging.info('generating doc in %s' % web_output_dir)
if not os.path.exists(web_output_dir):
os.makedirs(web_output_dir)
if not 'en' in doc_linguas:
doc_linguas.append('en')
doc_linguas.sort()
try:
doc = [x for x in self.documents if x.module == doc_module and x.channel == channel][0]
except IndexError:
doc = Document()
doc.module = doc_module
doc.channel = channel
doc.path = '/' + os.path.join(channel, doc_module, one_dot_version) + '/'
doc.languages = doc_linguas
doc.title = {}
doc.abstract = {}
doc._last_version = version
doc.versions = [one_dot_version]
self.documents.append(doc)
else:
if doc._last_version == version:
# file was already processed in a previous moduleset
return
doc._last_version = version
if int(one_dot_version.split('.')[1]) % 2 == 0:
# update path to point to the latest version (but no
# development versions)
doc.path = '/' + os.path.join(channel, doc_module, one_dot_version) + '/'
if not one_dot_version in doc.versions:
doc.versions.append(one_dot_version)
for lang in doc_linguas:
if not lang in doc.languages:
doc.languages.append(lang)
if category:
doc.category = category
doc.toc_id = self.toc_mapping.get(doc.category)
for lang in doc_linguas:
if not self.rebuild_all and os.path.exists(
os.path.join(web_output_dir, 'index.xml.%s' % lang)):
mtime = os.stat(os.path.join(web_output_dir, 'index.xml.%s' % lang))[stat.ST_MTIME]
if mtime > mtime_source:
logging.debug('using already generated doc in %s' % lang)
# get translated title/abstract for indexes
# (duplicated code, should clean up)
tree = ET.parse(os.path.join(web_output_dir, 'index.xml.%s' % lang))
if tree.find('title') is not None and tree.find('title').text:
doc.title[lang] = tree.find('title').text
elif tree.find('{http://www.w3.org/1999/xhtml}title') is not None and \
tree.find('{http://www.w3.org/1999/xhtml}title').text:
doc.title[lang] = tree.find('{http://www.w3.org/1999/xhtml}title').text
if tree.find('abstract') is not None and tree.find('abstract').text:
doc.abstract[lang] = tree.find('abstract').text
elif tree.find('{http://www.w3.org/1999/xhtml}abstract') is not None and \
tree.find('{http://www.w3.org/1999/xhtml}abstract').text:
doc.abstract[lang] = tree.find('{http://www.w3.org/1999/xhtml}abstract').text
continue
if lang == 'en':
lang_dirname = os.path.join(ext_dirname, dirname, 'C')
else:
lang_dirname = os.path.join(ext_dirname, dirname, lang)
xml_file = os.path.join(lang_dirname, doc_module + '.xml')
# format docbook into html files
cmd = ['xsltproc', '--output', web_output_dir + '/',
'--nonet', '--xinclude',
'--stringparam', 'libgo.lang', lang,
'--stringparam', 'libgo.channel', channel,
self.db2html_xsl_file, xml_file]
logging.debug('executing %s' % ' '.join(cmd))
rc = subprocess.call(cmd)
if rc != 0:
logging.warn('%s failed with error %d' % (' '.join(cmd), rc))
if doc_figures:
# and copy images/
logging.debug('copying figures')
for doc_figure in doc_figures:
src = os.path.join(lang_dirname, doc_figure)
if not os.path.exists(src):
continue
dst = os.path.join(web_output_dir, doc_figure + '.%s' % lang)
if not os.path.exists(os.path.split(dst)[0]):
os.makedirs(os.path.split(dst)[0])
open(dst, 'w').write(open(src, 'r').read())
# and get translated title/abstract for indexes
tree = ET.parse(os.path.join(web_output_dir, 'index.xml.%s' % lang))
if tree.find('title') is not None:
doc.title[lang] = tree.find('title').text
elif tree.find('{http://www.w3.org/1999/xhtml}title') is not None:
doc.title[lang] = tree.find('{http://www.w3.org/1999/xhtml}title').text
if tree.find('abstract') is not None:
doc.abstract[lang] = tree.find('abstract').text
elif tree.find('{http://www.w3.org/1999/xhtml}abstract') is not None:
doc.abstract[lang] = tree.find('{http://www.w3.org/1999/xhtml}abstract').text
def process_gtk_doc_module(self, tar, tarinfo, mtime_source):
dirname = os.path.split(tarinfo.name)[0]
makefile_am = tar.extractfile(tarinfo).read()
makefile_am = makefile_am.replace('\\\n', ' ')
doc_module = re.findall(r'DOC_MODULE\s?=\s?(.*)', makefile_am)[0].strip()
if not doc_module:
return
if doc_module in self.config.blacklist:
return
main_sgml_file = re.findall(r'DOC_MAIN_SGML_FILE\s?=\s?(.*)',
makefile_am)[0].strip()
main_sgml_file = main_sgml_file.replace('$(DOC_MODULE)', doc_module)
try:
html_images = re.findall('HTML_IMAGES\s+=\s+(.*)', makefile_am)[0].split()
except IndexError:
html_images = []
channel = 'developers'
ext_dirname = os.path.join(self.config.private_dir, 'extracts')
if not os.path.exists(ext_dirname):
os.makedirs(ext_dirname)
if not os.path.exists(os.path.join(ext_dirname, dirname)):
logging.debug('extracting %s out of %s' % (dirname, tar.name))
for tarinfo in tar.getmembers():
if not os.path.split(tarinfo.name)[0].startswith(dirname):
continue
dest = os.path.join(ext_dirname, tarinfo.name)
if not os.path.exists(os.path.dirname(dest)):
os.makedirs(os.path.dirname(dest))
if tarinfo.isdir() and not os.path.exists(dest):
os.makedirs(dest)
elif tarinfo.isreg():
if not os.path.exists(os.path.dirname(dest)):
os.makedirs(os.path.dirname(dest))
open(dest, 'w').write(tar.extractfile(tarinfo).read())
version = os.path.splitext(tar.name)[0].split('-')[-1]
one_dot_version = re.match(r'\d+\.\d+', version).group()
web_output_dir = os.path.join(self.config.output_dir, channel,
doc_module, one_dot_version)
if not os.path.exists(web_output_dir):
os.makedirs(web_output_dir)
if not self.rebuild_all and os.path.exists(
os.path.join(web_output_dir, '%s.devhelp' % doc_module)):
mtime = os.stat(os.path.join(web_output_dir, '%s.devhelp' % doc_module))[stat.ST_MTIME]
else:
mtime = 0
if mtime > mtime_source:
logging.debug('using already generated doc')
else:
logging.info('generating doc in %s' % web_output_dir)
cmd = ['xsltproc', '--output', web_output_dir + '/',
'--nonet', '--xinclude',
'--stringparam', 'libgo.lang', 'en',
'--stringparam', 'gtkdoc.bookname', doc_module,
'--stringparam', 'gtkdoc.version', '"1.8 (+lgo)"',
'--stringparam', 'libgo.channel', channel,
self.gtkdoc_xsl_file,
os.path.join(ext_dirname, dirname, main_sgml_file)]
logging.debug('executing %s' % ' '.join(cmd))
rc = subprocess.call(cmd)
if rc != 0:
logging.warn('%s failed with error %d' % (' '.join(cmd), rc))
if rc == 1536:
# build failed, probably because it has inline references in
# documentation and would require a full module build to get
# them properly. (happens with GTK+)
if html5lib:
# convert files to XML, then process them with xsltproc
# to get library.gnome.org look
logging.info('transforming files shipped with tarball')
parser = html5lib.HTMLParser()
for filename in os.listdir(os.path.join(ext_dirname, dirname, 'html')):
src = os.path.join(ext_dirname, dirname, 'html', filename)
dst = os.path.join(web_output_dir, filename)
if not filename.endswith('.html'):
open(dst, 'w').write(open(src, 'r').read())
continue
doc = parser.parse(open(src))
doc.childNodes[-1].attributes['xmlns'] = 'http://www.w3.org/1999/xhtml'
temporary = tempfile.NamedTemporaryFile()
temporary.write(doc.toxml())
temporary.flush()
cmd = ['xsltproc', '--output', dst,
'--nonet', '--xinclude',
self.gtkdoc_fixup_xsl_file,
os.path.join(ext_dirname, dirname, temporary.name)]
rc = subprocess.call(cmd)
else:
# simply copy files shipped in tarball
logging.info('copying files shipped with tarball')
for filename in os.listdir(os.path.join(ext_dirname, dirname, 'html')):
src = os.path.join(ext_dirname, dirname, 'html', filename)
dst = os.path.join(web_output_dir, filename)
if not os.path.exists(os.path.split(dst)[0]):
os.makedirs(os.path.split(dst)[0])
open(dst, 'w').write(open(src, 'r').read())
if html_images:
# and copy images/
logging.debug('copying images')
for html_image in html_images:
src = os.path.join(ext_dirname, dirname, html_image)
if not os.path.exists(src):
continue
dst = os.path.join(web_output_dir, html_image)
if not os.path.exists(os.path.split(dst)[0]):
os.makedirs(os.path.split(dst)[0])
open(dst, 'w').write(open(src, 'r').read())
# in any case, copy png files from gtk-doc
for src in glob.glob('/usr/share/gtk-doc/data/*.png'):
dst = os.path.join(web_output_dir, os.path.basename(src))
open(dst, 'w').write(open(src, 'r').read())
try:
doc = [x for x in self.documents if x.module == doc_module and x.channel == channel][0]
except IndexError:
doc = Document()
doc.module = doc_module
doc.channel = channel
doc.path = '/' + os.path.join(channel, doc_module, one_dot_version) + '/'
doc.languages = ['en']
doc.title = {}
doc.abstract = {}
doc.versions = [one_dot_version]
self.documents.append(doc)
else:
if int(one_dot_version.split('.')[1]) % 2 == 0:
# update path to point to the latest version (but no
# development versions)
doc.path = '/' + os.path.join(channel, doc_module, one_dot_version) + '/'
if not one_dot_version in doc.versions:
doc.versions.append(one_dot_version)
doc.category = 'api'
doc.toc_id = 'api'
if os.path.exists(os.path.join(web_output_dir, 'index.xml.en')):
tree = ET.parse(os.path.join(web_output_dir, 'index.xml.en'))
if tree.find('title') is not None:
doc.title['en'] = tree.find('title').text
elif tree.find('{http://www.w3.org/1999/xhtml}title') is not None:
doc.title['en'] = tree.find('{http://www.w3.org/1999/xhtml}title').text
elif os.path.exists(os.path.join(web_output_dir, '%s.devhelp' % doc_module)):
tree = ET.parse(os.path.join(web_output_dir, '%s.devhelp' % doc_module))
doc.title['en'] = tree.getroot().attrib['title']
def generate_indexes(self):
indexes = ET.Element('indexes')
# get all possible languages
languages = {}
for doc in self.documents:
for lang in doc.languages:
if lang == 'C':
continue # ignore
languages[lang] = True
for lang in languages.keys():
home = ET.SubElement(indexes, 'home')
home.set('lang', lang)
for channel in ('users', 'developers'):
docs = [x for x in self.documents if x.channel == channel]
if not docs:
continue
# get all possible languages
languages = {}
for doc in docs:
for lang in doc.languages:
if lang == 'C':
continue # ignore
languages[lang] = True
for lang in languages.keys():
logging.info('generating index for lang %s' % lang)
index = ET.SubElement(indexes, 'index')
index.set('lang', lang)
index.set('channel', channel)
docs.sort(lambda x,y: cmp(x.title.get(lang), y.title.get(lang)))
for doc in docs:
logging.debug('generating %s index for module %s' % (channel, doc.module))
if not lang in doc.languages:
if channel == 'developers':
# make sure API (in English) are displayed to all
# developers (whatever language is set)
doc.create_element(index, 'en')
else:
doc.create_element(index, lang)
idx_dirname = os.path.join(self.config.private_dir, 'indexes')
if not os.path.exists(idx_dirname):
os.makedirs(idx_dirname)
tree = ET.ElementTree(indexes)
tree.write(os.path.join(idx_dirname, 'indexes.xml'))
self.generate_html_indexes()
def generate_html_indexes(self):
idx_filename = os.path.join(self.config.private_dir, 'indexes', 'indexes.xml')
cmd = ['xsltproc', '--output', self.config.output_dir,
'--nonet', '--xinclude',
self.indexes_xsl_file, idx_filename]
logging.debug('executing %s' % ' '.join(cmd))
rc = subprocess.call(cmd)
if rc != 0:
logging.warn('%s failed with error %d' % (' '.join(cmd), rc))
def generate_static_pages(self):
try:
doc_linguas = re.findall(r'DOC_LINGUAS\s+=[\t ](.*)',
file(os.path.join(self.data_dir, 'pages', 'Makefile.am')).read())[0].split()
except IndexError:
doc_linguas = ['C']
web_output_dir = os.path.join(self.config.output_dir, 'about')
for lang in doc_linguas:
xml_file = os.path.join(os.path.join(self.data_dir, 'pages', lang, 'libgo.xml'))
if lang == 'C':
lang = 'en'
cmd = ['xsltproc', '--output', web_output_dir + '/',
'--nonet', '--xinclude',
'--stringparam', 'libgo.lang', lang,
'--stringparam', 'libgo.channel', 'about',
'--stringparam', 'db2html.sidenav', '""',
'--stringparam', 'db2html.navbar.bottom', '""',
self.db2html_xsl_file, xml_file]
logging.debug('executing %s' % ' '.join(cmd))
rc = subprocess.call(cmd)
if rc != 0:
logging.warn('%s failed with error %d' % (' '.join(cmd), rc))
if __name__ == '__main__':
Lgo()

156
stats
View File

@ -1,156 +0,0 @@
#!/usr/bin/python -u
# Copyright (c) 2006 Goran Rakic <grakic@devbase.net>.
#
# This file is part of libgo.
#
# libgo is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# libgo is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with libgo; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# stats -- check size of cache and output, list failed items, etc...
VERSION = "0.1.0"
import sys, getopt, os
from glob import glob
from os.path import join, getsize, abspath, isdir, basename, dirname
def usage(display_help = False):
"Display usage/help info"
print >> sys.stderr, "Usage: %s [OPTIONS] OUTPUTDIR" % (sys.argv[0])
if(display_help):
print >> sys.stderr, """
OPTIONS may be some of:
-f --failed List document items in cache that failed
to be built
And the usual ones:
-v --version Output version of the libgo-generate program
-h --help Output this message
"""
sys.exit(1)
# Process command line arguments
args = sys.argv[1:]
try: opts,args = getopt.getopt(args,'fvh',['failed', 'version', 'help'])
except getopt.GetoptError: usage(True)
list_failed = False
for opt, arg in opts:
if opt in ('-f', '--failed'):
list_failed = True
elif opt in ('-v', '--version'):
print VERSION
sys.exit(0)
elif opt in ('-h', '--help'):
usage(True)
def dirsize(path):
"Calculate a size of directory"
size = 0
for root, dirs, files in os.walk(path):
size += sum([getsize(join(root, name)) for name in files])
return size
# Last argument must be an output dir
if len(args)>0: outputdir = args[-1]
else: usage()
# Check if output dir exists
outputdir = abspath(outputdir)
if not isdir(outputdir):
print >> sys.stderr, "Error: Output directory %s does not exist." % outputdir
sys.exit(1)
largest_item = ('',0,0)
output_size = 0
releases = 0
modules = os.listdir(outputdir)
modules.remove('.cache')
if 'api' in modules:
modules.remove('api')
apis = os.listdir(outputdir+'/api')
modules += ['api/'+a for a in apis]
for m in modules:
r = len(os.listdir(outputdir+'/'+m))
size = dirsize(outputdir+'/'+m)
if size > largest_item[2]:
largest_item = m,r,size
output_size += size
releases += r
modules = len(modules)
cache_size = dirsize(outputdir+'/.cache/gnome')
ftpcache_size = dirsize(outputdir+'/.cache/gftp')
tmpftp_size = dirsize(outputdir+'/.cache/gftp/tmp')
ftpcache_size -= tmpftp_size
print """
Output size: %6.1fMB
Cache size: %6.1fMB
gftp cache size: %6.1fMB""" % (float(output_size)/(1024*1024), float(cache_size)/(1024*1024), float(ftpcache_size)/(1024*1024))
if modules:
print """
There are %d doc items (%d doc modules, with %.1f releases in average),
each one taking about %.1fKB of disk space.
Largest module is %s, with %d releases and %.1fMB in total size.
""" % (releases, modules, float(releases)/modules, float(output_size)/(releases*1024), largest_item[0], largest_item[1], float(largest_item[2])/(1024*1024))
else:
print """
There are no doc items in output directory."""
if list_failed:
failed_langs = glob(outputdir+'/.cache/gnome/*/*/.failed-*')
print """
Document items failed to build:"""
exists = False
sin,sout,serr = os.popen3('find %s -name .*failed' % outputdir)
for l in sout.read().split('\n'):
if l:
exists = True
print " ",
print l.replace(outputdir+'/.cache/gnome/','').replace('/.failed','')
sin.close(); sout.close(); serr.close()
if not exists:
print " There are no failed documents."
print """
Document translations failed to build:"""
exists = False
sin,sout,serr = os.popen3('find %s -name .*failed-*' % outputdir)
for l in sout.read().split('\n'):
if l:
exists = True
print " ",
print l.replace(outputdir+'/.cache/gnome/','')
sin.close(); sout.close(); serr.close()
if not exists:
print " There are no failed documents."
print
print " Also, look at libgo output for error messages about skipped doc items."
print " They are not included in the list above."
print
print " Some doc items can be removed from current building list, but"
print " are still in cache (and can be included in list of failed items)."
print

140
utils.py
View File

@ -1,140 +0,0 @@
# Copyright (c) 2006 Goran Rakic <grakic@devbase.net>.
#
# This file is part of libgo.
#
# libgo is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# libgo is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with libgo; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Misc utility functions
import sys, re, types, traceback, textwrap
from os.path import dirname, basename, isfile
import subprocess
from glob import glob
import os
decorators = []
def load_decorators():
"Load list of decorators availible"
sys.path.append(dirname(__file__)+'/decorators')
decfiles = glob(dirname(__file__)+'/decorators/*.py')
decfiles.sort()
for f in decfiles:
modName = basename(f[:-3])
Name = modName[modName.index('-')+1:]
try:
Module = __import__(modName)
Class = getattr(Module, '%sDecorator' % Name)
Decorator = Class()
decorators.append( (Name, Decorator.getCriteria(),
Decorator, Decorator.getLocators()) )
except:
print >> sys.stderr, " Error: Unable to load %s decorator" % Name
traceback.print_exc()
sys.exit(4)
return [d[0] for d in decorators]
def load_driver(name):
"Load driver class by name and create its instance"
sys.path.append(dirname(__file__)+'/drivers')
try:
module = __import__(name)
return getattr(module, '%sDriver' % name)
except:
print >> sys.stderr, " Error: Unable to load %s driver" % name
traceback.print_exc()
sys.exit(3)
def get_decorators(locator):
"Filter list of decorators to list only ones avaibile for given locator"
return [(d[0], d[1], d[2]) for d in decorators if locator in d[3]]
def cmd(cmd, verbose = False, output = False, cwd=None, extra_env=None):
"""
Calls subprocess and return output from stderr.
If output is True, return tuple of error and output.
If verbose is True, prints command before executing.
"""
if verbose:
print
print "> %s" % " ".join(cmd)
print
kws = {}
if isinstance(cmd, (str, unicode)):
kws['shell'] = True
if cwd is not None:
kws['cwd'] = cwd
if extra_env is not None:
kws['env'] = os.environ.copy()
kws['env'].update(extra_env)
p = subprocess.Popen(cmd,
close_fds=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
**kws)
retcode = p.wait()
error = p.stderr.read()
if output:
output = p.stdout.read()
return error, output
else:
return error.strip()
def svn_get_info(filename):
# we run Subversion in the C locale, because Subversion localises
# the key names in the output. See bug #334678 for more info.
error, output = cmd(
['svn', 'info', filename], output=True,
extra_env={
'LANGUAGE': 'C',
'LC_ALL': 'C',
'LANG': 'C'})
ret = {}
for line in output.splitlines():
if ':' not in line: continue
key, value = line.split(':', 1)
ret[key.lower().strip()] = value.strip()
return ret
def svn_get_uri(filename):
info = svn_get_info(filename)
return info.get('url', "")
__pad = len(" Warning: ")
__wrapper = textwrap.TextWrapper(width=80, initial_indent=' '*__pad, break_long_words=False)
def wrap(text):
"Returns wrapped string"
if type(text) != types.StringType:
text = str(text)
text = text.strip()
ret = []
for line in text.split('\n'):
ret.append(__wrapper.fill(line))
return '\n'.join(ret)
def touch(file):
""" Set the access/modified times of this file to the current time.
Create the file if it does not exist.
"""
fd = os.open(file, os.O_WRONLY | os.O_CREAT, 0666)
os.close(fd)
os.utime(file, None)