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
|
@ -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,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.
|
||||
|
23
Makefile
|
@ -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 *~ */*~ */*/*~
|
|
@ -0,0 +1,2 @@
|
|||
SUBDIRS = po data
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
])
|
||||
|
|
@ -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>
|
|
@ -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/>');
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
include $(top_srcdir)/gnome-doc-utils.make
|
||||
dist-hook: doc-dist-hook
|
||||
|
||||
DOC_MODULE = libgo
|
||||
|
|
@ -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>
|
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 154 B After Width: | Height: | Size: 154 B |
After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 699 B After Width: | Height: | Size: 699 B |
Before Width: | Height: | Size: 178 B After Width: | Height: | Size: 178 B |
Before Width: | Height: | Size: 212 B After Width: | Height: | Size: 212 B |
After Width: | Height: | Size: 650 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 846 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 846 B |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 2.2 KiB |
|
@ -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); }
|
||||
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 160 B After Width: | Height: | Size: 160 B |
Before Width: | Height: | Size: 928 B After Width: | Height: | Size: 928 B |
Before Width: | Height: | Size: 914 B After Width: | Height: | Size: 914 B |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 317 B After Width: | Height: | Size: 317 B |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 215 B After Width: | Height: | Size: 215 B |
After Width: | Height: | Size: 2.1 KiB |
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
295
doc/HACKING
|
@ -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.
|
||||
|
59
doc/README
|
@ -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)
|
56
doc/TODO
|
@ -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.
|
|
@ -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
|
|
@ -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.
|
||||
|
||||
|
|
@ -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
|
7071
doc/out-first
368
doc/out-second
|
@ -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)
|
||||
|
|
@ -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
|
@ -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]
|
290
drivers/cvs.py
|
@ -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
|
717
drivers/gftp.py
|
@ -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))
|
||||
|
|
@ -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))
|
|
@ -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
|
|
@ -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
|
62
findmissing
|
@ -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
|
243
indexutils.py
|
@ -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
|
@ -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)
|
||||
|
|
@ -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>
|
|
@ -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>
|
|
@ -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
|
|
@ -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.
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# please keep this list sorted alphabetically
|
||||
#
|
||||
fr
|
|
@ -0,0 +1,2 @@
|
|||
# List of source files which contain translatable strings.
|
||||
data/catalog.xml.in
|
|
@ -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"
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
version_min = '2.18.0'
|
||||
version_max = None
|
||||
|
||||
modules = ['eog', 'gedit', 'alacarte', 'glib']
|
||||
|
281
skin/lgo.css
|
@ -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;
|
||||
}
|
||||
|
|
@ -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])
|
||||
|
|
@ -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']
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
class FatalError(Exception):
|
||||
pass
|
||||
|
|
@ -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
|
@ -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
|
@ -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)
|