Compare commits

...

532 Commits

Author SHA1 Message Date
Alfred Wingate 5b9d44fee1
TODO: weird docs handling
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2024-03-03 20:58:58 +02:00
Alfred Wingate d8d1767766
TODO: debian remote-id exists
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2024-03-03 20:58:58 +02:00
Alfred Wingate fbd7a4e139
handlers/github: remove
* Mirror removed and api has very strict ratelimits making impractical
  to use.
* https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=f119d00dab0c3bd087faab36f1a44734772a9d75

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2024-03-03 20:58:58 +02:00
Alfred Wingate a7ff66ae04
handlers/pypi: stop using mirrors
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2024-03-03 20:58:58 +02:00
Alfred Wingate 5da26b0719
handlers/rubygems: stop using mirrors
* https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=65850a10f84e1b7a2cdf55392fa1d1f0717193c1

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2024-03-03 20:58:58 +02:00
Alfred Wingate 656f8e155e
handlers/google_code: dead
* https://bugs.gentoo.org/544092

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2024-03-03 20:58:57 +02:00
Alfred Wingate 294dcc2a9c
handlers/freecode: never shouldve been used in ebuilds
* https://bugs.gentoo.org/637970

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2024-03-03 20:58:57 +02:00
Alfred Wingate c628edc26b
handlers/berlios: obselete
* mirror removed in https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=2b72b0462bea5b34bbe4d767ccc44866df81515e
* Rest of the berlios urls use sourceforge now.

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2024-03-03 19:36:20 +02:00
Alfred Wingate 61cbb8e3f9
pre-commit: autoupdate versions
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2024-03-03 19:11:43 +02:00
Alfred Wingate b2cd013b09
Workaround hard to parse $'' strings
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2024-03-03 00:56:41 +02:00
Alfred Wingate e9fd94e1a5
Blacklist urls that don't make sense to scan
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2024-03-03 00:56:41 +02:00
Alfred Wingate e13a62af84
Remove encoding keyword from json()
* Removed in Python 3.9

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2024-03-03 00:56:41 +02:00
Alfred Wingate d93c3154ac
Update GNOME_URL_SOURCE
* It gets redirected eitherway.

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2024-03-03 00:56:41 +02:00
Alfred Wingate 9809d9a805
Add Gitea(+ Forgejo) handler
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2024-03-03 00:56:36 +02:00
Alfred Wingate d217c839a9
Add GitLab handler
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2024-03-02 22:13:44 +02:00
Alfred Wingate aad99f71fe
Use JSON api for PyPi
* "The XML-RPC API will be deprecated in the future. Use of this API is
  not recommended, and existing consumers of the API should migrate to
  the RSS and/or JSON APIs instead."
* "As a result, this API has a very restrictive rate limit and it may be
  necessary to pause between successive requests." As such this also
  gets around this issue for euscan.

https://warehouse.pypa.io/api-reference/xml-rpc.html

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2024-03-02 16:18:34 +02:00
Alfred Wingate 9465c14342
Remove more euscanwww stragglers from TODO
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 07:12:53 +02:00
Alfred Wingate 22915bade5
Fix kde handler
* It appears it was broken in the midst of 8d912379, no apparent
  rationale for it being changed there.

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 07:07:11 +02:00
Alfred Wingate 443b5f62fd
Enable flake8-bugbear linting and fix raised issues
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 06:25:40 +02:00
Alfred Wingate 49f1fbbad1
Remove Python2'isms from classes
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 06:18:19 +02:00
Alfred Wingate a03b420c75
Use OSError instead of alias IOError
https://docs.astral.sh/ruff/rules/os-error-alias/

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 06:15:48 +02:00
Alfred Wingate 6c0b816e73
Use f-strings or .format() over percent style
https://docs.astral.sh/ruff/rules/printf-string-formatting/

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 05:56:40 +02:00
Alfred Wingate 21fe4eafec
Enable pyupgrade linting
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 05:21:49 +02:00
Alfred Wingate 377ba2f727
N806
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 05:19:02 +02:00
Alfred Wingate 9f7ba6c9cd
Address N818
https://peps.python.org/pep-0008/#exception-names

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 05:17:14 +02:00
Alfred Wingate 764bcf9ce8
Enable PEP8 linting in ruff
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 05:16:25 +02:00
Alfred Wingate c0be0e0b67
Fix invalid backslash characters
* https://docs.python.org/3/whatsnew/3.6.html#deprecated-python-behavior

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 05:10:40 +02:00
Alfred Wingate d48699e5fd
Enable all pycodestyle checks in ruff
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 05:02:30 +02:00
Alfred Wingate eedf3c5939
Remove euscanwww leftovers from TODO
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 04:51:30 +02:00
Alfred Wingate 7ac854dc61
Add changelog to python metadata
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 04:43:44 +02:00
Alfred Wingate 0551629a9a
Update MANIFEST.in
* Missed in previous changes

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 04:39:25 +02:00
Alfred Wingate 17c4e19bc5
Filter XMLParsedAsHTMLWarnings
* Parsing xhtml sites would trigger it.

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 04:27:57 +02:00
Alfred Wingate c489b404d1
Temporarily remove README.rst from METADATA
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 01:56:00 +02:00
Alfred Wingate 7b4951977b
Update changelog (at least the 1.0.1 changes)
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 01:41:53 +02:00
Alfred Wingate 86c88e8d30
Change default user-agent
* Better to have it be more meaningful.

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 01:14:05 +02:00
Parona f6bdd66f5f Merge branch 'revamp' into 'master'
Upgrade to PEP517 buildsystem, fix broken gentoolkit usage. Pretty up

See merge request src_prepare/euscan-ng!1
2023-11-15 22:36:44 +00:00
Alfred Wingate 3222f348d8
Use a cleaned up copy of the license
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 00:16:19 +02:00
Alfred Wingate b4749fad3e
Fix inconsistency in --version in regards to copyright headers
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 00:16:19 +02:00
Alfred Wingate 9efcd3a842
Update copyright
* Cleanup inconsistencies in the headers while at it

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 00:16:19 +02:00
Alfred Wingate c40d65a79e
Remove man page
* Will look into alternatives that either most likely create a final man
  page during sdist creation.

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 00:16:19 +02:00
Alfred Wingate c6e6e25862
Add publishing capability to CI
* Not yet enabled automatically due to gentoolkit

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 00:16:19 +02:00
Alfred Wingate 6c90268712
.git-blame-ignore-revs: Ignore mass formatting commits
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 00:16:19 +02:00
Alfred Wingate a8f35aee25
Fix issues pointed out by ruff
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-16 00:16:07 +02:00
Alfred Wingate 70f88ed37d
Run isort on project
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-15 23:30:40 +02:00
Alfred Wingate d860708ec9
Run black on project
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-15 23:30:40 +02:00
Alfred Wingate a91775919c
Add pre-commit config
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-15 23:30:40 +02:00
Alfred Wingate 02fd3a9e79
Add gitlab CI
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-15 23:30:40 +02:00
Alfred Wingate 65e77ac533
Configure linting and formatting tools
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-15 23:30:39 +02:00
Alfred Wingate dfa0bb7424
Add python3.12 compatability
* imp and find_loader got removed in py3.12

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-15 23:30:39 +02:00
Alfred Wingate 50a23b71dd
Get version from git with setuptools_scm
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-15 23:30:39 +02:00
Alfred Wingate cc2d715b6d
Transition to PEP517 buildsystem
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-15 23:30:39 +02:00
Alfred Wingate bae87b0877
Fix euscan by using portage MetadataXML over gentoolkit Metadata
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-15 23:30:39 +02:00
Alfred Wingate c51d3fc70c
Remove helper scripts
* These scripts will be broken after PEP517 transition.

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-15 23:30:39 +02:00
Alfred Wingate c873e1520d
Change source layout
* In preparation for PEP517 transition.

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-15 23:30:39 +02:00
Alfred Wingate ec7399752c
Remove the djano webservice in its entirety
Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-15 23:30:06 +02:00
Maciej Barć 962f26ae05
update setup files
Signed-off-by: Maciej Barć <xgqt@protonmail.com>
2021-02-26 19:04:36 +01:00
Maciej Barć be2d26bfd9
makefile: add all target 2020-09-16 15:20:31 +02:00
Maciej Barć 184085c20d
makefile: add 2020-09-12 01:06:02 +02:00
Maciej Barć cc992227fc
manifest: update 2020-09-12 01:04:43 +02:00
Maciej Barć 73f55dfaab
license: rename from copying 2020-09-11 21:52:34 +02:00
Maciej Barć e99737131d
setup: split web part 2020-09-11 21:41:20 +02:00
Maciej Barć 5dc5751432
gitignore: update 2020-09-11 21:40:02 +02:00
Maciej Barć c76b0be9f5
thanks: remove 2020-09-11 21:28:23 +02:00
Maciej Barć b0da1f1b10
readme: update ng 2020-09-11 21:03:34 +02:00
Maciej Barć 0ffb357689
fork 2020-09-11 14:48:42 +02:00
Bernard Cafarelli fff319bd8b
Fix helper regex for python 3.7 2020-01-14 16:29:58 +01:00
Bernard Cafarelli 8e25050f4a
Disable Content-disposition check for now
Some packages (nextcloud-client) for example have different filename in
this header, and so I miss new versions
2020-01-07 15:35:40 +01:00
Bernard Cafarelli 90464f8697
Fix brute-force short option 2020-01-06 22:19:23 +01:00
Bernard Cafarelli b25c66e9ab
Update some blacklists
Also fix blacklist log message
2019-12-05 19:03:49 +01:00
Bernard Cafarelli 9afec1a034
More python3 fixes 2019-12-05 19:00:02 +01:00
Bernard Cafarelli 94c3eeba49
Initial python3 compatibility 2019-12-05 17:46:19 +01:00
Corentin Chary 2fedc7450d Merge pull request #29 from ercpe/pypi-https
Use HTTPS for pypi's http api
2016-10-15 16:31:07 +02:00
Johann Schmitz 96f025f5fc
Use HTTPS for pypi's http api
pypi started to refuse plain http connections to it's api.
2016-06-19 06:12:27 +02:00
Corentin Chary 2d70845115 euscan/handlers/pypi: fix scan_url()
Probably never worked...
2015-03-09 11:07:00 +01:00
Corentin Chary 84e32e1554 processing: fix scan_metadata.py when the new maintainer name is None 2013-11-21 10:28:22 +01:00
Corentin Chary c130e59b28 fixes 2013-09-29 11:01:09 +02:00
Corentin Chary 8c6bdebcab fixes 2013-09-29 11:01:09 +02:00
Corentin Chary 4fef44668c Merge pull request #22 from volpino/master
Adding links to bugs.g.o and qa-reports.g.o and minor fixes
2013-08-27 00:51:12 -07:00
volpino 7194c542e2 Adding links to bugs.g.o and qa-reports.g.o 2013-08-26 17:33:54 +02:00
volpino 3b2f88c683 adding xml to the available formats 2013-08-26 17:08:59 +02:00
Corentin Chary 55bc34b075 fixes 2013-07-10 09:43:36 +02:00
Corentin Chary 0c59e72a8a djeuscan: small scan fixes 2013-04-02 10:17:37 +02:00
Corentin Chary 0225553eeb euscan_captcha: fix captcha 2013-04-02 10:17:11 +02:00
volpino bbc91972f9 euscanwwW: Fixing links in stabilization feed
Signed-off-by: volpino <fox91@anche.no>
2013-03-09 13:09:44 +01:00
volpino 745a7fd15a euscanwww: Adding link to stabilization feed
Signed-off-by: volpino <fox91@anche.no>
2013-03-09 13:00:51 +01:00
volpino 23fb315a5f euscanwww: minor fixes to feeds.py
Signed-off-by: volpino <fox91@anche.no>
2013-03-09 12:35:39 +01:00
volpino 4dfcd92aa5 euscanwww: Fixing and using vtype in stabilization_candidates, added db_index
Signed-off-by: volpino <fox91@anche.no>
2013-03-09 12:07:47 +01:00
volpino c55d09a031 euscanwww: Added feed for stabilization candidates. Still a prototype though
Signed-off-by: volpino <fox91@anche.no>
2013-02-26 09:41:06 +01:00
volpino 4b84dd54b5 Updating gitignore
Signed-off-by: volpino <fox91@anche.no>
2013-02-23 18:44:44 +01:00
volpino b5b05e9502 euscanwww: Added PoC of stabilization candidates feature
Signed-off-by: volpino <fox91@anche.no>
2013-02-23 18:43:43 +01:00
volpino 9254040b38 Merge branch 'master' of github.com:volpino/euscan 2013-02-23 12:29:39 +01:00
volpino 240dec4b42 minor fix
Signed-off-by: volpino <fox91@anche.no>
2013-02-23 12:29:05 +01:00
volpino 829494163f updating TODO
Signed-off-by: volpino <fox91@anche.no>
2013-02-23 12:29:05 +01:00
volpino 12b504961d euscanwww: Added category description, overlay description, homepage and path
Minor changes:
- Fixed broken tests (alive field was still there)
- Added plural to Category model

Signed-off-by: volpino <fox91@anche.no>
2013-02-23 12:29:05 +01:00
volpino b41ffe3609 euscanwww: PEP8 fixes
Signed-off-by: volpino <fox91@anche.no>
2013-02-23 12:29:05 +01:00
volpino f26add40c9 euscan: minor PEP8 fix
Signed-off-by: volpino <fox91@anche.no>
2013-02-23 12:29:04 +01:00
volpino 2aa4d5d481 euscanwww: adding missing migration for index on handler
Signed-off-by: volpino <fox91@anche.no>
2013-02-23 12:29:04 +01:00
volpino 21d026becf euscanwww: Added floatformat to average confidence to round
Signed-off-by: volpino <fox91@anche.no>
2013-02-23 12:29:04 +01:00
volpino 259e466db8 euscanwww: Indentation must be a multiple of 4
Signed-off-by: volpino <fox91@anche.no>
2013-02-23 12:29:04 +01:00
volpino 6c360cd53d updating TODO
Signed-off-by: volpino <fox91@anche.no>
2013-01-26 10:32:30 +01:00
volpino 26a4186b5d Merge branch 'master' of https://github.com/iksaif/euscan 2013-01-26 10:29:25 +01:00
volpino 4f0c1b3996 euscanwww: Added category description, overlay description, homepage and path
Minor changes:
- Fixed broken tests (alive field was still there)
- Added plural to Category model

Signed-off-by: volpino <fox91@anche.no>
2013-01-26 10:27:02 +01:00
Corentin Chary b2726bd058 fixes 2013-01-16 10:08:24 +01:00
volpino 76c4090f92 euscanwww: PEP8 fixes
Signed-off-by: volpino <fox91@anche.no>
2013-01-07 21:41:50 +01:00
volpino 541eb71188 Merge branch 'master' of https://github.com/iksaif/euscan 2013-01-07 20:33:14 +01:00
Corentin Chary d2685af861 djeuscan: add lost migrations
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-12-12 22:56:09 +01:00
Corentin Chary e42ba7dfd0 djeuscan: rework the scan process, don't use alive anymore
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-12-12 22:54:50 +01:00
volpino 907eff4214 euscan: minor PEP8 fix
Signed-off-by: volpino <fox91@anche.no>
2012-12-05 18:43:32 +01:00
volpino f7968dddcb Merge branch 'master' of https://github.com/iksaif/euscan 2012-12-01 23:36:04 +01:00
Corentin Chary dfb7a7b986 Merge pull request #19 from EvaSDK/master
Add gnome handler
2012-12-01 04:55:11 -08:00
Gilles Dartiguelongue e249199cae Fix issues raised in pull request #19
* Replace print/raise by eoutput usage.
    * Fix scan_url function to properly format arguments of scan_pkg.
2012-11-30 23:39:25 +01:00
volpino d38fc26b72 euscanwww: adding missing migration for index on handler
Signed-off-by: volpino <fox91@anche.no>
2012-11-30 11:42:19 +01:00
volpino 058a2fe38c euscanwww: Added floatformat to average confidence to round
Signed-off-by: volpino <fox91@anche.no>
2012-11-29 12:02:43 +01:00
volpino 8c53d7c03e euscanwww: Indentation must be a multiple of 4
Signed-off-by: volpino <fox91@anche.no>
2012-11-28 11:22:28 +01:00
Corentin Chary e89edb588e euscanwww: handle '' handler
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-11-27 21:48:33 +01:00
volpino 3f47a08a54 euscanwww: Improved query for aggregating handler's data
Signed-off-by: volpino <fox91@anche.no>
2012-11-27 14:16:56 +01:00
Corentin Chary c6a0c29401 euscanwww: tweak the new handler code
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-11-26 23:39:34 +01:00
Corentin Chary a723d30a33 euscanwww: reorder some settings
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-11-26 23:39:11 +01:00
volpino 7380daf7e9 euscanwww: Fixing metadata and ebuild urls
Signed-off-by: volpino <fox91@anche.no>
2012-11-26 15:38:27 +01:00
volpino a8f69e8128 euscanwww: per handler package list
Signed-off-by: volpino <fox91@anche.no>
2012-11-26 14:55:49 +01:00
volpino 8ad3ed2897 euscanwww: Handler's statistics
Signed-off-by: volpino <fox91@anche.no>
2012-11-26 14:32:39 +01:00
volpino 1af51ec674 euscanwww: moving "Statistics" at the bottom of the menu bar
Signed-off-by: volpino <fox91@anche.no>
2012-11-26 12:22:08 +01:00
volpino 0601222691 euscanwww: slot is not part of unique_together. Better version strings
Signed-off-by: volpino <fox91@anche.no>
2012-11-25 23:18:47 +01:00
Gilles Dartiguelongue 7e635b380f Add gnome handler 2012-11-24 00:42:11 +01:00
Corentin Chary 882f8b0fba DEBUG=False by default 2012-11-23 10:25:43 +01:00
Corentin Chary e8670bc853 Return HttpResponseNotFound(), got 20 exceptions emails this morning :D
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-11-23 10:25:30 +01:00
Corentin Chary c135c35670 Update TODO
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-11-19 22:57:31 +01:00
Corentin Chary 8a11e1fc39 djeuscan: temporary fix for ebuild/metadata
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-11-19 22:54:52 +01:00
Corentin Chary fa4916f5f8 Update TODO
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-11-19 22:50:41 +01:00
Corentin Chary 0efe8292b1 Don't remove everything, only cache 2012-11-12 23:26:43 +01:00
volpino 9f5402f896 euscanwww: Favourite/Unfavourite template code refactored
* Now is more DRY, the JS code and the HTML code are in one place
* It works even without JS

Signed-off-by: volpino <fox91@anche.no>
2012-11-08 18:57:29 +01:00
volpino 9143301875 euscanwww: Refresh package button works even without JS
Signed-off-by: volpino <fox91@anche.no>
2012-11-08 16:22:03 +01:00
volpino 853e92c56e euscanwww: Simple link instead of form
Signed-off-by: volpino <fox91@anche.no>
2012-11-08 15:50:19 +01:00
volpino 90f55433d1 euscanwww: Upstream urls now are anchors
Signed-off-by: volpino <fox91@anche.no>
2012-11-08 15:46:16 +01:00
volpino 7f55e00ed0 euscanwww: raise Http404 -> return HttpResponseNotFound()
Signed-off-by: volpino <fox91@anche.no>
2012-11-08 15:25:49 +01:00
volpino c648d7e756 euscanwww: Showing ebuild and metadata in package details page
Signed-off-by: volpino <fox91@anche.no>
2012-11-08 15:22:53 +01:00
volpino effab2015b euscanwww: Use Version.tag to be more DRY
Signed-off-by: volpino <fox91@anche.no>
2012-11-08 15:19:45 +01:00
volpino b838f3cb59 Merge branch 'master' of https://github.com/iksaif/euscan
Signed-off-by: volpino <fox91@anche.no>
2012-11-04 18:04:22 +01:00
volpino 6296f4c0f3 euscanwww: South migration for keeping data for the new accounts app
Signed-off-by: volpino <fox91@anche.no>
2012-11-04 17:58:18 +01:00
Corentin Chary 5c460e895a djeuscan/tasks: fix update_portage() and layman --sync 2012-11-04 12:30:22 +01:00
volpino 7ed088e705 Updating TODO
Signed-off-by: volpino <fox91@anche.no>
2012-11-02 20:17:16 +01:00
volpino c04b4c8187 euscanwww: Adding make.conf and overlays info to config page
Signed-off-by: volpino <fox91@anche.no>
2012-11-02 20:15:51 +01:00
volpino 4751eaf7a5 euscanwww: Added migration for deleting UserProfile
Signed-off-by: volpino <fox91@anche.no>
2012-11-02 20:15:51 +01:00
volpino 30f209b816 euscanwww: Make euscan_captcha a real app
Signed-off-by: volpino <fox91@anche.no>
2012-11-02 20:15:51 +01:00
volpino c31076ddb4 euscanwww: Moving all account related stuff to a separate app
Note: This commit could break things, the userprofile model has been
moved so the db layout must change (some alter table commands are
needed to don't lose data)

Signed-off-by: volpino <fox91@anche.no>
2012-11-02 20:15:51 +01:00
volpino 2bf0061979 euscanwww: removed useless 'print'
Signed-off-by: volpino <fox91@anche.no>
2012-11-02 20:15:50 +01:00
volpino 352dfa9e14 euscanwww: moving captcha app where the apps should be
Signed-off-by: volpino <fox91@anche.no>
2012-11-02 20:15:50 +01:00
volpino 6f421cfe13 euscanwww: test fixes and minor PEP8 fixes
Signed-off-by: volpino <fox91@anche.no>
2012-11-02 20:15:50 +01:00
volpino 1abc4d409e euscanwww: fixing urls.py to be more DRY
Signed-off-by: volpino <fox91@anche.no>
2012-11-02 20:15:45 +01:00
volpino 48c1eadab4 Merge branch 'master' of https://github.com/iksaif/euscan
Conflicts:
	TODO
	euscanwww/djeuscan/processing/scan/scan_portage.py
	euscanwww/djeuscan/tasks.py
	euscanwww/djeuscan/templates/euscan/_package_details.html

Signed-off-by: volpino <fox91@anche.no>
2012-10-30 20:27:37 +01:00
Corentin Chary df1da16e45 euscan/handlers: we need the file version
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-10-29 13:06:06 +01:00
Corentin Chary 90c7f27b95 djeuscan/processing: fix scan_upstream after scan_portage
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-10-29 13:06:06 +01:00
Corentin Chary c40528f7d2 Update TODO
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-10-29 13:06:05 +01:00
Corentin Chary 5a8d7e8932 euscanwww: use maintainers names, not ids
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-10-29 13:06:05 +01:00
Corentin Chary 808acfe13a django-recaptcha 0.0.5 compat
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-10-29 13:06:05 +01:00
volpino 975f7b1dbf euscanwww: Adding an about config page
Signed-off-by: volpino <fox91@anche.no>
2012-10-29 13:06:04 +01:00
volpino 4b3e0bd525 euscanwww: Upgrading Bootstrap toogle buttons
Signed-off-by: volpino <fox91@anche.no>
2012-10-29 13:06:04 +01:00
volpino c519f6b28a euscan: last_version property added
Signed-off-by: volpino <fox91@anche.no>
2012-10-29 13:06:04 +01:00
volpino ddd8be39f5 euscanwww: Wrapping herds and maintainers in <p> to put them in newlines
Signed-off-by: volpino <fox91@anche.no>
2012-10-29 13:06:04 +01:00
volpino 565c5823c1 euscan: deb handler - adding support for Packages.gz or Packages.bz2 and version detection fix
Signed-off-by: volpino <fox91@anche.no>
2012-10-29 13:06:04 +01:00
volpino ef20139730 euscan: Removing http cache from TODO
Signed-off-by: volpino <fox91@anche.no>
2012-10-29 13:06:04 +01:00
volpino 3d058946b6 euscanwww: making get parameter shorter
Signed-off-by: volpino <fox91@anche.no>
2012-10-29 13:06:03 +01:00
volpino 75b5bcc32f euscanwww: Adding an option to run upstream scanning after an update in portage
Signed-off-by: volpino <fox91@anche.no>
2012-10-29 13:06:03 +01:00
volpino 056b00f709 euscan: Adding naive deb handler, TODO updated
Signed-off-by: volpino <fox91@anche.no>
2012-10-29 13:06:03 +01:00
volpino d2433c1b3c euscan: Adding freecode handler
Uses experimental remote-id "freecode"

Signed-off-by: volpino <fox91@anche.no>
2012-10-29 13:06:03 +01:00
volpino 16e14bf791 euscanwww: Created a feed for scan world with packages in GET
Note: Check if passing parameters in GET is good, there's the risk of
looong urls

Signed-off-by: volpino <fox91@anche.no>
2012-10-29 13:06:02 +01:00
volpino 60deecd853 euscan: Adding support for disabling handlers
Signed-off-by: volpino <fox91@anche.no>
2012-10-29 13:06:02 +01:00
Corentin Chary 2bd6c03b3b djeuscan: really fix scan on demand
don't use stupid locks, only rate limit.

Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-10-10 09:36:25 +02:00
volpino c02072cb16 euscanwww: Adding an about config page
Signed-off-by: volpino <fox91@anche.no>
2012-09-24 16:47:55 +02:00
volpino f257c40aec euscanwww: Upgrading Bootstrap toogle buttons
Signed-off-by: volpino <fox91@anche.no>
2012-09-24 15:36:11 +02:00
volpino f9f18fbce2 euscan: last_version property added
Signed-off-by: volpino <fox91@anche.no>
2012-09-22 16:08:38 +02:00
volpino 04be40e8e0 euscanwww: Wrapping herds and maintainers in <p> to put them in newlines
Signed-off-by: volpino <fox91@anche.no>
2012-09-22 15:45:07 +02:00
volpino 26fae25aec euscan: deb handler - adding support for Packages.gz or Packages.bz2 and version detection fix
Signed-off-by: volpino <fox91@anche.no>
2012-09-21 19:03:53 +02:00
volpino fd204f7b1f euscan: Removing http cache from TODO
Signed-off-by: volpino <fox91@anche.no>
2012-09-21 17:12:43 +02:00
volpino 15d67b3060 euscanwww: making get parameter shorter
Signed-off-by: volpino <fox91@anche.no>
2012-09-21 17:10:51 +02:00
Corentin Chary 9afb31fc65 euscan: fix #435118 and #435120
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-09-15 23:21:30 +02:00
volpino 57c80cf954 euscanwww: Adding an option to run upstream scanning after an update in portage
Signed-off-by: volpino <fox91@anche.no>
2012-09-14 17:22:18 +02:00
volpino 0203a465ee euscan: Adding naive deb handler, TODO updated
Signed-off-by: volpino <fox91@anche.no>
2012-09-14 16:56:52 +02:00
volpino 4b29c6db2b euscan: Adding freecode handler
Uses experimental remote-id "freecode"

Signed-off-by: volpino <fox91@anche.no>
2012-09-14 16:21:30 +02:00
volpino 16f8d0c355 euscanwww: Created a feed for scan world with packages in GET
Note: Check if passing parameters in GET is good, there's the risk of
looong urls

Signed-off-by: volpino <fox91@anche.no>
2012-09-14 15:25:08 +02:00
volpino 58381f9808 Merge branch 'master' of https://github.com/iksaif/euscan 2012-09-14 11:34:56 +02:00
volpino 14854dbadd euscan: Adding support for disabling handlers
Signed-off-by: volpino <fox91@anche.no>
2012-09-14 11:33:57 +02:00
Corentin Chary 89f3192937 euscan: update TODO
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-09-14 10:42:53 +02:00
Corentin Chary 1fc42e083d Merge remote-tracking branch 'origin/master'
Conflicts:
	euscanwww/djeuscan/templates/euscan/accounts/euscan_email.txt

Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-09-14 10:31:19 +02:00
Corentin Chary e13d54100d euscanwww/templates: minor fixes
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-09-14 10:29:24 +02:00
Corentin Chary 32506e252a euscanwww: small scan related fixes
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-09-14 10:29:06 +02:00
Corentin Chary a1cc8425f2 euscan: TODO
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-09-14 10:28:26 +02:00
Corentin Chary e1254df431 Merge remote-tracking branch 'fox/master' 2012-09-14 10:26:56 +02:00
Corentin Chary e25620b862 Merge remote-tracking branch 'origin/master' 2012-09-14 10:26:50 +02:00
volpino 80ca711565 euscanwww: Improved email template
Now the code is quite cryptic but it's to remove useless blank lines
in the final output.

Signed-off-by: volpino <fox91@anche.no>
2012-09-03 15:09:12 +02:00
volpino 2019b245e8 euscan: Adding config file support
Signed-off-by: volpino <fox91@anche.no>
2012-09-02 18:58:01 +02:00
volpino 332b5d7c80 euscan: Added XML output
Signed-off-by: volpino <fox91@anche.no>
2012-09-02 18:39:04 +02:00
volpino 59b5eb77ac Merge branch 'master' of https://github.com/iksaif/euscan 2012-09-02 17:53:37 +02:00
Corentin Chary b8df26b211 euscan: update TODO
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-08-19 18:41:17 +02:00
volpino 519f335966 euscan: PEP8 compliant code
Signed-off-by: volpino <fox91@anche.no>
2012-08-15 15:37:55 +02:00
volpino 2557b74beb Merge branch 'master' of https://github.com/iksaif/euscan 2012-08-15 15:34:15 +02:00
volpino 269fc0afa5 euscanwww: Fixing all templates to be XHTML compliant
Signed-off-by: volpino <fox91@anche.no>
2012-08-15 15:33:44 +02:00
volpino d66c2dff99 euscan: Adding missing requirement ansi2html
Signed-off-by: volpino <fox91@anche.no>
2012-08-15 15:31:50 +02:00
volpino 68da776d07 euscanwww: Fixing preferences form errors
Signed-off-by: volpino <fox91@anche.no>
2012-08-15 15:25:22 +02:00
Corentin Chary b97fb74dc3 euscan: fix mangling
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-08-15 11:29:29 +02:00
Corentin Chary bbfcc3d6d5 euscan: misc fixes
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-08-15 11:04:29 +02:00
volpino d8de359256 euscanwww: Added feeds help page
Signed-off-by: volpino <fox91@anche.no>
2012-08-14 15:32:54 +02:00
volpino 99d97cc2a1 euscanwww: The input of a field with errors is red
Signed-off-by: volpino <fox91@anche.no>
2012-08-14 14:26:28 +02:00
volpino 3ca42ce848 euscanwww: user feed link is displayed on every page for registered users
Signed-off-by: volpino <fox91@anche.no>
2012-08-14 14:19:57 +02:00
volpino 0d956b4c9f euscanwww: Adding missing login_required to UserFeed
Signed-off-by: volpino <fox91@anche.no>
2012-08-14 14:19:38 +02:00
volpino 39e1f95128 euscanwww: Fixed runtests.py and added a simple test for user profile
Signed-off-by: volpino <fox91@anche.no>
2012-08-14 14:07:23 +02:00
volpino ec2e132583 euscanwww: Minor cleanings
Signed-off-by: volpino <fox91@anche.no>
2012-08-14 13:51:07 +02:00
volpino f2a4d5d4a4 euscanwww: Better login template
Signed-off-by: volpino <fox91@anche.no>
2012-08-14 12:15:39 +02:00
Corentin Chary 88b15c18d2 djeuscan: enhance email template
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-08-14 11:45:52 +02:00
Corentin Chary 2b823fb905 djeuscan: better email template
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-08-14 10:27:00 +02:00
Corentin Chary 97830775c8 djeuscan: fix some small bugs
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-08-14 09:11:23 +02:00
volpino d1058aed8b euscanwww: initial implementation of euscan updates email
Signed-off-by: volpino <fox91@anche.no>
2012-08-11 15:09:42 +02:00
volpino 1bb4f14faa euscanwww: Adding more options to preferences, implementing more filters for feeds
Signed-off-by: volpino <fox91@anche.no>
2012-08-11 13:32:56 +02:00
volpino f04f28aacc euscanwww: Added watch/unwatch button to scan world
Signed-off-by: volpino <fox91@anche.no>
2012-08-10 18:16:40 +02:00
volpino 58d6ecc490 euscanwww: Changed all feeds to support url options
Signed-off-by: volpino <fox91@anche.no>
2012-08-09 12:20:19 +02:00
volpino 8b39853b5f euscanwww: Adding support for GET options in feed
Signed-off-by: volpino <fox91@anche.no>
2012-08-08 15:19:31 +02:00
volpino 78bc2520a7 euscanwww: Adding PoC switches for feed settings
Signed-off-by: volpino <fox91@anche.no>
2012-08-08 14:33:37 +02:00
volpino 225350f584 euscanwww: Swapping watch/unwatch icons
Signed-off-by: volpino <fox91@anche.no>
2012-08-08 13:31:59 +02:00
volpino edb8d88fb6 euscanwww: Adding basic custom user feed
Signed-off-by: volpino <fox91@anche.no>
2012-08-08 13:30:56 +02:00
volpino 2b75908205 Merge branch 'master' of https://github.com/iksaif/euscan 2012-08-08 12:21:07 +02:00
volpino 0124465806 euscan: Improving Berlios and Sourceforge handlers
Signed-off-by: volpino <fox91@anche.no>
2012-08-08 12:20:33 +02:00
volpino 77f1cb52ea euscanwww: Improved forms UI, added preferences page and change password
Signed-off-by: volpino <fox91@anche.no>
2012-08-08 10:47:58 +02:00
volpino c4e3c4c04a euscanwww: Fixing typo in dashboard
Signed-off-by: volpino <fox91@anche.no>
2012-08-08 09:28:48 +02:00
volpino 827af401a9 euscanwww: Adding requirement to setup.py
Signed-off-by: volpino <fox91@anche.no>
2012-08-08 09:27:42 +02:00
volpino 49f33796a7 euscanwww: Corrected typo in favourite overlay
Signed-off-by: volpino <fox91@anche.no>
2012-08-08 08:58:07 +02:00
volpino d3de157a1b euscan: Fixing wrong priority
Signed-off-by: volpino <fox91@anche.no>
2012-08-07 16:45:28 +02:00
volpino a31b6fa4a8 euscan: Adding new handlers: google-code, berlios, sourceforge
Signed-off-by: volpino <fox91@anche.no>
2012-08-07 16:42:27 +02:00
volpino ea6e421d16 euscan: Fixing failure while scanning postgresql-server
Signed-off-by: volpino <fox91@anche.no>
2012-08-07 11:16:05 +02:00
volpino 952d9505b2 euscan/euscawww: Removing unused imports, fixed some typos and PEP8 cleaning
Signed-off-by: volpino <fox91@anche.no>
2012-08-07 09:39:49 +02:00
Corentin Chary 5caca5f41f euscan: default mangling rule is gentoo
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-08-07 09:32:11 +02:00
Corentin Chary b03541c97d euscanwww/tasks: ungroup tasks for now, use immutables tasks
There is a bug in celery preventing (group | group | task)() chains
to work. Was reported but not yet fixed.

Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-08-07 08:46:05 +02:00
Corentin Chary c2d9236d06 euscan: update TODO
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-08-07 08:45:58 +02:00
Corentin Chary aa966bf837 euscan: small handler fixes
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-08-07 08:44:26 +02:00
Corentin Chary d5bf980779 euscan: shuffle mirrors
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-08-07 08:44:02 +02:00
Corentin Chary bd034cadf1 euscan: restore reload_gentoolkit()
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-08-07 08:43:23 +02:00
Corentin Chary f6e2882b44 euscan: optimize SRC_URI fetching
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-08-06 23:30:29 +02:00
Corentin Chary f37b9a7740 euscan/handlers: fix cpan version comparaisons
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-08-04 16:22:12 +02:00
Corentin Chary 0c97fcd42e euscanwww: some optimizations
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-08-03 21:59:09 +02:00
Corentin Chary 94f6b7541c euscanwww: misc fixes
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-08-03 21:58:24 +02:00
Corentin Chary d0aceaeec4 euscanwww: fix captcha <table> must be inside <form>
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-08-03 21:57:41 +02:00
Corentin Chary 62b1fbba4e euscanwww: fix tasks
- group_one was broken
- new way of calling  consume refresh queries

Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-08-03 21:55:59 +02:00
Corentin Chary a8e6b09125 eucanwww: add recaptcha support
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-08-03 21:55:23 +02:00
Corentin Chary 8d91237988 euscan/handlers: rework handlers, better remote-id + watch support
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-08-03 21:50:54 +02:00
volpino d262b935e6 euscan: hopefully better CPAN gentoo version mangling
Signed-off-by: volpino <fox91@anche.no>
2012-07-31 09:50:11 +02:00
volpino d34e3d4c4c euscanwww: Added missing icons and truncatechars
Signed-off-by: volpino <fox91@anche.no>
2012-07-30 00:08:02 +02:00
volpino 6178d66f0d euscanwww: removing unused import and PEP8 cleaning
Signed-off-by: volpino <fox91@anche.no>
2012-07-29 10:13:17 +02:00
volpino a88824309d Merge branch 'master' of https://github.com/iksaif/euscan 2012-07-29 10:05:20 +02:00
volpino c49914af23 euscan: fixed handler name with remote-id
Signed-off-by: volpino <fox91@anche.no>
2012-07-28 18:16:16 +02:00
Corentin Chary 6ce658fa0d euscan: stuff
(yeah, sorry ..)

Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-28 11:39:38 +02:00
Corentin Chary 6ec059bdc2 Merge remote-tracking branch 'fox/master' 2012-07-28 11:32:41 +02:00
Corentin Chary 4e317fc145 djeuscan: add sendmail email backend
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-28 10:15:03 +02:00
volpino f470c4f059 euscan: performance improvements
Signed-off-by: volpino <fox91@anche.no>
2012-07-27 13:58:51 +02:00
volpino 29f143ff87 euscanwww: messages becomes a property
Signed-off-by: volpino <fox91@anche.no>
2012-07-27 12:55:57 +02:00
volpino fd8c61d7e8 euscanwww: Added some "truncatechars" filters
Signed-off-by: volpino <fox91@anche.no>
2012-07-27 12:28:53 +02:00
volpino 34e966f5de euscanwww: Adding queue position in refresh package alert message
Signed-off-by: volpino <fox91@anche.no>
2012-07-27 12:21:48 +02:00
volpino 31e3dd66d8 euscanwww: Prevent not deterministic QuerySet order when slicing
Signed-off-by: volpino <fox91@anche.no>
2012-07-27 11:37:58 +02:00
volpino 04265dacff euscan: just PEP8 cleaning
Signed-off-by: volpino <fox91@anche.no>
2012-07-27 11:33:27 +02:00
volpino 2c9b44f4d9 Merge branch 'master' of https://github.com/iksaif/euscan 2012-07-27 11:27:22 +02:00
volpino 326658acb9 euscan: confidence tweak in generic handler
Signed-off-by: volpino <fox91@anche.no>
2012-07-27 11:26:54 +02:00
Corentin Chary 6dce7707c8 euscan: fix some \n issues
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-26 21:31:10 +02:00
Corentin Chary 8d65eaea1f djeuscan: use crontabs and depends on djcelery migrations
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-26 21:18:43 +02:00
Corentin Chary 89408dde2b djeuscan: pkg.metadata can fail
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-26 21:18:31 +02:00
Corentin Chary 3c30cae6eb djeuscan: use store_true for populqte in scan_metadata
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-26 21:17:45 +02:00
Corentin Chary 29b1ad557a Merge remote-tracking branch 'fox/master'
Conflicts:
	euscanwww/djeuscan/helpers.py

Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-26 21:17:10 +02:00
volpino 35603fd704 euscan: Added remote-id handler
Signed-off-by: volpino <fox91@anche.no>
2012-07-26 17:46:53 +02:00
volpino ad0c946230 euscan: patch_metadata regex fix to match bz2 sources
Signed-off-by: volpino <fox91@anche.no>
2012-07-26 15:50:30 +02:00
volpino 1835327d5c euscan: Fixed typo
Signed-off-by: volpino <fox91@anche.no>
2012-07-26 14:50:47 +02:00
volpino 7b9560ced0 euscanwww: Moving from XXXAssociation to UserProfile
Signed-off-by: volpino <fox91@anche.no>
2012-07-26 14:37:03 +02:00
volpino 3ef800b68d Merge branch 'master' of https://github.com/iksaif/euscan
Conflicts:
	bin/euscan_patch_metadata
	euscanwww/djeuscan/views.py
	pym/euscan/handlers/__init__.py
	pym/euscan/handlers/kde.py
	pym/euscan/handlers/url/cpan.py
	pym/euscan/handlers/url/generic.py
	pym/euscan/handlers/url/github.py
	pym/euscan/handlers/url/php.py
	pym/euscan/handlers/url/pypi.py
	pym/euscan/handlers/url/rubygem.py
	pym/euscan/scan.py

Signed-off-by: volpino <fox91@anche.no>
2012-07-26 10:57:38 +02:00
volpino 12bf1fc75b euscan: Redesigning the handlers layout
Signed-off-by: volpino <fox91@anche.no>
2012-07-26 10:44:10 +02:00
Corentin Chary f670645747 Revert "djeuscan: helpers.py is actually unused"
This reverts commit 8146dc1f44.
2012-07-25 17:08:19 +02:00
Corentin Chary 28b913295a euscan: ignore robots.txt for fedorahosted.org
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-25 17:04:37 +02:00
Corentin Chary 1a7efc58a7 djeuscan: tweak admin.py
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-25 16:53:17 +02:00
Corentin Chary a12e2c42ea djeuscan: move problem to another page, use an icon, restrict to registered
We may move it back to the package page later.

Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-25 16:53:17 +02:00
volpino 112313ab7f euscan: generic handler fixes
* urljoin was broken with dirs ("http://site.com/lol" joined with "wat"
  produces http://site.com/wat)
* fixed _v regex, don't match what is not needed

Signed-off-by: volpino <fox91@anche.no>
2012-07-25 16:53:17 +02:00
volpino 9f164ed22c euscanwww: Removing useless stuff while creating watch tag
* Removing useless options or actions
* Fixing handling of substitution regex

Signed-off-by: volpino <fox91@anche.no>
2012-07-25 16:53:17 +02:00
volpino e2890c6364 euscan: Added watch handler, fixed generic one
Signed-off-by: volpino <fox91@anche.no>
2012-07-25 16:53:17 +02:00
volpino 795dcb1414 euscanwww: == None -> is None
Signed-off-by: volpino <fox91@anche.no>
2012-07-25 16:53:17 +02:00
volpino 1cf5d0726a euscan: handlers now use a Package object instead of cpv
Signed-off-by: volpino <fox91@anche.no>
2012-07-25 16:53:16 +02:00
volpino 67654ee0b4 euscan: Progressbar on stderr
Signed-off-by: volpino <fox91@anche.no>
2012-07-25 16:53:16 +02:00
volpino cf8f9ae9cc euscanwww: From fixture to south data migration
Signed-off-by: volpino <fox91@anche.no>
2012-07-25 16:53:16 +02:00
volpino 83cc025170 euscan: euscan_patch_metadata --diff option
Signed-off-by: volpino <fox91@anche.no>
2012-07-25 16:53:16 +02:00
Corentin Chary 8146dc1f44 djeuscan: helpers.py is actually unused
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-25 16:53:16 +02:00
volpino 36e1aa6d12 euscan: euscan_path_metadata diff using difflib
Signed-off-by: volpino <fox91@anche.no>
2012-07-25 13:49:47 +02:00
volpino 21c6a9107d euscan: generic handler fixes
* urljoin was broken with dirs ("http://site.com/lol" joined with "wat"
  produces http://site.com/wat)
* fixed _v regex, don't match what is not needed

Signed-off-by: volpino <fox91@anche.no>
2012-07-25 10:44:15 +02:00
volpino 29101f88f8 euscanwww: Removing useless stuff while creating watch tag
* Removing useless options or actions
* Fixing handling of substitution regex

Signed-off-by: volpino <fox91@anche.no>
2012-07-25 10:19:27 +02:00
volpino c35065e344 euscan: Added watch handler, fixed generic one
Signed-off-by: volpino <fox91@anche.no>
2012-07-24 17:48:20 +02:00
Corentin Chary 7cdd10f028 Revert "djeuscan: helpers.py is actually unused"
This reverts commit be9d28c255.
2012-07-24 09:04:20 +02:00
volpino 266838b308 euscanwww: == None -> is None
Signed-off-by: volpino <fox91@anche.no>
2012-07-24 09:03:14 +02:00
volpino cc7c378648 Revert "djeuscan: helpers.py is actually unused"
This reverts commit be9d28c255.
2012-07-24 09:02:01 +02:00
volpino 8e08b6a33b euscan: handlers now use a Package object instead of cpv
Signed-off-by: volpino <fox91@anche.no>
2012-07-24 08:56:00 +02:00
Corentin Chary 99054971aa euscan: drop fixed version dependencies
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-24 08:37:31 +02:00
Corentin Chary 46c2ea6f70 euscan: use python-git for __version__
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-24 08:33:19 +02:00
volpino fd12bf1cb4 Merge branch 'master' of https://github.com/iksaif/euscan
Conflicts:
	euscanwww/djeuscan/processing/scan/scan_portage.py

Signed-off-by: volpino <fox91@anche.no>
2012-07-24 08:15:56 +02:00
volpino 2b09bfba8a euscan: Progressbar on stderr
Signed-off-by: volpino <fox91@anche.no>
2012-07-24 08:10:56 +02:00
Corentin Chary 9d905166be djeuscan: smaller icons, change refresh icon
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-24 08:09:47 +02:00
Corentin Chary 96a5a91e0c djeuscan: remove empty CELERYBEAT_SCHEDULE
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-24 08:09:17 +02:00
Corentin Chary fe7a81654b djeuscan: switch to ansi2html
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-24 08:08:37 +02:00
Corentin Chary e0a5308463 djeuscan: add euscan result log into a variable
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-24 08:07:09 +02:00
Corentin Chary 6bb42d72fc djeuscan: display confidence and tweak result display
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-24 08:06:10 +02:00
Corentin Chary 3d6126cf81 djeuscan: run scan_metadata(packages=None, populate=True)
Scan only additional stuff, not packages.

Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-24 08:05:12 +02:00
Corentin Chary 7e911bd9c6 djeuscan: use debug to dump json on error
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-24 08:03:42 +02:00
Corentin Chary 5d39cbf2fd djeuscan: in scan_metadata, if packages=None, skip packages scan
But if packages=[], scan all packages.

Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-24 07:59:40 +02:00
Corentin Chary 9617fd25a1 djeuscan: add cp() and cpv() for Package and Version
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-24 07:59:00 +02:00
Corentin Chary b0cd34ed75 djeuscan: portage. can be used instead of PORTDB
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-23 18:49:41 +02:00
Corentin Chary be9d28c255 djeuscan: helpers.py is actually unused
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-23 18:49:41 +02:00
volpino fb77d201c8 Merge branch 'master' of https://github.com/iksaif/euscan 2012-07-22 10:37:34 +02:00
volpino 8f768bd4fd euscanwww: From fixture to south data migration
Signed-off-by: volpino <fox91@anche.no>
2012-07-22 10:34:13 +02:00
volpino 634c2db389 euscan: euscan_patch_metadata --diff option
Signed-off-by: volpino <fox91@anche.no>
2012-07-22 10:26:40 +02:00
volpino edf549bc40 euscanwww: added fixture for periodic tasks
Signed-off-by: volpino <fox91@anche.no>
2012-07-21 10:00:12 +02:00
volpino f7340bee43 euscan: patch_metadata now handles debian diff files
Signed-off-by: volpino <fox91@anche.no>
2012-07-21 09:22:26 +02:00
Corentin Chary 65618e3056 djeuscan: portage. can be used instead of PORTDB
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-21 07:36:35 +02:00
Corentin Chary 5add4ddfcc djeuscan: helpers.py is actually unused
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-21 07:36:06 +02:00
volpino 0d4e8283ae euscanwww: added alert on refresh request, added missing pull-right
Signed-off-by: volpino <fox91@anche.no>
2012-07-20 17:20:18 +02:00
volpino 10cb482294 euscanwww: Icons for watching and refreshing, a user can refresh only once
Signed-off-by: volpino <fox91@anche.no>
2012-07-20 17:10:12 +02:00
volpino c6f2baa0e6 euscanwww: color code fix for json hilighting
Signed-off-by: volpino <fox91@anche.no>
2012-07-20 16:30:37 +02:00
volpino 0885e89cc1 euscanwww: uscan watch handle options
Signed-off-by: volpino <fox91@anche.no>
2012-07-20 16:10:53 +02:00
volpino ad02fd4b81 euscanwww: Added ansi to html helper
Signed-off-by: volpino <fox91@anche.no>
2012-07-20 15:12:44 +02:00
volpino 1aaee90ab7 euscanwww: take herds.xml path as an argument
Signed-off-by: volpino <fox91@anche.no>
2012-07-20 14:15:28 +02:00
volpino 609eff60ab euscanwww: Launch scan_portage per category like scan_metadata
Signed-off-by: volpino <fox91@anche.no>
2012-07-20 14:11:09 +02:00
volpino 7dc322348d euscanwww: PEP8, Cleaning unused imports and removing useless stuff
* Removed useless use of chords
* populate in scan_metadata is off by default
* fixed group_one and scan_metadata launch
* removed useless utils.py

Signed-off-by: volpino <fox91@anche.no>
2012-07-20 14:07:16 +02:00
volpino 3d8ea27ecc Merge branch 'master' of https://github.com/iksaif/euscan 2012-07-20 11:58:07 +02:00
volpino 2245698326 euscanwww: scan_metadata populates db from herds.xml
* Every herd has a m2m relation with maintainers
* New method populate_herds_and_maintainers to fill data in from herds.xml

Signed-off-by: volpino <fox91@anche.no>
2012-07-20 11:50:16 +02:00
Corentin Chary 5fb076b304 euscan: remove trailing comma
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-20 09:06:22 +02:00
Corentin Chary 8743e9d1e1 euscan: move version type helpers to euscan.version
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-20 09:04:15 +02:00
Corentin Chary 6f9e575bbc euscanwww: add missing file
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-20 08:42:38 +02:00
Corentin Chary 2544af2e32 euscanwww/tasks: simplify tasks
- strip '_task' end
- remove "launcher" functions, if we want complicated starter
  functions we will put them somewhere else later.
- now, everything is asynchroneous, maybe we could switch from
  group_one()/group_chunks() to .chunks() someday...

Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-20 08:42:38 +02:00
Corentin Chary 634e06b779 euscan: don't fail if robots.txt can't be read
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-20 08:41:13 +02:00
Corentin Chary bcda1a7ce3 euscan: add --ebuild-uri to use ${PV}, etc.
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-20 08:41:12 +02:00
volpino c483ac41f1 euscanwww: using djcelery.schedulers.DatabaseScheduler for periodic tasks
Signed-off-by: volpino <fox91@anche.no>
2012-07-18 17:16:31 +02:00
volpino 339ae58445 euscan: Added first implementation of the script to scrape debian watch
Signed-off-by: volpino <fox91@anche.no>
2012-07-18 14:02:26 +02:00
volpino 58532b2136 euscan: #!/usr/bin/python -> #!/usr/bin/env python
Signed-off-by: volpino <fox91@anche.no>
2012-07-18 10:48:14 +02:00
volpino 8268e634f0 euscanwww: Report problems is hided and can be shown with a click
Signed-off-by: volpino <fox91@anche.no>
2012-07-17 19:05:26 +02:00
volpino d70e4cb617 euscanwww: Adding unstable to legenda
Signed-off-by: volpino <fox91@anche.no>
2012-07-17 16:53:28 +02:00
volpino 748fa12462 euscanwww: Display unstable versions in package table list
Signed-off-by: volpino <fox91@anche.no>
2012-07-17 16:51:38 +02:00
volpino b052f2e8b8 euscanwww: scan_portage get paths using eix and PORTDB
Signed-off-by: volpino <fox91@anche.no>
2012-07-17 16:34:33 +02:00
volpino be146163f6 euscanwww: Displaying unstable versions in package view
Signed-off-by: volpino <fox91@anche.no>
2012-07-17 13:18:44 +02:00
volpino a85f7e71c1 euscanwww: Version.version_type -> Version.vtype
Signed-off-by: volpino <fox91@anche.no>
2012-07-17 12:30:55 +02:00
volpino 33a06d99fb euscan: added --ignore-pre-release and --ignore-pre-release-if-stable
options

Signed-off-by: volpino <fox91@anche.no>
2012-07-17 12:27:22 +02:00
volpino c4577c5279 euscanwww: Store ebuild and metadata path in Version
Uses getRepositoryPath, change if possible

Signed-off-by: volpino <fox91@anche.no>
2012-07-17 11:36:59 +02:00
volpino b7d772dfc3 euscanwww: Tests unwatch too
Signed-off-by: volpino <fox91@anche.no>
2012-07-14 16:43:12 +02:00
volpino 66db910583 euscanwww: Tests for watch packages/categories/maintainers/herds
Signed-off-by: volpino <fox91@anche.no>
2012-07-14 16:22:02 +02:00
volpino c0aefdef29 euscanwww: Started writing tests for favourite stuff but login fails
Signed-off-by: volpino <fox91@anche.no>
2012-07-14 15:29:42 +02:00
volpino bd2af29ff7 euscanwww: Basic user dashboard
Signed-off-by: volpino <fox91@anche.no>
2012-07-14 13:56:21 +02:00
volpino aa09812f6f euscanwww: Migration for handling ebuild and metadata paths
Signed-off-by: volpino <fox91@anche.no>
2012-07-14 13:55:56 +02:00
volpino a9265ec5d1 euscan: Performance improvement moving imports
Signed-off-by: volpino <fox91@anche.no>
2012-07-10 18:14:41 +02:00
volpino 3f0cef09e0 euscan: Fixed typo in out.py. euscan output was broken
Signed-off-by: volpino <fox91@anche.no>
2012-07-10 17:41:24 +02:00
volpino fab19a6bfc euscanwww: Watch/unwatch packages, categories, maintainers, overlays
Added a button for watch/unwatch and a dashboard with user selected
stuff only

Signed-off-by: volpino <fox91@anche.no>
2012-07-10 16:15:06 +02:00
volpino 02be58024a euscanwww: Minor fixes
Signed-off-by: volpino <fox91@anche.no>
2012-07-09 18:15:34 +02:00
volpino 379a6d2942 euscanwww: Adding a problem reporting form in package page
Signed-off-by: volpino <fox91@anche.no>
2012-07-09 14:29:42 +02:00
volpino 03cf3b90a4 euscanwww: Upgraded to Celery 3.0 and fixed scan_portage
Fixed TaskSet calls and synchronous stuff. Everything should be
deadlock safe

Signed-off-by: volpino <fox91@anche.no>
2012-07-07 18:09:14 +02:00
volpino 3be52a710c euscanwww: Changing RefreshPackageQuery.query to ForeignKey
Signed-off-by: volpino <fox91@anche.no>
2012-07-07 15:46:35 +02:00
volpino a6b215cec9 euscanwww: Fixed tasks to work with processing.scan and processing.misc
Fixed tasks to work with processing.* changes.
Moved periodic tasks config to settings.py using CELERYBEAT_SCHEDULE

Signed-off-by: volpino <fox91@anche.no>
2012-07-07 15:13:59 +02:00
volpino 80e8157627 Merge branch 'master' of https://github.com/iksaif/euscan 2012-07-03 11:13:35 +02:00
Corentin Chary 2f0080e544 git: update .gitignore
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-03 10:57:07 +02:00
Corentin Chary bdff6b7c63 euscanwww/scan_portage: try using gentoopm and fix slots
gentoopm is still slower with portage backend, will try pkgcore
backend later.

Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-03 10:56:14 +02:00
Corentin Chary 8062fddc23 euscanwww: move processing to scan and misc, enhance update_portage_tree
update_portage_tree() now:
- watch stderr and stdout for each command
- use layman command instead of layman API for sync because
  layman API doesn't work when stdout or stderr is not a real file
  (we could probably work around that with pipes and epoll)
- use egencache instead of emerge to generate cache
- export PORTAGE_CONFIGROOT, ROOT, EIX_CACHEFILE etc.. so they
  are used everywhere

Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-02 18:16:59 +02:00
volpino 5a2f2e9eab Merge branch 'master' of https://github.com/iksaif/euscan 2012-07-02 17:45:31 +02:00
volpino 6407efa14f euscan: naive implementation of --mirror
Signed-off-by: volpino <fox91@anche.no>
2012-07-02 17:44:55 +02:00
Corentin Chary 90702ddee8 euscan: don't import pkg_resources, we don't want all these warnings
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-02 11:20:52 +02:00
Corentin Chary 84a764dad5 euscan: allow --progress with --quiet
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-02 11:20:18 +02:00
Corentin Chary ba805536ad euscanwww: add --category to scan_metadata, remove homepage and description
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-02 11:19:49 +02:00
Corentin Chary 0e32ccf46e euscanwww: make it work with MySQL
unique indexes length must be <= 255

Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-02 09:44:00 +02:00
Corentin Chary 093cb4da47 euscanwww/scan_portage: fixes and add --category
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-02 09:43:31 +02:00
Corentin Chary ad5e399096 euscanwww: move start_dev_services.sh to scripts
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-07-02 08:09:06 +02:00
volpino 71f71c5b58 euscanwww: fixed commit_on_success
Signed-off-by: volpino <fox91@anche.no>
2012-06-30 19:21:43 +02:00
volpino 09f0f75a42 Merge branch 'master' of https://github.com/iksaif/euscan 2012-06-30 18:37:04 +02:00
volpino f43ab3ae3d euscanwww: fixing merge
Signed-off-by: volpino <fox91@anche.no>
2012-06-30 18:36:45 +02:00
Corentin Chary 728770088c euscan: don't respect robots.txt for mono download site
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-06-30 15:57:56 +02:00
volpino 94b814481b euscanwww: adding elem.clear() to prevent memory leaking in xml parsing
Signed-off-by: volpino <fox91@anche.no>
2012-06-30 11:03:24 +02:00
volpino 145388a5e5 euscanwww: scan_upstream_all_task scans in randomized order
Signed-off-by: volpino <fox91@anche.no>
2012-06-30 10:50:17 +02:00
volpino c6f5fb0b7c euscanwww: reverting removed purge_packages in scan_package_task
Signed-off-by: volpino <fox91@anche.no>
2012-06-30 10:42:26 +02:00
volpino c184628f48 Merge branch 'master' of https://github.com/iksaif/euscan
Conflicts:
	euscanwww/djeuscan/processing/scan_portage.py

Signed-off-by: volpino <fox91@anche.no>
2012-06-30 10:39:18 +02:00
volpino 0c5a0ac36f euscanwww: Using incremental xml parsing for portage scanning
Signed-off-by: volpino <fox91@anche.no>
2012-06-30 10:28:03 +02:00
Corentin Chary 9e6f885f89 djeuscan/scan_portage: fix purge-packages and purge-versions
purge-packages: purge package that are not found in the tree
purge-versions: purge versions that are not found in the tree

Also, only purge versions of packages specified on the command line
when called without --all.

Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-06-30 10:19:07 +02:00
volpino a83e4de59d euscanwww: user refresh package should not purge packages
Signed-off-by: volpino <fox91@anche.no>
2012-06-30 09:35:31 +02:00
volpino 91ccdeb4e7 euscanwww: simple script to start services (only for development)
Signed-off-by: volpino <fox91@anche.no>
2012-06-30 09:01:36 +02:00
Corentin Chary 20f796df60 Merge branch 'master' of git://github.com/volpino/euscan
Conflicts:
	euscanwww/djeuscan/management/commands/scan_upstream.py

Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-06-30 07:38:26 +02:00
Corentin Chary e660d93398 euscanwww/scan_upstream: remove --feed
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-06-30 07:37:04 +02:00
volpino fc7f929038 euscanwww: Fixed broken tasks
Signed-off-by: volpino <fox91@anche.no>
2012-06-29 17:25:45 +02:00
volpino e9c03fbded euscanwww: Fixed CSS stylesheet
Added Twitter Bootstrap and tweaked the layout to use the grid layout

Signed-off-by: volpino <fox91@anche.no>
2012-06-29 14:22:01 +02:00
volpino d7bf130fda euscan: minor fixes
Signed-off-by: volpino <fox91@anche.no>
2012-06-28 12:43:46 +02:00
volpino 0d6376681f euscan: fixed progressbar
added -p option, now the progressbar is "global" and shows the total
progress

Signed-off-by: volpino <fox91@anche.no>
2012-06-28 12:20:57 +02:00
volpino b06965f386 euscan: plugin system for handlers
Signed-off-by: volpino <fox91@anche.no>
2012-06-28 11:08:05 +02:00
volpino 951624759a euscanwww: Fixing tasks
Fixing minor bugs in tasks.py and little related stuff

Signed-off-by: volpino <fox91@anche.no>
2012-06-27 10:15:30 +02:00
volpino 1ae2dcba50 euscanwww: settable options for _run_in_chunks()
Signed-off-by: volpino <fox91@anche.no>
2012-06-26 18:31:35 +02:00
volpino 8fdac1014c euscanwww: Adding infos to EuscanResults
Now we store metadata, output from euscan is cleaned from colors
encoding when outputting json

Signed-off-by: volpino <fox91@anche.no>
2012-06-26 18:13:28 +02:00
volpino 699bb372a5 euscanwww: Added README for celery
Signed-off-by: volpino <fox91@anche.no>
2012-06-26 17:17:35 +02:00
volpino d7e0a4ca16 euscanwww: Tweaked processing.scan_portage to use eix --xml
Signed-off-by: volpino <fox91@anche.no>
2012-06-26 17:16:02 +02:00
volpino f9c9a4bfd8 euscanwww: added scan_package task
Signed-off-by: volpino <fox91@anche.no>
2012-06-22 11:40:40 +02:00
volpino 779ccdf5d3 euscanwww: use logging in djeuscan.processing
Signed-off-by: volpino <fox91@anche.no>
2012-06-22 11:31:15 +02:00
volpino 9af5548178 Merge branch 'master' of https://github.com/iksaif/euscan 2012-06-22 09:34:11 +02:00
volpino 9bfd728d4f euscanwww: Moved business logic to djeuscan.processing
Moved stuff from management commands to djeuscan.processing

Signed-off-by: volpino <fox91@anche.no>
2012-06-22 09:32:39 +02:00
Corentin Chary 94adc751c1 Merge pull request #17 from mgorny/master
github API support, part I
2012-06-14 07:55:31 -07:00
Michał Górny a3fe7a21e7 github: return the regular download URL instead. 2012-06-14 12:56:45 +02:00
Michał Górny 5af479fea8 Handle exceptions in scanning loop. 2012-06-14 12:38:52 +02:00
Michał Górny 7cbe517a70 Initial support for github downloads.
Right now, it just handles ebuilds using mirror://github.
2012-06-14 12:34:39 +02:00
volpino 6cc892717b Merge branch 'master' of https://github.com/iksaif/euscan 2012-06-14 10:21:37 +02:00
volpino 11c8422c9b euscanwww: Reset password
Signed-off-by: volpino <fox91@anche.no>
2012-06-14 10:21:01 +02:00
volpino 34d3bd714d euscanwww: Watched herds/maintainers/categories panel
* Refactored templates and templatetags
* Added unfavourite views
* Added button to favourite/unfavourite package
* Panel for showing favourited objects

Signed-off-by: volpino <fox91@anche.no>
2012-06-14 10:03:49 +02:00
volpino 11c234f7f7 euscanwww: Added account profile page
* Added an account profile page
* Added a button to favourite packages
* Implemented models to favourite categories, herds, maintainers but
  still to implement

Signed-off-by: volpino <fox91@anche.no>
2012-06-12 15:27:28 +02:00
volpino bd971a7da0 euscanwww: When scanning upstream output object was never cleaned
Signed-off-by: volpino <fox91@anche.no>
2012-06-12 14:55:58 +02:00
volpino 7367596e33 euscanwww: Added LDAP login
Needs testing and the settings must be changed to use the gentoo ldap
server

Signed-off-by: volpino <fox91@anche.no>
2012-06-12 13:39:05 +02:00
volpino bd9af90ff6 euscanwww: Removed useless purge tasks, some error handling
Signed-off-by: volpino <fox91@anche.no>
2012-06-12 13:05:58 +02:00
Corentin Chary 8f1668b51e Merge pull request #16 from radhermit/bs4
add support for Beautiful Soup 4
2012-06-11 00:03:07 -07:00
volpino d34a0c4992 euscanwww: included django-registration and tweaked templates
Signed-off-by: volpino <fox91@anche.no>
2012-06-09 17:12:09 +02:00
volpino 4246c544ad euscanwww: bug found, celery timeouts on join. Commented out
Signed-off-by: volpino <fox91@anche.no>
2012-06-09 16:12:17 +02:00
volpino 9cddc82808 Merge branch 'master' of https://github.com/iksaif/euscan
Conflicts:
	euscanwww/djeuscan/models.py

Signed-off-by: volpino <fox91@anche.no>
2012-06-08 14:46:37 +02:00
volpino b43bf8fa28 euscanwww: Removing duplicated code
Signed-off-by: volpino <fox91@anche.no>
2012-06-08 14:43:18 +02:00
volpino 43e996d83d euscanwww: Fixed the upstream task that was completely broken
Signed-off-by: volpino <fox91@anche.no>
2012-06-08 14:24:17 +02:00
volpino a6a87260b1 euscanwww: Fixed a minor bug in the task launching interface
Signed-off-by: volpino <fox91@anche.no>
2012-06-08 14:23:37 +02:00
volpino a94a24eeac euscanwww: Refresh query logic and task queue split in chunks
Added the needed logic for running refresh queries from the web
interface.

Added a simple function to tasks.py that takes an iterable of arguments
and a task and launches many subtasks formed by 32 tasks each (for not
having a huge amount of tasks launched at the same time)

Signed-off-by: volpino <fox91@anche.no>
2012-06-08 14:21:11 +02:00
volpino 8913f826de euscanwww: Added RefreshPackageQuery to models
Allows storing queries for refresh requests by users

Signed-off-by: volpino <fox91@anche.no>
2012-06-08 14:19:20 +02:00
Tim Harder 5df28b028e add support for Beautiful Soup 4 2012-06-08 00:18:59 -07:00
volpino 33555a9fbe euscanwww: Fixed Layman sync task
Signed-off-by: volpino <fox91@anche.no>
2012-06-05 16:44:08 +02:00
volpino 8501805f8e euscanwww: Scan tasks recieve a list of packages
Signed-off-by: volpino <fox91@anche.no>
2012-06-05 13:30:31 +02:00
volpino 4a9301a215 euscanwww: naive implementation of the refresh button
A refresh button lets launching a scan_upstream task for a package while
navigating into euscanwww

Signed-off-by: volpino <fox91@anche.no>
2012-06-05 13:10:25 +02:00
volpino 8ed74a74df euscanwww: Changed Layman sync task to use Python API
Signed-off-by: volpino <fox91@anche.no>
2012-06-05 12:46:22 +02:00
volpino c41521d59f euscanwww: Admin interface tweaks
Added some search fields, ordering and filters to the admin panel

Signed-off-by: volpino <fox91@anche.no>
2012-06-04 11:27:18 +02:00
volpino 60e2019cc3 euscanwww: Added tasks for syncing and updating portage tree
Added these tasks:
 * emerge_sync
 * layman_sync
 * emerge_regen
 * eix_update

Signed-off-by: volpino <fox91@anche.no>
2012-06-04 11:06:47 +02:00
Corentin Chary 5b1884ead7 djeuscan: fix alive / packaged updates
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-06-04 10:28:06 +02:00
volpino 2edb220d3e euscanwww: use jQuery each instead of for
Signed-off-by: volpino <fox91@anche.no>
2012-06-03 17:38:51 +02:00
volpino 5970b4df37 euscanwww: Admin improved and simple task launcher added
Signed-off-by: volpino <fox91@anche.no>
2012-06-03 09:43:49 +02:00
volpino 47ec539e1d euscanwww: scan_upstream imports euscan.scan
scan_upstream command imports euscan.scan and simply calls a function,
it doesn't call a subprocess

Signed-off-by: volpino <fox91@anche.no>
2012-05-31 18:42:37 +02:00
volpino e8718748b4 euscanwww: Celery fixes and little logging
Signed-off-by: volpino <fox91@anche.no>
2012-05-31 09:11:40 +02:00
volpino 56c4d79fb2 euscanwww: starting implementing Celery tasks
Basic tasks.py module, some fixes in the management commands

Signed-off-by: volpino <fox91@anche.no>
2012-05-30 22:54:55 +02:00
Corentin Chary 83f5df4daf euscanwww: fix the scan process
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-05-29 15:29:03 +02:00
Corentin Chary f0a3c34ac8 Merge remote branch 'fox/master' 2012-05-29 09:21:44 +02:00
volpino c36f625a54 euscanwww: fixing colored output
Signed-off-by: volpino <fox91@anche.no>
2012-05-28 23:24:09 +02:00
volpino fce8ef347b euscanwww: management commands are validators aware
Management commands should create objects that don't raise
ValidationError

Signed-off-by: volpino <fox91@anche.no>
2012-05-28 22:57:33 +02:00
volpino b46e9acc08 euscan: Refactored all management commands
Management commands are refactored to have the logic moved from the
commands themselves to a separated function in order to make them easily
convertible into Celery tasks

Commands are renamed to be modules importable from other python scripts

Signed-off-by: volpino <fox91@anche.no>
2012-05-28 21:19:53 +02:00
volpino e535c204b0 euscanwww: fixed homepage and category validation
Accept multiple urls but skip invalid urls, added virtual as accepted
category

Signed-off-by: volpino <fox91@anche.no>
2012-05-28 18:45:14 +02:00
Corentin Chary 3437cf5e4b euscan: cleanups
Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-05-28 07:02:41 +02:00
volpino a224cb27cb euscan: naive progressbar implementation
Progressbar for formatted output

Signed-off-by: volpino <fox91@anche.no>
2012-05-27 10:23:15 +02:00
volpino 31bd4dc55e euscan: adjusted code to be PEP8 compliant
Signed-off-by: volpino <fox91@anche.no>
2012-05-25 10:23:33 +02:00
Corentin Chary 305fdea0c7 euscan: make eend works again
Simplify einfo/ewarn/eend handling (for now) and make "message" someting
containing only what stdout would contain. We loose some informations, but
I'm really not sure we need more.

Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-05-25 00:19:17 +02:00
Corentin Chary 687851ffcb Merge git://github.com/volpino/euscan
Conflicts:
	pym/euscan/scan.py
2012-05-24 23:47:55 +02:00
Corentin Chary 177d77842f euscan: allow to use .ebuild files in any directory
Even outside PORTDIR_OVERLAY !

Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-05-24 23:44:05 +02:00
volpino 4d606ae1cf euscan: added scan time to formatted output
scan_time in metadata dictionary

Signed-off-by: volpino <fox91@anche.no>
2012-05-24 20:27:18 +02:00
volpino 9989433ad5 euscan: detect version type
In the formatted output display the version type (beta, alpha, rc, ...)

Signed-off-by: volpino <fox91@anche.no>
2012-05-23 23:08:07 +02:00
volpino 1efeee4134 euscan: added simple support to result confidence
Confidence values are meaningless at the moment. Need to fix it.

Signed-off-by: volpino <fox91@anche.no>
2012-05-23 16:44:44 +02:00
volpino a18083bd98 euscan: json format output
Now "-f json" seems good, it supports the handler type used to retrieve
each version and outputs metadata.

Signed-off-by: volpino <fox91@anche.no>
2012-05-23 16:30:43 +02:00
volpino 8cb19b5a6b euscan: adding json output
Naive json output implmented, probably needs some further tuning

Signed-off-by: volpino <fox91@anche.no>
2012-05-21 22:38:38 +02:00
volpino 373fba6e01 euscan: fixed patched versions issue
The old code extracted version 0.8.6.1 from buildbot-0.8.6p1 instead of
0.8.6_p1

Signed-off-by: volpino <fox91@anche.no>
2012-05-21 12:03:14 +02:00
Corentin Chary 7f8fb05c23 htdocs: add static symlink
(don't remember why exactly)

Signed-off-by: Corentin Chary <corentin.chary@gmail.com>
2012-05-20 11:14:50 +02:00
volpino 777b6909a3 added long_description to setup.py 2012-05-19 14:23:24 +02:00
volpino 8563785746 model validators 2012-05-19 14:11:06 +02:00
volpino de0ad4b210 issue #13 fixed 2012-05-13 16:42:29 +02:00
volpino 61a24fefb7 minor fix in runtests 2012-05-13 14:10:57 +02:00
volpino c85de09947 some more cleaning, removing relative imports 2012-05-13 14:09:22 +02:00
volpino b339efe012 tests for managers 2012-05-13 11:37:05 +02:00
volpino 2ec8cba794 feeds tests 2012-05-12 17:29:09 +02:00
volpino c790618a51 more tests 2012-05-12 16:07:49 +02:00
volpino d3676250ab tests refactoring and some fixes 2012-05-09 16:50:17 +02:00
volpino 9a39328e3b more and more tests 2012-05-07 14:27:54 +02:00
volpino 04d54f4689 add db journal to gitignore 2012-05-07 13:44:11 +02:00
volpino 46489c84a4 charts test 2012-05-07 10:56:54 +02:00
volpino cb3dcaf713 test test test! 2012-05-07 10:20:33 +02:00
volpino 23f43e869a urls from future in templates 2012-05-06 20:27:14 +02:00
volpino 948c5b8c39 some tests, urls now have a name 2012-05-06 20:03:49 +02:00
volpino 0ece4c04b2 removed some code minimizations for readability 2012-05-05 16:59:34 +02:00
volpino e0bb80f905 some cleaning 2012-05-05 16:55:59 +02:00
Federico Scrinzi 37a623a97a Merge pull request #1 from bacher09/master
Code refactoring
2012-05-05 07:43:15 -07:00
volpino 1f18782007 test reorganized, launch them with setup.py test 2012-05-05 16:09:04 +02:00
Slava Bacherikov 22ac8c4e2e Merge branch 'master' of git://github.com/volpino/euscan 2012-05-05 16:51:15 +03:00
Slava Bacherikov 3a56aa4391 Rewrote some for_ methods in PackageMixin class 2012-05-05 18:50:13 +03:00
Slava Bacherikov b4162313f2 Change in PackageMixin, create ANNOTATE_DICT 2012-05-05 18:28:41 +03:00
Slava Bacherikov 0efba89342 Change in PackageMixin 2012-05-05 17:41:09 +03:00
volpino 058b50556b issue #4 2012-05-05 14:28:48 +02:00
volpino 52fc4a5df4 VersionLog manager 2012-05-05 11:48:12 +02:00
volpino 050c210f40 charts fix, bug introduced while refactoring 2012-05-05 11:04:44 +02:00
volpino 22bcf20c7c select_related prefetch refactored 2012-05-05 10:54:04 +02:00
volpino 5c0dbe11f2 feeds use manager 2012-05-05 10:38:51 +02:00
volpino 7ad08128cd apis now use manager 2012-05-05 10:22:59 +02:00
volpino 6464187342 changing charts.py to use manager 2012-05-05 10:09:27 +02:00
volpino 84b2a1917a PackageManager allows chaining 2012-05-05 10:03:02 +02:00
volpino a145d8a4f6 fixing circular import 2012-05-05 10:02:17 +02:00
volpino ab6ea22ed3 moved more stuff from views to helpers or managers 2012-05-01 21:15:55 +02:00
volpino c3d28402c7 Merge branch 'master' of https://github.com/iksaif/euscan 2012-05-01 20:43:38 +02:00
volpino 48de5022ba one more function moved to manager, some docs 2012-05-01 17:08:49 +02:00
volpino a6c7a58e61 minor README fix 2012-05-01 16:56:48 +02:00
volpino 8e37f6249c some refactoring, added Package manager for removing code duplicates, added helpers module, basic tests layout 2012-05-01 16:56:09 +02:00
Federico Scrinzi 1c53c60eed Update README.rst 2012-05-01 15:29:40 +03:00
volpino e17e0de19a README in rst 2012-05-01 13:50:53 +02:00
Corentin Chary 1a40cf7bcc Merge pull request #2 from volpino/master
Cleaning up and updating requirements
2012-04-29 12:42:14 -07:00
volpino ff14477f60 removing tabs and spaces mix in templates 2012-04-28 18:29:21 +02:00
volpino 8c91855a58 Lovely day for PEP8 and pylint! 2012-04-28 18:16:05 +02:00
volpino 4e4f9643ac README update 2012-04-28 15:04:01 +02:00
volpino 2a6cf35c01 adding missing requirements 2012-04-28 14:56:43 +02:00
volpino 0d6ba637e7 missing BeautifulSoup requirement 2012-04-26 23:15:54 +02:00
Corentin Chary 07beab265c TODO: update
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-04-23 17:05:59 +02:00
Corentin Chary 9e1ff8adb7 euscanwww: use tz aware datetimes
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-04-23 17:05:46 +02:00
Corentin Chary 6e0706d638 euscan: fix cpan version ordering
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-04-23 17:05:23 +02:00
Corentin Chary b0ccdd2157 euscan: new cpan handler
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-04-20 17:27:16 +02:00
Corentin Chary 3da5fb5240 euscan: mangle versions the gentoo-way
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-04-19 15:36:44 +02:00
Corentin Chary da269b0711 euscanwww: euscan -> djeuscan
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-04-04 17:31:54 +02:00
Corentin Chary 6a57b44d7c euscan: force nodejs.org scan
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-04-04 14:34:09 +02:00
Corentin Chary 9f1cdae45e euscanwww: django 1.4 port
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-04-04 14:33:40 +02:00
Corentin Chary d5a9b31b3c euscanwww/feeds: remove duplicate descriptions
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-03-28 09:10:24 +02:00
Corentin Chary 37a9a742c3 euscan: cleanups
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-03-28 09:09:08 +02:00
Corentin Chary 76a1121c9f euscan: don't keep version from partial paths
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-03-28 09:09:08 +02:00
Corentin Chary 697fbf06ab euscanwww/templates: add icons
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-03-28 09:09:08 +02:00
Corentin Chary a8d38127cc Merge pull request #1 from volpino/master
Removing django-annoying from the codebase, setuptools for setup.py and some cleaning
2012-03-27 23:12:17 -07:00
volpino a7e9a7c101 more requirements, some more are missing tough 2012-03-27 19:13:43 +02:00
volpino 06bef562e8 cleaning up, pep8 fix and changing tabs to spaces 2012-03-27 18:58:19 +02:00
volpino ac6c57cb57 adding django-annoying to requirements and deleting it from the codebase 2012-03-27 18:48:31 +02:00
volpino 9814b81797 adding setuptools to setup.py 2012-03-27 18:45:35 +02:00
Corentin Chary 5062f29e3c euscanwww: don't delete packages when deleting related versions
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-03-14 14:07:28 +01:00
Corentin Chary 2effd34b01 euscanwww: optimize commands
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-03-14 14:07:06 +01:00
Corentin Chary 043197a3be euscanwww: update style, prefetch related, ...
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-03-05 14:46:34 +01:00
Corentin Chary 1d65ee1984 euscanwww: add charts bellow menu on herd/category/maintainer
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-03-05 11:27:53 +01:00
Corentin Chary ff33042f36 euscanwww: add freshness and last versions
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-03-02 18:01:46 +01:00
Corentin Chary d899ffb849 euscanwww: add a snapshot and some steps when importing snapshots
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-03-02 14:27:21 +01:00
Corentin Chary d6f3b6629c euscanwww: take args from stdin and update INSTALL
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-03-02 14:08:28 +01:00
Corentin Chary 329b20fecf euscan/rubygem: better gem detection
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-03-02 13:54:23 +01:00
Corentin Chary b6821903a6 euscanwww/INSTALL: basic intructions
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-03-02 13:54:00 +01:00
Corentin Chary df1d778365 euscan: add a quick /_rc/-rc/ hack
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-02-20 08:21:07 +01:00
Corentin Chary 5bd358968a euscan: re-indent blacklists
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-02-20 08:20:54 +01:00
Corentin Chary b0664564f3 euscan: update TODO and euscan-update.sh
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-02-14 14:55:11 +01:00
Corentin Chary 8190779070 euscan: remove a line
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-02-14 14:54:34 +01:00
Corentin Chary bdd6040c12 euscanwww: remove csrf and add request processor
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-02-14 14:54:05 +01:00
Corentin Chary 9e47ceb311 euscanwww/templates: add some "extras"
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-02-14 14:53:33 +01:00
Corentin Chary 31af7ae416 euscan: add new related tool to TODO
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-01-21 09:32:36 +01:00
Corentin Chary 2d81d0a0be euscan: change download url
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-01-18 08:13:41 +01:00
Corentin Chary 333c535230 euscan: fix man page installation
ref: https://bugs.gentoo.org/show_bug.cgi?id=398873

Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-01-16 14:15:50 +01:00
Corentin Chary 72e43ac4fe euscan: tweak error paths
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2012-01-02 21:31:05 +01:00
Corentin Chary 2bd012ef82 euscanwww: show maintainer name and email
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2011-12-30 11:34:54 +01:00
Corentin Chary b78e73038d euscan: add kde handler and fix some regex issues
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2011-12-30 11:34:39 +01:00
Corentin Chary d673c00e12 euscan: update TODO list
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2011-12-30 11:33:27 +01:00
Corentin Chary fef31c514c euscan: respect --quiet in pypi handler
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2011-12-12 15:15:00 +01:00
Corentin Chary 0e6c18b84b euscanwww: clean settings
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2011-12-11 14:32:55 +01:00
Corentin Chary 3569f1bb97 euscan: better --quiet mode
Signed-off-by: Corentin Chary <corentincj@iksaif.net>
2011-12-11 14:32:38 +01:00
149 changed files with 3775 additions and 13846 deletions

4
.git-blame-ignore-revs Normal file
View File

@ -0,0 +1,4 @@
# Reformat with black
d860708ec92cfa041f7a89e17c4dd03d17a94071
# Reformat with isort
70f88ed37d33cccd46a167ba81f2c953936d75d7

26
.gitignore vendored
View File

@ -1,4 +1,24 @@
**/*.rs.bk
*.beam
*.dump
*.egg-info/
*.ez
*.py[co]
*.swp
*.tar
*~
*.pyc
euscanwww/rrd/*.rrd
euscanwww/media/charts/*.png
*~
,*
.eggs/
.fetch/
.idea/
.vscode/
.~lock.*
/build/
/cover/
/deps/
/dist/
/target/
__pycache__/
_build/
src/euscan/_version.py

36
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,36 @@
image: python:latest
variables:
PIP_CACHE_DIR: ${CI_PROJECT_DIR}/.cache/pip
cache:
paths:
- ${PIP_CACHE_DIR}
before_script:
- python --version ; pip --version
- pip install virtualenv
- virtualenv venv
- source venv/bin/activate
pre-commit:
variables:
PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit
cache:
paths:
- ${PRE_COMMIT_HOME}
script:
- pip install pre-commit
- pre-commit run --all-files
publish:
variables:
TWINE_PASSWORD: ${CI_JOB_TOKEN}
TWINE_USERNAME: gitlab-ci-token
TWINE_REPOSITORY_URL: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi
TWINE_NON_INTERACTIVE: 1
when: manual # gentoolkit as a dependency blocks publishing for now
script:
- pip install build twine
- python -m build
- python -m twine upload --verbose dist/*

15
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,15 @@
repos:
- repo: https://github.com/psf/black
rev: 24.2.0
hooks:
- id: black
- repo: https://github.com/PyCQA/isort
rev: 5.13.2
hooks:
- id: isort
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.0
hooks:
- id: ruff

View File

@ -1,8 +1,3 @@
* euscan
Original author: Corentin Chary <corentin.chary@gmail.com>
Current maintainer: Corentin Chary <corentin.chary@gmail.com>
* euscanwww
Original author: Corentin Chary <corentin.chary@gmail.com>
Current maintainer: Corentin Chary <corentin.chary@gmail.com>
Current maintainer: src_prepare group https://gitlab.com/src_prepare

34
CHANGELOG.rst Normal file
View File

@ -0,0 +1,34 @@
================
Change history
================
Note: Changelog prior to 1.0.0 is patchy.
1.0.1 (unreleased)
==================
* Remove euscanwww
* Remove man page
* Major reformatting with black and isort
* Migrate to a PEP517 buildsystem
* Add python 3.12 support
* Change default user-agent
* Use portage MetadataXML over gentoolkit Metadata after it was removed in gentoolkit version 0.6.0.
1.0.0 (released 2020-09-16)
===========================
* Python 3 compatibility
* Fix brute-force short option
* Beautiful Soup 4 support
0.1.1 (released 2012-01-18)
===========================
* Better --quiet mode
0.1.0 (released 2011-11-27)
===========================
* Initial Release

View File

@ -1,12 +0,0 @@
================
Change history
================
.. _version-0.1.0:
0.1.0
=====
:release-date: 2011-11-27 10:00 P.M CET
* Initial Release

View File

@ -1,12 +1,12 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@ -15,7 +15,7 @@ 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
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
@ -55,8 +55,8 @@ 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
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
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
@ -168,7 +168,7 @@ 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
@ -225,7 +225,7 @@ 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
@ -255,7 +255,7 @@ 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
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
@ -277,9 +277,9 @@ 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
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
@ -291,7 +291,7 @@ 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) 19yy <name of author>
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
@ -303,17 +303,16 @@ the "copyright" line and a pointer to where the full notice is found.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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) 19yy name of author
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.
@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names:
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
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -1,9 +1,8 @@
include AUTHORS
include COPYING
include NEWS
include README
include CHANGELOG.rst
include LICENSE
include README.rst
include TODO
include setup.py
include pyproject.toml
recursive-include bin *
recursive-include man *
recursive-include pym *.py
recursive-include src *.py

196
README
View File

@ -1,196 +0,0 @@
What is euscan ?
================
dev-portage/euscan
------------------
euscan is available in portage as a dev package (app-portage/euscan-9999). This tool allow to check if a given package/ebuild has new upstream versions or not. It will use different heuristic to scan upstream and grab new versions and related urls.
This tool was designed to mimic debian's uscan, but there is a major difference between the two: uscan uses a specific "watch" file that describe how it should scan packages, while euscan uses only what can already be found in ebuilds. Of course, we could later add some informations in metadata.xml to help euscan do its job more efficiently.
euscan heuristics are described in the "How does-it works ?" section.
### Examples
$ euscan amatch
* dev-ruby/amatch-0.2.7 [gentoo]
Ebuild: /home/euscan/local/usr/portage/dev-ruby/amatch/amatch-0.2.7.ebuild
Repository: gentoo
Homepage: http://flori.github.com/amatch/
Description: Approximate Matching Extension for Ruby
* SRC_URI is 'mirror://rubygems/amatch-0.2.7.gem'
* Using: http://rubygems.org/api/v1/versions/amatch.json
Upstream Version: 0.2.8 http://rubygems.org/gems/amatch-0.2.8.gem
$ euscan rsyslog
* app-admin/rsyslog-5.8.5 [gentoo]
Ebuild: /home/euscan/local/usr/portage/app-admin/rsyslog/rsyslog-5.8.5.ebuild
Repository: gentoo
Homepage: http://www.rsyslog.com/
Description: An enhanced multi-threaded syslogd with database support and more.
* SRC_URI is 'http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.8.5.tar.gz'
* Scanning: http://www.rsyslog.com/files/download/rsyslog/rsyslog-${PV}.tar.gz
* Scanning: http://www.rsyslog.com/files/download/rsyslog
* Generating version from 5.8.5
* Brute forcing: http://www.rsyslog.com/files/download/rsyslog/rsyslog-${PV}.tar.gz
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.8.6.tar.gz ... [ !! ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.8.7.tar.gz ... [ !! ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.8.8.tar.gz ... [ !! ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.0.tar.gz ... [ ok ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.10.0.tar.gz ... [ !! ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.11.0.tar.gz ... [ !! ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.1.tar.gz ... [ ok ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.2.tar.gz ... [ ok ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.3.tar.gz ... [ ok ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.12.0.tar.gz ... [ !! ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.4.tar.gz ... [ !! ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.5.tar.gz ... [ !! ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.6.tar.gz ... [ !! ]
Upstream Version: 5.9.1 http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.1.tar.gz
Upstream Version: 5.9.0 http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.0.tar.gz
Upstream Version: 5.9.3 http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.3.tar.gz
Upstream Version: 5.9.2 http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.2.tar.gz
### Hidden settings
You can configure some settings using the command line, but the __init__.py file of the euscan package contains more settings, including blacklists and default settings.
Maybe we should add the ability to use /etc/euscan.conf and ~/.config/euscan/euscan.conf to override these settings.
euscan-www: euscan as a service
-------------------------------
euscan-www is a web application that aggregates euscan results. For example there is an instance of euscan-www that monitors gentoo-x86 + some official overlays currently hosted at http://euscan.iksaif.net/ .
euscan-www uses django and provides some custom commands to feed the database. You can use euscan-www on you system tree, or preferably you can use a local tree to avoid messing with your system.
### Installation
Like any django web app, just start by editing settings.py and then run these two commands.
$ python manage.py syncdb
$ python manage.py migrate
Now your instance is ready, you can just run this command to browse it. If you want to host it publicly you should use a real webserver.
$ python manage.py runserver
### Creating a local tree
Create a local tree with all that portage (and layman would need). There is an example in euscanwww/scripts/local-tree/. See escan-update.sh to know what env variables you need to run any portage related command in this local tree.
### Scanning process
The scanning process is done by euscan-update.sh. You should read carefully this script, and adapt it to your needs. For example it uses gparallel to launch multiple process at a time, and you should adapt that to your number of cpu and network bandwith.
Once your euscan-update.sh is ok, just run it.
$ sh euscan-update.sh
### Custom Django management commands
euscan-www povides some new management commands, here is a short description of these commands. Use "help" or read euscan-update.sh to get more informations.
#### list-packages
List packages stored in database.
#### scan-portage
Scan the portage tree and store new packages and versions in the database.
#### scan-metadata.py
Scan metadata and looks for homepage, maintainers and herds.
#### scan-upstream
Scan upstream package. The prefered way to use this script it to first launch euscan on some packages, store the result of the file, and feed this command with the result.
#### update-counters
Update statistics and rrd files.
#### regen-rrds
If you deleted your rrd files, this script will use the database to regen them.
How does it work ?
==================
euscan has different heuristics to scan upstream and provides multiple "handlers". First, here is a description of the generic handler.
Scanning directories
--------------------
The first thing to do is to scan directories. It's also what uscan do, but it uses a file that describe what url and regexp to use to match packages.
euscan uses SRC_URI and tries to find the current version (or part of this version) in the resolved SRC_URI and generate a regexp from that.
For example for app-accessibility/dash-4.10.1, SRC_URI is:
mirror://gnome/sources/dasher/4.10/dasher-4.10.1.tar.bz2
euscan will scan pages based on this template:
http://ftp.gnome.org/pub/gnome/sources/dasher/${0}.${1}/dasher-${PV}.tar.bz2
Then, from that, it will scan the top-most directory that doesn't depend on the version, and try to go deeper from here.
Brute force
-----------
Like when scanning directories, a template of SRC_URI is built. Then euscan generate next possible version numbers, and tries to download the url generated from the template and the new version number.
For example, running euscan on portage/app-accessibility/festival-freebsoft-utils-0.6:
SRC_URI is 'http://www.freebsoft.org/pub/projects/festival-freebsoft-utils/festival-freebsoft-utils-0.6.tar.gz'
Template is http://www.freebsoft.org/pub/projects/festival-freebsoft-utils/festival-freebsoft-utils-${PV}.tar.gz
Generate version from 0.6: 0.7, 0.8, 0.10, ...
Try new urls: http://www.freebsoft.org/pub/projects/festival-freebsoft-utils/festival-freebsoft-utils-0.7.tar.gz, etc..
Blacklists
----------
euscan uses blacklist for multiple purposes.
### BLACKLIST_VERSIONS
For versions that should not be checked at all. sys-libs/libstdc++-v3-3.4 is good example because it's a package which version will always be 3.4 (Compatibility package for running binaries linked against a pre gcc 3.4 libstdc++).
### BLACKLIST_PACKAGES
Some packages are dead, but SRC_URI refers to sources that are still being updated, for example: sys-kernel/xbox-sources that uses the same sources as vanilla-sources but is not updated the same way.
### SCANDIR_BLACKLIST_URLS
For urls that are not browsable. mirror://gentoo/ is a good example: it's both stupid to scan it and very long/expensive.
### BRUTEFORCE_BLACKLIST_PACKAGES and BRUTEFORCE_BLACKLIST_URLS
Disable brute force on those packages and urls. Most of the time it's because upstream is broken and will answer HTTP 200 even if the file doesn't exist.
### ROBOTS_TXT_BLACKLIST_DOMAINS
Don't respect robots.txt for these domains (sourcefourge, berlios, github.com).
Site handlers
-------------
### Pecl/PEAR
A site handler that uses the Pecl/PEAR rest API (http://pear.php.net/manual/en/core.rest.php).
### Rubygems
This one uses rubygems's json API (http://guides.rubygems.org/rubygems-org-api/)
### Pypy
Uses pypy's XML rpc API.

166
README.rst Normal file
View File

@ -0,0 +1,166 @@
What is euscan-ng ?
===================
dev-portage/euscan-ng
=====================
euscan-ng is a fork of Bernard Cafarelli's euscan: https://github.com/voyageur/euscan
which is a fork of Corentin Chary's euscan: https://github.com/iksaif/euscan
Right now euscan-ng and (legacy) euscan cannot be installed (system-wide) on the same system.
euscan-ng is available in src_prepare overlay as a dev package (app-portage/euscan-ng-9999).
This tool allows to check if a given package has new upstream versions or not.
It will use different heuristic to scan upstream and grab new versions and related urls.
This tool was designed to mimic debian's uscan, but there is a major
difference between the two: uscan uses a specific "watch" file that describes
how it should scan packages, while euscan-ng uses only what can already be found
in ebuilds. Of course, we could later add some informations in metadata.xml
to help euscan-ng do its job more efficiently.
euscan-ng heuristics are described in the "How does-it works?" section.
Examples
--------
::
$ euscan amatch
* dev-ruby/amatch-0.2.7 [gentoo]
Ebuild: /home/euscan/local/usr/portage/dev-ruby/amatch/amatch-0.2.7.ebuild
Repository: gentoo
Homepage: http://flori.github.com/amatch/
Description: Approximate Matching Extension for Ruby
* SRC_URI is 'mirror://rubygems/amatch-0.2.7.gem'
* Using: http://rubygems.org/api/v1/versions/amatch.json
Upstream Version: 0.2.8 http://rubygems.org/gems/amatch-0.2.8.gem
::
$ euscan rsyslog
* app-admin/rsyslog-5.8.5 [gentoo]
Ebuild: /home/euscan/local/usr/portage/app-admin/rsyslog/rsyslog-5.8.5.ebuild
Repository: gentoo
Homepage: http://www.rsyslog.com/
Description: An enhanced multi-threaded syslogd with database support and more.
* SRC_URI is 'http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.8.5.tar.gz'
* Scanning: http://www.rsyslog.com/files/download/rsyslog/rsyslog-${PV}.tar.gz
* Scanning: http://www.rsyslog.com/files/download/rsyslog
* Generating version from 5.8.5
* Brute forcing: http://www.rsyslog.com/files/download/rsyslog/rsyslog-${PV}.tar.gz
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.8.6.tar.gz ... [ !! ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.8.7.tar.gz ... [ !! ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.8.8.tar.gz ... [ !! ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.0.tar.gz ... [ ok ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.10.0.tar.gz ... [ !! ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.11.0.tar.gz ... [ !! ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.1.tar.gz ... [ ok ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.2.tar.gz ... [ ok ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.3.tar.gz ... [ ok ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.12.0.tar.gz ... [ !! ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.4.tar.gz ... [ !! ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.5.tar.gz ... [ !! ]
* Trying: http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.6.tar.gz ... [ !! ]
Upstream Version: 5.9.1 http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.1.tar.gz
Upstream Version: 5.9.0 http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.0.tar.gz
Upstream Version: 5.9.3 http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.3.tar.gz
Upstream Version: 5.9.2 http://www.rsyslog.com/files/download/rsyslog/rsyslog-5.9.2.tar.gz
Hidden settings
---------------
You can configure some settings using the command line, but the __init__.py
file of the euscan package contains more settings, including blacklists and
default settings.
Maybe we should add the ability to use /etc/euscan.conf and
~/.config/euscan/euscan.conf to override these settings.
How does it work ?
==================
euscan has different heuristics to scan upstream and provides multiple
"handlers". First, here is a description of the generic handler.
Scanning directories
--------------------
The first thing to do is to scan directories. It's also what uscan do, but it
uses a file that describe what url and regexp to use to match packages.
euscan uses SRC_URI and tries to find the current version (or part of this version)
in the resolved SRC_URI and generate a regexp from that.
For example for app-accessibility/dash-4.10.1, SRC_URI is::
mirror://gnome/sources/dasher/4.10/dasher-4.10.1.tar.bz2
euscan will scan pages based on this template::
http://ftp.gnome.org/pub/gnome/sources/dasher/${0}.${1}/dasher-${PV}.tar.bz2
Then, from that, it will scan the top-most directory that doesn't depend on
the version, and try to go deeper from here.
Brute force
-----------
Like when scanning directories, a template of SRC_URI is built. Then euscan
generate next possible version numbers, and tries to download the url generated
from the template and the new version number.
For example, running euscan on portage/app-accessibility/festival-freebsoft-utils-0.6::
SRC_URI is 'http://www.freebsoft.org/pub/projects/festival-freebsoft-utils/festival-freebsoft-utils-0.6.tar.gz'
Template is http://www.freebsoft.org/pub/projects/festival-freebsoft-utils/festival-freebsoft-utils-${PV}.tar.gz
Generate version from 0.6: 0.7, 0.8, 0.10, ...
Try new urls: http://www.freebsoft.org/pub/projects/festival-freebsoft-utils/festival-freebsoft-utils-0.7.tar.gz, etc..
Blacklists
----------
euscan uses blacklist for multiple purposes.
BLACKLIST_VERSIONS
For versions that should not be checked at all. sys-libs/libstdc++-v3-3.4
is good example because it's a package which version will always be 3.4
(Compatibility package for running binaries linked against a pre gcc 3.4 libstdc++).
BLACKLIST_PACKAGES
Some packages are dead, but SRC_URI refers to sources that are still being
updated, for example: sys-kernel/xbox-sources that uses the same sources as
vanilla-sources but is not updated the same way.
SCANDIR_BLACKLIST_URLS
For urls that are not browsable. mirror://gentoo/ is a good example: it's
both stupid to scan it and very long/expensive.
BRUTEFORCE_BLACKLIST_PACKAGES and BRUTEFORCE_BLACKLIST_URLS
Disable brute force on those packages and urls. Most of the time it's because
upstream is broken and will answer HTTP 200 even if the file doesn't exist.
ROBOTS_TXT_BLACKLIST_DOMAINS
Don't respect robots.txt for these domains (sourcefourge, berlios, github.com).
Site handlers
-------------
Pecl/PEAR
A site handler that uses the Pecl/PEAR rest API
(http://pear.php.net/manual/en/core.rest.php).
Rubygems
This one uses rubygems's json API
(http://guides.rubygems.org/rubygems-org-api/)
PyPI
Uses PyPI's XML rpc API.

0
THANKS
View File

61
TODO
View File

@ -4,38 +4,45 @@ TODO
euscan
------
- check other distros (youri)
- steel ideas from other tools (uscan, portscout)
### Version detections
Site Handlers
-------------
- Check other distros (youri, distrowatch, distromatch, whoas; Equivalent-Packages)
- Steal ideas from other tools (uscan, portscout)
- Steal data from other tools (dehs)
- sourceforge: http://sourceforge.net/api/file/index/project-name/vboxgtk/mtime/desc/limit/20/rss http://sourceforge.net/api/release/index/project-id/264534/rss
- ftp.kde.org: doesn't scan the "unstable" tree
- mysql: should use http://downloads.mysql.com/archives/
### Command line interface
- html output
### Tests
- Write tests for handlers
- List some packages to test specific handlers
-- Sourceforge: mummer, bfast, vcftools, mtop, phppgadmin, e2fsprog-libs
-- Berlios: nast, enigma, usbprog, python-wifi, wifi-radar, bcm43xx-fwcutter
-- Google code: pychess, redis, rssguard, ostinato, pidgin-facebookchat
### metadata.xml
- Use handler's statistics page to generate metadata for some packages
(handled by deb or brute force for example)
- Create a subtree of metadata using custom rules
- Finalize format
- Write a GLEP
- Convert subtree
- Commit metadata.xml changes to tree
### packages:
- MySQL: should use http://downloads.mysql.com/archives/
- mariadb: should use http://downloads.askmonty.org/MariaDB/+releases/
euscanwww
---------
- add last scan in the footer
- rss scan world + post ?
- add an /about/config page that describe the current config (overlays, stuff in make.conf, euscan default settings, etc..)
- add a table for overlays, change euscan_versions
### handlers
### Commands
- remote-id type deb repository:
-- find out how to get download url (not sure it's possible)
- euscan_init: init local tree (portage, layman, eix)
- euscan_addoverlay: add a layman overlay
- euscan_sync [--async|--sync]: sync portage, overlays, caches
- euscan_scan [--async|--sync] [--all|--category=<category>|--herd=<herd>|--maintainer=<maintainer>|--package=<package>]: scan local
- euscan_uscan [--async|--sync] [--all|--category=<category>|--herd=<herd>|--maintainer=<maintainer>|--package=<package>]: scan upstream
### Scan process
- Move to celery:
- periodic task for emerge --sync; layman -S; eix-update etc... (every day ?)
- periodic task for euscan (once every week, groupped by category or package ?)
This would allow easier on-demand refresh from web interface
### bugs or unwanted behavior
- Parsing docs and accepting 404's
-- net-analyzer/sensu

View File

@ -1,246 +1,397 @@
#!/usr/bin/python
#!/usr/bin/env python
# Copyright 2011 Corentin Chary <corentin.chary@gmail.com>
# Copyright 2020-2023 src_prepare group
# Distributed under the terms of the GNU General Public License v2
"""Copyright 2011 Gentoo Foundation
Distributed under the terms of the GNU General Public License v2
"""
from __future__ import print_function
""" Meta """
__author__ = "Corentin Chary (iksaif)"
__email__ = "corentin.chary@gmail.com"
__version__ = "git"
__productname__ = "euscan"
__description__ = "A tool to detect new upstream releases."
__version__ = "git"
""" Imports """
import os
import sys
import getopt
import errno
import httplib
from portage.output import white, yellow, turquoise, green, EOutput
from portage.exception import AmbiguousPackageName
# Meta
__author__ = "Corentin Chary (iksaif)"
__email__ = "corentin.chary@gmail.com"
__productname__ = "euscan-ng"
__description__ = "A tool to detect new upstream releases."
# Imports
import getopt
import sys
from errno import EINTR, EINVAL
from http.client import HTTPConnection
from gentoolkit import pprinter as pp
from gentoolkit.eclean.search import (port_settings)
from gentoolkit.errors import GentoolkitException
from portage import settings
from portage.exception import AmbiguousPackageName
from portage.output import green, turquoise, white, yellow
from euscan import CONFIG, output
from euscan.scan import scan_upstream
from euscan._version import __version__
from euscan.out import progress_bar
""" Globals """
# Globals
isatty = os.environ.get("TERM") != "dumb" and sys.stdout.isatty()
isatty_stderr = os.environ.get("TERM") != "dumb" and sys.stderr.isatty()
def setupSignals():
""" This block ensures that ^C interrupts are handled quietly. """
def exit_helper(status):
if CONFIG["format"]:
print(output.get_formatted_output())
sys.exit(status)
def setup_signals():
"""This block ensures that ^C interrupts are handled quietly."""
import signal
def exithandler(signum,frame):
def exithandler(signum, frame):
signal.signal(signal.SIGINT, signal.SIG_IGN)
signal.signal(signal.SIGTERM, signal.SIG_IGN)
print ()
sys.exit(errno.EINTR)
print()
exit_helper(EINTR)
signal.signal(signal.SIGINT, exithandler)
signal.signal(signal.SIGTERM, exithandler)
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
def printVersion():
def print_version():
"""Output the version info."""
print( "%s (%s) - %s" \
% (__productname__, __version__, __description__))
print(f"{__productname__} ({__version__}) - {__description__}")
print()
print("Author: %s <%s>" % (__author__,__email__))
print("Copyright 2011 Gentoo Foundation")
print(f"Copyright 2011 {__author__} <{__email__}>")
print("Copyright 2020-2023 src_prepare group")
print("Distributed under the terms of the GNU General Public License v2")
def printUsage(_error=None, help=None):
def print_usage(_error=None, help=None):
"""Print help message. May also print partial help to stderr if an
error from {'options'} is specified."""
out = sys.stdout
if _error:
out = sys.stderr
if not _error in ('global-options', 'packages',):
if _error not in (
"global-options",
"packages",
):
_error = None
if not _error and not help: help = 'all'
if _error in ('global-options',):
print( pp.error("Wrong option on command line."), file=out)
print( file=out)
if _error in ('packages',):
print( pp.error("You need to specify exactly one package."), file=out)
print( file=out)
print( white("Usage:"), file=out)
if _error in ('global-options', 'packages',) or help == 'all':
print( " "+turquoise(__productname__),
yellow("[options]"),
green("<package> [<package> [...]]"), file=out)
if _error in ('global-options',) or help == 'all':
print( " "+turquoise(__productname__),
yellow("[--help, --version]"), file=out)
if not _error and not help:
help = "all"
if _error in ("global-options",):
output.eerror("Wrong option on command line.\n")
if _error in ("packages",):
output.eerror("You need to specify exactly one package.\n")
print(white("Usage:"), file=out)
if (
_error
in (
"global-options",
"packages",
)
or help == "all"
):
print(
" " + turquoise(__productname__),
yellow("[options]"),
green("<package> [<package> [...]]"),
file=out,
)
if _error in ("global-options",) or help == "all":
print(" " + turquoise(__productname__), yellow("[--help, --version]"), file=out)
print(file=out)
if _error in ('global-options',) or help:
print( "Available ", yellow("options")+":", file=out)
print( yellow(" -C, --nocolor")+
" - turn off colors on output", file=out)
print( yellow(" -q, --quiet")+
" - be as quiet as possible", file=out)
print( yellow(" -h, --help")+ \
" - display the help screen", file=out)
print( yellow(" -V, --version")+
" - display version info", file=out)
print( file=out)
print( yellow(" -1, --oneshot")+
" - stop as soon as a new version is found", file=out)
print( yellow(" -b, --brute-force=<level>")+
" - define the brute force "+yellow("<level>")+" (default: 2)\n" +
" " * 29 + "bigger levels will generate more versions numbers\n" +
" " * 29 + "0 means disabled", file=out)
print( file=out)
if _error in ('packages',) or help:
print( green(" package")+
" - the packages (or ebuilds) you want to scan", file=out)
print( file=out)
'''print( "More detailed instruction can be found in",
turquoise("`man %s`" % __productname__), file=out)'''
if _error in ("global-options",) or help:
print("Available ", yellow("options") + ":", file=out)
print(
yellow(" -C, --nocolor")
+ " - turn off colors on output",
file=out,
)
print(
yellow(" -q, --quiet")
+ " - be as quiet as possible",
file=out,
)
print(
yellow(" -h, --help")
+ " - display the help screen",
file=out,
)
print(
yellow(" -V, --version") + " - display version info",
file=out,
)
print(file=out)
print(
yellow(" -1, --oneshot")
+ " - stop as soon as a new version is found",
file=out,
)
print(
yellow(" -b, --brute-force=<level>")
+ " - define the brute force "
+ yellow("<level>")
+ " (default: 2)\n"
+ " " * 38
+ "bigger levels will generate more versions numbers\n"
+ " " * 38
+ "0 means disabled",
file=out,
)
print(
yellow(" -f, --format=<format>")
+ " - define the output "
+ yellow("<format>")
+ " (available: json, xml)",
file=out,
)
print(
yellow(" -p, --progress") + " - display a progress bar",
file=out,
)
print(
yellow(" -i, --ignore-pre-release")
+ " " * 11
+ "- Ignore non-stable versions",
file=out,
)
print(
yellow(" -I, --ignore-pre-release-if-stable")
+ " - Ignore non-stable versions only if current\n"
+ " " * 38
+ "version is stable",
file=out,
)
print(
yellow(" --mirror") + " - use mirror:// URIs",
file=out,
)
print(
yellow(" --ebuild-uri")
+ " - use ebuild variables in URIs",
file=out,
)
print(
yellow(" --no-handlers")
+ " - exclude handlers (comma-separated list)",
file=out,
)
print(file=out)
if _error in ("packages",) or help:
print(
green(" package")
+ " " * 28
+ "- the packages (or ebuilds) you want to scan",
file=out,
)
print(file=out)
# print( "More detailed instruction can be found in",
# turquoise("`man %s`" % __productname__), file=out)
class ParseArgsException(Exception):
class ParseArgsError(Exception):
"""For parseArgs() -> main() communications."""
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
def parseArgs():
def parse_args():
"""Parse the command line arguments. Raise exceptions on
errors. Returns package and affect the CONFIG dict.
errors. Returns packages and affects the CONFIG dict.
"""
def optionSwitch(opts):
def option_switch(opts):
"""local function for interpreting command line options
and setting options accordingly"""
return_code = True
for o, a in opts:
if o in ("-h", "--help"):
raise ParseArgsException('help')
raise ParseArgsError("help")
elif o in ("-V", "--version"):
raise ParseArgsException('version')
raise ParseArgsError("version")
elif o in ("-C", "--nocolor"):
CONFIG['nocolor'] = True
CONFIG["nocolor"] = True
pp.output.nocolor()
elif o in ("-q", "--quiet"):
CONFIG['quiet'] = True
CONFIG['verbose'] = 0
CONFIG["quiet"] = True
CONFIG["verbose"] = 0
elif o in ("-1", "--oneshot"):
CONFIG['oneshot'] = True
CONFIG["oneshot"] = True
elif o in ("-b", "--brute-force"):
CONFIG['brute-force'] = int(a)
elif o in ("-v", "--verbose") and not CONFIG['quiet']:
CONFIG['verbose'] += 1
CONFIG["brute-force"] = int(a)
elif o in ("-v", "--verbose") and not CONFIG["quiet"]:
CONFIG["verbose"] += 1
elif o in ("-f", "--format"):
CONFIG["format"] = a
CONFIG["nocolor"] = True
pp.output.nocolor()
elif o in ("-p", "--progress"):
CONFIG["progress"] = isatty_stderr
elif o in ("--mirror"):
CONFIG["mirror"] = True
elif o in ("-i", "--ignore-pre-release"):
CONFIG["ignore-pre-release"] = True
elif o in ("-I", "--ignore-pre-release-if-stable"):
CONFIG["ignore-pre-release-if-stable"] = True
elif o in ("--ebuild-uri"):
CONFIG["ebuild-uri"] = True
elif o in ("--no-handlers"):
CONFIG["handlers-exclude"] = a.split(",")
else:
return_code = False
return return_code
' here are the different allowed command line options (getopt args) '
getopt_options = {'short':{}, 'long':{}}
getopt_options['short']['global'] = "hVCqv1b:"
getopt_options['long']['global'] = ["help", "version", "nocolor", "quiet",
"verbose", "oneshot", "brute-force="]
# here are the different allowed command line options (getopt args)
getopt_options = {"short": {}, "long": {}}
getopt_options["short"]["global"] = "hVCqv1b:f:piI"
getopt_options["long"]["global"] = [
"help",
"version",
"nocolor",
"quiet",
"verbose",
"oneshot",
"brute-force=",
"format=",
"progress",
"mirror",
"ignore-pre-release",
"ignore-pre-release-if-stable",
"ebuild-uri",
"no-handlers=",
]
short_opts = getopt_options['short']['global']
long_opts = getopt_options['long']['global']
opts_mode = 'global'
short_opts = getopt_options["short"]["global"]
long_opts = getopt_options["long"]["global"]
opts_mode = "global"
' apply getopts to command line, show partial help on failure '
# apply getopts to command line, show partial help on failure
try:
opts, args = getopt.getopt(sys.argv[1:], short_opts, long_opts)
except:
raise ParseArgsException(opts_mode+'-options')
except getopt.GetoptError as exc:
raise ParseArgsError(opts_mode + "-options") from exc
' set options accordingly '
optionSwitch(opts)
# set options accordingly
option_switch(opts)
if len(args) < 1:
raise ParseArgsException('packages')
raise ParseArgsError("packages")
return args
def main():
"""Parse command line and execute all actions."""
CONFIG['nocolor'] = (port_settings["NOCOLOR"] in ('yes','true')
or not sys.stdout.isatty())
if CONFIG['nocolor']:
CONFIG["nocolor"] = CONFIG["nocolor"] or (
settings["NOCOLOR"] in ("yes", "true") or not isatty
)
if CONFIG["nocolor"]:
pp.output.nocolor()
' parse command line options and actions '
# parse command line options and actions
try:
packages = parseArgs()
except ParseArgsException as e:
if e.value == 'help':
printUsage(help='all')
sys.exit(0)
elif e.value[:5] == 'help-':
printUsage(help=e.value[5:])
sys.exit(0)
elif e.value == 'version':
printVersion()
sys.exit(0)
queries = parse_args()
except ParseArgsError as e:
if e.value == "help":
print_usage(help="all")
exit_helper(0)
elif e.value[:5] == "help-":
print_usage(help=e.value[5:])
exit_helper(0)
elif e.value == "version":
print_version()
exit_helper(0)
else:
printUsage(e.value)
sys.exit(errno.EINVAL)
print_usage(e.value)
exit_helper(EINVAL)
""" Change euscan's output """
output = EOutput(CONFIG['quiet'])
if CONFIG['verbose'] > 2:
httplib.HTTPConnection.debuglevel = 1
if CONFIG["verbose"] > 2:
HTTPConnection.debuglevel = 1
if not CONFIG["format"] and not CONFIG["quiet"]:
CONFIG["progress"] = False
on_progress = None
if CONFIG["progress"]:
on_progress_gen = progress_bar()
on_progress = next(on_progress_gen)
on_progress(maxval=len(queries) * 100, increment=0, label="Working...")
# Importing stuff here for performance reasons
from euscan.scan import scan_upstream
for query in queries:
if CONFIG["progress"]:
on_progress(increment=10, label=query)
for package in packages:
ret = []
output.set_query(query)
try:
ret = scan_upstream(package)
except AmbiguousPackageName as e:
pkgs = e.args[0]
for candidate in pkgs:
print(candidate)
ret = scan_upstream(query, on_progress)
except AmbiguousPackageName as e:
pkgs = e.args[0]
output.eerror("\n".join(pkgs))
from os.path import basename # To get the short name
from os.path import basename # To get the short name
output.eerror(
"The short ebuild name '%s' is ambiguous. Please specify"
% basename(pkgs[0])
+ "one of the above fully-qualified ebuild names instead."
)
exit_helper(1)
except GentoolkitException as err:
output.eerror(f"{query}: {str(err)}")
exit_helper(1)
print(file=sys.stderr)
print(pp.error("The short ebuild name '%s' is ambiguous. Please specify" % basename(pkgs[0])),
file=sys.stderr, end="")
pp.die(1, "one of the above fully-qualified ebuild names instead.")
except GentoolkitException as err:
pp.die(1, str(err))
except Exception as err:
pp.die(1, str(err))
import traceback
print ()
print("-" * 60)
traceback.print_exc(file=sys.stderr)
print("-" * 60)
for url, version in ret:
print ("Upstream Version: "
+ pp.number("%s" % version)
+ pp.path(" %s" % url))
output.eerror(f"{query}: {str(err)}")
exit_helper(1)
if not len(ret):
print (pp.warn("Didn't find any new version, "
+ "check package's homepage for "
+ "more informations"));
if not ret and not CONFIG["quiet"]:
output.einfo(
"Didn't find any new version, check package's homepage "
+ "for more informations"
)
if not (CONFIG["format"] or CONFIG["quiet"]) and len(queries) > 1:
print("")
if CONFIG["progress"]:
next(on_progress_gen)
print("\n", file=sys.stderr)
output.set_query(None)
if __name__ == "__main__":
try:
setupSignals()
main()
except KeyboardInterrupt:
print( "Aborted.")
sys.exit(errno.EINTR)
sys.exit(0)
setup_signals()
main()
exit_helper(0)

276
bin/euscan_patch_metadata Executable file
View File

@ -0,0 +1,276 @@
#!/usr/bin/env python
# Copyright 2011 Corentin Chary <corentin.chary@gmail.com>
# Copyright 2020-2023 src_prepare group
# Distributed under the terms of the GNU General Public License v2
import gzip
import logging
import os
import re
import shutil
import sys
import tarfile
import urllib
from difflib import unified_diff
from tempfile import mkstemp
from BeautifulSoup import BeautifulSoup, SoupStrainer
from gentoolkit.query import Query
from portage.exception import AmbiguousPackageName
logger = logging.getLogger(__name__)
# From portage-janitor
def guess_indent_values(before):
rindent = -1
indent = -1
tab = False
def guess_for_tags(tags):
for tag in tags:
for i in [0, 2, 4, 6, 8, 12, 16]:
if f"\n{' ' * i}<{tag}" in before:
return i, False
for i in [0, 1, 2]:
if f"\n{'\t' * i}<{tag}" in before:
return i, True
return -1, False
rindent, tab = guess_for_tags(
["herd", "maintainer", "longdescription", "use", "upstream"]
)
if rindent == -1:
rindent = 2
rindent_str = ("\t" if tab else " ") * rindent
indent, tab = guess_for_tags(["watch", "name", "email"])
if indent == -1:
indent = rindent * 2 if rindent else 4
if rindent and rindent_str == "\t":
tab = True
indent_str = ("\t" if tab else " ") * indent
return rindent_str, indent_str
def get_watch_data(package):
deb_url, deb_type = get_deb_url(package.name)
if deb_type == "source":
return handle_source(deb_url)
if deb_type == "diff":
return handle_diff(deb_url)
def handle_diff(deb_url):
_, temp_deb = mkstemp()
logger.info(" Downloading debian diff %s...", deb_url)
urllib.urlretrieve(deb_url, temp_deb)
watch_data = ""
fp = gzip.open(temp_deb, "rb")
for line in fp:
if re.match(r"\+\+\+ .+?/debian/watch", line):
fp.readline() # diff lines, don't care
cur_line = fp.readline()
while cur_line.startswith("+"):
watch_data += cur_line[1:]
cur_line = fp.readline()
fp.close()
os.unlink(temp_deb)
return watch_data
def handle_source(deb_url):
_, temp_deb = mkstemp()
temp_dir = os.path.dirname(temp_deb)
logger.info(" Downloading debian source %s...", deb_url)
urllib.urlretrieve(deb_url, temp_deb)
tar = tarfile.open(temp_deb)
watch_data = None
try:
tar.extract("debian/watch", temp_dir)
except KeyError:
pass
else:
debian_path = os.path.join(temp_dir, "debian")
watch_path = os.path.join(debian_path, "watch")
watch_data = open(os.path.join(watch_path)).read()
shutil.rmtree(debian_path)
os.unlink(temp_deb)
return watch_data
def get_deb_url(name):
deb_url = None
deb_type = None
while not deb_url:
url = "http://packages.debian.org/source/unstable/%s" % name
opened = urllib.urlopen(url)
content = opened.read()
for link in BeautifulSoup(content, parseOnlyThese=SoupStrainer("a")):
if re.match(r"[^\s]+\.debian\.tar\.(?:gz|bz2)", link.text):
deb_url = link["href"]
deb_type = "source"
break
if re.match(r"[^\s]+\.diff\.gz", link.text):
deb_url = link["href"]
deb_type = "diff"
break
if not deb_url:
logger.error(" Cannot get package from %s" % url)
name = input(" Package name in Debian: ")
return deb_url, deb_type
def patch_metadata(package, watch_data, diff=False):
logger.info(" Patching metadata file")
metadata_path = package.metadata.metadata_path
with open(metadata_path) as fp:
original = fp.read()
rindent, indent = guess_indent_values(original)
data = original
# clean watch_data
watch_data = "\n".join(
[line for line in watch_data.split("\n") if not line.startswith("#")]
) # comments
watch_data = watch_data.replace("\\\n", "") # remove backslashes
watch_tags = []
for watch_line in watch_data.split("\n"): # there can be multiple lines
watch_line = " ".join(watch_line.split()) # remove extra spaces and \n
version_parse = re.match(r"version=(\d+?)", watch_line)
if version_parse:
version = version_parse.group(1)
continue
if not watch_line: # skip empty lines
continue
# parse watch_line
result = re.match(r'(?:opts=(?:"([^"]+?)"|([^\s]+?)) )?(.*)', watch_line)
opts_quote, opts, url = result.groups()
opts = opts_quote or opts
if opts:
# clean opts, skip useless ones
valid = ("uversionmangle", "versionmangle", "downloadurlmangle")
cleaned_opts = []
for opt in opts.split(","):
opt_name, opt_value = opt.split("=", 1)
if opt_name in valid:
if opt_name == "uversionmangle":
opt_name = "versionmangle"
cleaned_opts.append(f'{opt_name}="{opt_value}"')
opts = " ".join(cleaned_opts)
# clean url from useless stuff. Just keep <base> [<filepattern>]
url_search = re.search(r"^([^\s]+)(?: ([^\s]*\([^\s]+\)[^\s]*))?", url)
url = " ".join([x for x in url_search.groups() if x is not None])
if opts:
watch_tag = f'{indent}<watch version="{version}" {opts}>{url}</watch>'
else:
watch_tag = f'{indent}<watch version="{version}">{url}</watch>'
watch_tags.append(watch_tag)
watch_tags = "\n".join(watch_tags)
if "<upstream>" in data:
data = data.replace("<upstream>", "<upstream>\n%s" % watch_tags, 1)
else:
rep = f"{rindent}<upstream>\n{watch_tags}\n{rindent}</upstream>\n</pkgmetadata>"
data = data.replace("</pkgmetadata>", rep, 1)
if not diff:
return data
else:
# Generate clean a/category/package/metadata.xml path
n = metadata_path.find(package.category)
if n != -1:
metadata_path = metadata_path[n:]
res = unified_diff(
original.splitlines(True),
data.splitlines(True),
fromfile=os.path.join("a/", metadata_path),
tofile=os.path.join("b/", metadata_path),
)
return "".join([x for x in res])
def process_package(query, diff=False):
try:
matches = Query(query).smart_find(
in_installed=True,
in_porttree=True,
in_overlay=True,
include_masked=True,
show_progress=False,
no_matches_fatal=False,
)
except AmbiguousPackageName:
logger.error(" Ambiguous package name")
return None
if len(matches) == 0:
logger.error(" Package not found")
return None
matches = sorted(matches)
package = matches.pop()
if "9999" in package.version and len(matches) > 0:
package = matches.pop()
watch_data = get_watch_data(package)
if watch_data is None:
logger.error(" No watch file found")
else:
return patch_metadata(package, watch_data, diff=diff)
def main():
import optparse
p = optparse.OptionParser(
usage="usage: %prog <package> [<package> [...]]",
)
p.add_option(
"-d",
"--diff",
action="store_true",
dest="diff",
default=False,
help="Outputs a diff",
)
opts, packages = p.parse_args()
logging.basicConfig(stream=sys.stderr, level=logging.INFO, format="%(message)s")
for package in packages:
logger.info("Processing %s..." % package)
result = process_package(package, opts.diff)
if result:
sys.stdout.write(result)
if __name__ == "__main__":
main()

View File

View File

@ -1,194 +0,0 @@
from django.shortcuts import render_to_response
from django import forms
from django.template import RequestContext
from django.db.models import signals as signalmodule
from django.http import HttpResponse
from django.utils import simplejson
__all__ = ['render_to', 'signals', 'ajax_request', 'autostrip']
try:
from functools import wraps
except ImportError:
def wraps(wrapped, assigned=('__module__', '__name__', '__doc__'),
updated=('__dict__',)):
def inner(wrapper):
for attr in assigned:
setattr(wrapper, attr, getattr(wrapped, attr))
for attr in updated:
getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
return wrapper
return inner
def render_to(template=None, mimetype=None):
"""
Decorator for Django views that sends returned dict to render_to_response
function.
Template name can be decorator parameter or TEMPLATE item in returned
dictionary. RequestContext always added as context instance.
If view doesn't return dict then decorator simply returns output.
Parameters:
- template: template name to use
- mimetype: content type to send in response headers
Examples:
# 1. Template name in decorator parameters
@render_to('template.html')
def foo(request):
bar = Bar.object.all()
return {'bar': bar}
# equals to
def foo(request):
bar = Bar.object.all()
return render_to_response('template.html',
{'bar': bar},
context_instance=RequestContext(request))
# 2. Template name as TEMPLATE item value in return dictionary.
if TEMPLATE is given then its value will have higher priority
than render_to argument.
@render_to()
def foo(request, category):
template_name = '%s.html' % category
return {'bar': bar, 'TEMPLATE': template_name}
#equals to
def foo(request, category):
template_name = '%s.html' % category
return render_to_response(template_name,
{'bar': bar},
context_instance=RequestContext(request))
"""
def renderer(function):
@wraps(function)
def wrapper(request, *args, **kwargs):
output = function(request, *args, **kwargs)
if not isinstance(output, dict):
return output
tmpl = output.pop('TEMPLATE', template)
return render_to_response(tmpl, output, \
context_instance=RequestContext(request), mimetype=mimetype)
return wrapper
return renderer
class Signals(object):
'''
Convenient wrapper for working with Django's signals (or any other
implementation using same API).
Example of usage::
# connect to registered signal
@signals.post_save(sender=YourModel)
def sighandler(instance, **kwargs):
pass
# connect to any signal
signals.register_signal(siginstance, signame) # and then as in example above
or
@signals(siginstance, sender=YourModel)
def sighandler(instance, **kwargs):
pass
In any case defined function will remain as is, without any changes.
(c) 2008 Alexander Solovyov, new BSD License
'''
def __init__(self):
self._signals = {}
# register all Django's default signals
for k, v in signalmodule.__dict__.iteritems():
# that's hardcode, but IMHO it's better than isinstance
if not k.startswith('__') and k != 'Signal':
self.register_signal(v, k)
def __getattr__(self, name):
return self._connect(self._signals[name])
def __call__(self, signal, **kwargs):
def inner(func):
signal.connect(func, **kwargs)
return func
return inner
def _connect(self, signal):
def wrapper(**kwargs):
return self(signal, **kwargs)
return wrapper
def register_signal(self, signal, name):
self._signals[name] = signal
signals = Signals()
class JsonResponse(HttpResponse):
"""
HttpResponse descendant, which return response with ``application/json`` mimetype.
"""
def __init__(self, data):
super(JsonResponse, self).__init__(content=simplejson.dumps(data), mimetype='application/json')
def ajax_request(func):
"""
If view returned serializable dict, returns JsonResponse with this dict as content.
example:
@ajax_request
def my_view(request):
news = News.objects.all()
news_titles = [entry.title for entry in news]
return {'news_titles': news_titles}
"""
@wraps(func)
def wrapper(request, *args, **kwargs):
response = func(request, *args, **kwargs)
if isinstance(response, dict):
return JsonResponse(response)
else:
return response
return wrapper
def autostrip(cls):
"""
strip text fields before validation
example:
class PersonForm(forms.Form):
name = forms.CharField(min_length=2, max_length=10)
email = forms.EmailField()
PersonForm = autostrip(PersonForm)
#or you can use @autostrip in python >= 2.6
Author: nail.xx
"""
fields = [(key, value) for key, value in cls.base_fields.iteritems() if isinstance(value, forms.CharField)]
for field_name, field_object in fields:
def get_clean_func(original_clean):
return lambda value: original_clean(value and value.strip())
clean_func = get_clean_func(getattr(field_object, 'clean'))
setattr(field_object, 'clean', clean_func)
return cls

View File

@ -1,5 +0,0 @@
class Redirect(Exception):
def __init__(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs

View File

@ -1,69 +0,0 @@
from django.db import models
from django.db.models import OneToOneField
from django.utils import simplejson as json
from django.core.serializers.json import DjangoJSONEncoder
from django.db.models.fields.related import SingleRelatedObjectDescriptor
class AutoSingleRelatedObjectDescriptor(SingleRelatedObjectDescriptor):
def __get__(self, instance, instance_type=None):
try:
return super(AutoSingleRelatedObjectDescriptor, self).__get__(instance, instance_type)
except self.related.model.DoesNotExist:
obj = self.related.model(**{self.related.field.name: instance})
obj.save()
return obj
class AutoOneToOneField(OneToOneField):
'''
OneToOneField creates related object on first call if it doesnt exist yet.
Use it instead of original OneToOne field.
example:
class MyProfile(models.Model):
user = AutoOneToOneField(User, primary_key=True)
home_page = models.URLField(max_length=255, blank=True)
icq = models.IntegerField(max_length=255, null=True)
'''
def contribute_to_related_class(self, cls, related):
setattr(cls, related.get_accessor_name(), AutoSingleRelatedObjectDescriptor(related))
class JSONField(models.TextField):
"""
JSONField is a generic textfield that neatly serializes/unserializes
JSON objects seamlessly.
Django snippet #1478
example:
class Page(models.Model):
data = JSONField(blank=True, null=True)
page = Page.objects.get(pk=5)
page.data = {'title': 'test', 'type': 3}
page.save()
"""
__metaclass__ = models.SubfieldBase
def to_python(self, value):
if value == "":
return None
try:
if isinstance(value, basestring):
return json.loads(value)
except ValueError:
pass
return value
def get_db_prep_save(self, value, *args, **kwargs):
if value == "":
return None
if isinstance(value, dict):
value = json.dumps(value, cls=DjangoJSONEncoder)
return super(JSONField, self).get_db_prep_save(value, *args, **kwargs)

View File

@ -1,32 +0,0 @@
from django.shortcuts import _get_queryset
from django.conf import settings
def get_object_or_None(klass, *args, **kwargs):
"""
Uses get() to return an object or None if the object does not exist.
klass may be a Model, Manager, or QuerySet object. All other passed
arguments and keyword arguments are used in the get() query.
Note: Like with get(), a MultipleObjectsReturned will be raised if more than one
object is found.
"""
queryset = _get_queryset(klass)
try:
return queryset.get(*args, **kwargs)
except queryset.model.DoesNotExist:
return None
def get_config(key, default):
"""
Get settings from django.conf if exists,
return default value otherwise
example:
ADMIN_EMAIL = get_config('ADMIN_EMAIL', 'default@email.com')
"""
return getattr(settings, key, default)

View File

@ -1,32 +0,0 @@
import re
from django.conf import settings
from django.views.static import serve
from django.shortcuts import redirect
from .exceptions import Redirect
class StaticServe(object):
"""
Django middleware for serving static files instead of using urls.py
"""
regex = re.compile(r'^%s(?P<path>.*)$' % settings.MEDIA_URL)
def process_request(self, request):
if settings.DEBUG:
match = self.regex.search(request.path)
if match:
return serve(request, match.group(1), settings.MEDIA_ROOT)
class RedirectMiddleware(object):
"""
You must add this middleware to MIDDLEWARE_CLASSES list,
to make work Redirect exception. All arguments passed to
Redirect will be passed to django built in redirect function.
"""
def process_exception(self, request, exception):
if not isinstance(exception, Redirect):
return
return redirect(*exception.args, **exception.kwargs)

View File

@ -1,14 +0,0 @@
import django
from django import template
from smart_if import smart_if
register = template.Library()
try:
if int(django.get_version()[-5:]) < 11806:
register.tag('if', smart_if)
except ValueError:
pass

View File

@ -1,240 +0,0 @@
from django import template
__author__ = "SmileyChris"
#==============================================================================
# Calculation objects
#==============================================================================
class BaseCalc(object):
def __init__(self, var1, var2=None, negate=False):
self.var1 = var1
self.var2 = var2
self.negate = negate
def resolve(self, context):
try:
var1, var2 = self.resolve_vars(context)
outcome = self.calculate(var1, var2)
except:
outcome = False
if self.negate:
return not outcome
return outcome
def resolve_vars(self, context):
var2 = self.var2 and self.var2.resolve(context)
return self.var1.resolve(context), var2
def calculate(self, var1, var2):
raise NotImplementedError()
class Or(BaseCalc):
def calculate(self, var1, var2):
return var1 or var2
class And(BaseCalc):
def calculate(self, var1, var2):
return var1 and var2
class Equals(BaseCalc):
def calculate(self, var1, var2):
return var1 == var2
class Greater(BaseCalc):
def calculate(self, var1, var2):
return var1 > var2
class GreaterOrEqual(BaseCalc):
def calculate(self, var1, var2):
return var1 >= var2
class In(BaseCalc):
def calculate(self, var1, var2):
return var1 in var2
OPERATORS = {
'=': (Equals, True),
'==': (Equals, True),
'!=': (Equals, False),
'>': (Greater, True),
'>=': (GreaterOrEqual, True),
'<=': (Greater, False),
'<': (GreaterOrEqual, False),
'or': (Or, True),
'and': (And, True),
'in': (In, True),
}
BOOL_OPERATORS = ('or', 'and')
class IfParser(object):
error_class = ValueError
def __init__(self, tokens):
self.tokens = tokens
def _get_tokens(self):
return self._tokens
def _set_tokens(self, tokens):
self._tokens = tokens
self.len = len(tokens)
self.pos = 0
tokens = property(_get_tokens, _set_tokens)
def parse(self):
if self.at_end():
raise self.error_class('No variables provided.')
var1 = self.get_bool_var()
while not self.at_end():
op, negate = self.get_operator()
var2 = self.get_bool_var()
var1 = op(var1, var2, negate=negate)
return var1
def get_token(self, eof_message=None, lookahead=False):
negate = True
token = None
pos = self.pos
while token is None or token == 'not':
if pos >= self.len:
if eof_message is None:
raise self.error_class()
raise self.error_class(eof_message)
token = self.tokens[pos]
negate = not negate
pos += 1
if not lookahead:
self.pos = pos
return token, negate
def at_end(self):
return self.pos >= self.len
def create_var(self, value):
return TestVar(value)
def get_bool_var(self):
"""
Returns either a variable by itself or a non-boolean operation (such as
``x == 0`` or ``x < 0``).
This is needed to keep correct precedence for boolean operations (i.e.
``x or x == 0`` should be ``x or (x == 0)``, not ``(x or x) == 0``).
"""
var = self.get_var()
if not self.at_end():
op_token = self.get_token(lookahead=True)[0]
if isinstance(op_token, basestring) and (op_token not in
BOOL_OPERATORS):
op, negate = self.get_operator()
return op(var, self.get_var(), negate=negate)
return var
def get_var(self):
token, negate = self.get_token('Reached end of statement, still '
'expecting a variable.')
if isinstance(token, basestring) and token in OPERATORS:
raise self.error_class('Expected variable, got operator (%s).' %
token)
var = self.create_var(token)
if negate:
return Or(var, negate=True)
return var
def get_operator(self):
token, negate = self.get_token('Reached end of statement, still '
'expecting an operator.')
if not isinstance(token, basestring) or token not in OPERATORS:
raise self.error_class('%s is not a valid operator.' % token)
if self.at_end():
raise self.error_class('No variable provided after "%s".' % token)
op, true = OPERATORS[token]
if not true:
negate = not negate
return op, negate
#==============================================================================
# Actual templatetag code.
#==============================================================================
class TemplateIfParser(IfParser):
error_class = template.TemplateSyntaxError
def __init__(self, parser, *args, **kwargs):
self.template_parser = parser
return super(TemplateIfParser, self).__init__(*args, **kwargs)
def create_var(self, value):
return self.template_parser.compile_filter(value)
class SmartIfNode(template.Node):
def __init__(self, var, nodelist_true, nodelist_false=None):
self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
self.var = var
def render(self, context):
if self.var.resolve(context):
return self.nodelist_true.render(context)
if self.nodelist_false:
return self.nodelist_false.render(context)
return ''
def __repr__(self):
return "<Smart If node>"
def __iter__(self):
for node in self.nodelist_true:
yield node
if self.nodelist_false:
for node in self.nodelist_false:
yield node
def get_nodes_by_type(self, nodetype):
nodes = []
if isinstance(self, nodetype):
nodes.append(self)
nodes.extend(self.nodelist_true.get_nodes_by_type(nodetype))
if self.nodelist_false:
nodes.extend(self.nodelist_false.get_nodes_by_type(nodetype))
return nodes
def smart_if(parser, token):
"""
A smarter {% if %} tag for django templates.
While retaining current Django functionality, it also handles equality,
greater than and less than operators. Some common case examples::
{% if articles|length >= 5 %}...{% endif %}
{% if "ifnotequal tag" != "beautiful" %}...{% endif %}
Arguments and operators _must_ have a space between them, so
``{% if 1>2 %}`` is not a valid smart if tag.
All supported operators are: ``or``, ``and``, ``in``, ``=`` (or ``==``),
``!=``, ``>``, ``>=``, ``<`` and ``<=``.
"""
bits = token.split_contents()[1:]
var = TemplateIfParser(parser, bits).parse()
nodelist_true = parser.parse(('else', 'endif'))
token = parser.next_token()
if token.contents == 'else':
nodelist_false = parser.parse(('endif',))
parser.delete_first_token()
else:
nodelist_false = None
return SmartIfNode(var, nodelist_true, nodelist_false)

View File

@ -1,26 +0,0 @@
from django.http import HttpResponse
from django.utils.encoding import iri_to_uri
class HttpResponseReload(HttpResponse):
"""
Reload page and stay on the same page from where request was made.
example:
def simple_view(request):
if request.POST:
form = CommentForm(request.POST):
if form.is_valid():
form.save()
return HttpResponseReload(request)
else:
form = CommentForm()
return render_to_response('some_template.html', {'form': form})
"""
status_code = 302
def __init__(self, request):
HttpResponse.__init__(self)
referer = request.META.get('HTTP_REFERER')
self['Location'] = iri_to_uri(referer or "/")

View File

@ -1,186 +0,0 @@
from piston.handler import AnonymousBaseHandler, BaseHandler
from piston.utils import rc, HttpStatusCode
from django.db.models import Sum, Max
from django.core.exceptions import ObjectDoesNotExist
from django.forms.models import model_to_dict
from euscan.models import Version, Package, Herd, Maintainer, EuscanResult, VersionLog
from euscan.forms import WorldForm, PackagesForm
def xint(i):
try:
return int(i)
except:
return 0
def renameFields(vqs, fields):
ret = []
for n in vqs:
for tr in fields:
if tr[0] in n:
n[tr[1]] = n[tr[0]]
del n[tr[0]]
ret.append(n)
return ret
class catch_and_return(object):
def __init__(self, err, response):
self.err = err
self.response = response
def __call__(self, fn):
def wrapper(*args, **kwargs):
try:
return fn(*args, **kwargs)
except self.err:
return self.response
return wrapper
# /api/1.0/
class RootHandler(AnonymousBaseHandler):
allowed_methods = ('GET',)
def read(self, request):
return {'api-version': '1.0'}
# /api/1.0/statistics
class StatisticsHandler(AnonymousBaseHandler):
allowed_methods = ('GET',)
def read(self, request):
data = {}
data['n_packaged'] = xint(Package.objects.aggregate(Sum('n_packaged'))['n_packaged__sum'])
data['n_overlay'] = xint(Package.objects.aggregate(Sum('n_overlay'))['n_overlay__sum'])
data['n_versions'] = xint(Package.objects.aggregate(Sum('n_versions'))['n_versions__sum'])
data['n_upstream'] = data['n_versions'] - data['n_packaged'] - data['n_overlay']
data['n_packages'] = Package.objects.count()
data['n_herds'] = Herd.objects.count()
data['n_maintainers'] = Maintainer.objects.count()
data['last_scan'] = EuscanResult.objects.get(id=EuscanResult.objects.aggregate(Max('id'))['id__max']).datetime
return data
# /api/1.0/maintainers
class MaintainersHandler(AnonymousBaseHandler):
allowed_methods = ('GET',)
def read(self, request):
maintainers = Package.objects.filter(maintainers__isnull=False)
maintainers = maintainers.values('maintainers__id', 'maintainers__name', 'maintainers__email')
maintainers = maintainers.annotate(n_packaged=Sum('n_packaged'),
n_overlay=Sum('n_overlay'),
n_versions=Sum('n_versions'))
maintainers = renameFields(maintainers, [('maintainers__id', 'id'),
('maintainers__name', 'name'),
('maintainers__email', 'email')])
return maintainers
# /api/1.0/herds
class HerdsHandler(AnonymousBaseHandler):
allowed_methods = ('GET',)
def read(self, request):
# FIXME: optimize the query, it uses 'LEFT OUTER JOIN' instead of 'INNER JOIN'
herds = Package.objects.filter(herds__isnull=False)
herds = herds.values('herds__herd').annotate(n_packaged=Sum('n_packaged'),
n_overlay=Sum('n_overlay'),
n_versions=Sum('n_versions'))
herds = renameFields(herds, [('herds__herd', 'herd')])
return herds
# /api/1.0/categories
class CategoriesHandler(AnonymousBaseHandler):
allowed_methods = ('GET',)
def read(self, request):
categories = Package.objects.values('category')
categories = categories.annotate(n_packaged=Sum('n_packaged'),
n_overlay=Sum('n_overlay'),
n_versions=Sum('n_versions'))
return categories
# /api/1.0/packages/by-maintainer/
# /api/1.0/packages/by-category/
# /api/1.0/packages/by-herd/
class PackagesHandler(AnonymousBaseHandler):
allowed_methods = ('GET',)
fields = ('category', 'name', 'n_packaged', 'n_overlay', 'n_versions')
model = Package
@catch_and_return(ObjectDoesNotExist, rc.NOT_FOUND)
def read(self, request, **kwargs):
data = {}
if 'category' in kwargs:
packages = Package.objects.filter(category=kwargs['category'])
data = { 'category' : kwargs['category'], 'packages' : packages }
elif 'herd' in kwargs:
herd = Herd.objects.get(herd=kwargs['herd'])
packages = Package.objects.filter(herds__id=herd.id)
data = { 'herd' : herd, 'packages' : packages }
elif 'maintainer_id' in kwargs:
maintainer = Maintainer.objects.get(id=kwargs['maintainer_id'])
packages = Package.objects.filter(maintainers__id=maintainer.id)
data = { 'maintainer' : maintainer, 'packages' : packages }
if not data:
return rc.NOT_FOUND
return data
# /api/1.0/package/
class PackageHandler(AnonymousBaseHandler):
allowed_methods = ('GET',)
@catch_and_return(ObjectDoesNotExist, rc.NOT_FOUND)
def read(self, request, category, package):
package = Package.objects.get(category=category, name=package)
package.homepages = package.homepage.split(' ')
versions = Version.objects.filter(package=package)
log = EuscanResult.objects.filter(package=package).order_by('-datetime')[:1]
log = log[0] if log else None
vlog = VersionLog.objects.filter(package=package).order_by('-id')
herds = []
for herd in package.herds.all():
herds.append(model_to_dict(herd, ['herd']))
maintainers = []
for maintainer in package.maintainers.all():
maintainers.append(model_to_dict(maintainer, ['name', 'email']))
version_log = []
for v in vlog:
v = model_to_dict(v, ['version', 'revision', 'slot', 'overlay', 'datetime', 'action'])
if v['action'] == VersionLog.VERSION_ADDED:
v['action'] = 'added'
if v['action'] == VersionLog.VERSION_REMOVED:
v['action'] = 'removed'
version_log.append(v)
upstream = []
packaged = []
for version in versions:
unpackaged = not version.packaged
version = model_to_dict(version, ['version', 'revision', 'slot', 'overlay', 'urls'])
if unpackaged:
upstream.append(version)
else:
packaged.append(version)
package = model_to_dict(package, ['category', 'name', 'description',
'homepage'])
package['herds'] = herds
package['maintainers'] = maintainers
package['packaged'] = packaged
package['upstream'] = upstream
package['vlog'] = version_log
if log:
package['log'] = model_to_dict(log, ['result', 'datetime'])
return package

View File

@ -1,27 +0,0 @@
from django.conf.urls.defaults import *
from piston.resource import Resource
from api.handlers import *
root_handler = Resource(handler=RootHandler)
statistics_handler = Resource(handler=StatisticsHandler)
herds_handler = Resource(handler=HerdsHandler)
categories_handler = Resource(handler=CategoriesHandler)
maintainers_handler = Resource(handler=MaintainersHandler)
packages_handler = Resource(handler=PackagesHandler)
package_handler = Resource(handler=PackageHandler)
urlpatterns = patterns('api.views',
url(r'^1.0/statistics\.(?P<emitter_format>.+)$', statistics_handler, name='api.views.statistics'),
url(r'^1.0/herds\.(?P<emitter_format>.+)$', herds_handler, name='api.views.herds'),
url(r'^1.0/categories\.(?P<emitter_format>.+)$', categories_handler, name='api.views.categories'),
url(r'^1.0/maintainers\.(?P<emitter_format>.+)$', maintainers_handler, name='api.views.maintainers'),
url(r'^1.0/packages/by-maintainer/(?P<maintainer_id>\d+)\.(?P<emitter_format>.+)$', packages_handler, name='api.views.packages'),
url(r'^1.0/packages/by-herd/(?P<herd>[\@\{\}\w+.-]*)\.(?P<emitter_format>.+)?$', packages_handler, name='api.views.packages'),
url(r'^1.0/packages/by-category/(?P<category>[\w+][\w+.-]*)\.(?P<emitter_format>.+)?$', packages_handler, name='api.views.packages'),
url(r'^1.0/package/(?P<category>[\w+][\w+.-]*)/(?P<package>[\w+][\w+.-]*)\.(?P<emitter_format>.+)$', package_handler, name='api.views.package'),
url(r'^1.0/api\.(?P<emitter_format>.+)$', root_handler, name='api.views.root'),
)

View File

@ -1,20 +0,0 @@
from euscan.models import Herd, Maintainer, Package, Version, VersionLog, EuscanResult, Log, \
WorldLog, CategoryLog, HerdLog, MaintainerLog
from django.contrib import admin
admin.site.register(Herd)
admin.site.register(Maintainer)
class PackageAdmin(admin.ModelAdmin):
search_fields = ('category', 'name')
admin.site.register(Package, PackageAdmin)
admin.site.register(Version)
admin.site.register(VersionLog)
admin.site.register(EuscanResult)
admin.site.register(Log)
admin.site.register(WorldLog)
admin.site.register(CategoryLog)
admin.site.register(HerdLog)
admin.site.register(MaintainerLog)

View File

@ -1,261 +0,0 @@
import os.path
import time
from euscanwww import settings
from django.db.models import F, Sum, Max
from euscan.models import Version, Package, Herd, Maintainer
from euscan.models import CategoryLog
import rrdtool
import pylab
import matplotlib
CHARTS_ROOT = os.path.join(settings.MEDIA_ROOT, "charts")
CHARTS_URL = os.path.join(settings.MEDIA_URL, "charts")
CHARTS_TTL = (24 * 60 * 60)
pylab.rcParams['font.size'] = 10.0
pylab.rcParams['axes.titlesize'] = 10.0
pylab.rcParams['xtick.labelsize'] = 8.0
pylab.rcParams['legend.fontsize'] = 8.0
def xint(i):
try:
return int(i)
except:
return 0
def chart_alive(name):
path = os.path.join(CHARTS_ROOT, name)
if not os.path.exists(path):
return False
if os.path.getmtime(__file__) > os.path.getmtime(path):
return False
if os.path.getmtime(path) + CHARTS_TTL < time.time():
return False
return True
def rrd_name(**kwargs):
name = ""
if 'category' in kwargs and kwargs['category']:
name = 'category-%s' % kwargs['category']
elif 'herd' in kwargs and kwargs['herd']:
name = 'herd-%d' % kwargs['herd'].id
elif 'maintainer' in kwargs and kwargs['maintainer']:
name = 'maintainer-%d' % kwargs['maintainer'].id
else:
name = 'world'
return name
def chart_name(name, **kwargs):
name = name.replace('_', '-')
if 'category' in kwargs and kwargs['category']:
name += '-%s' % kwargs['category']
if 'herd' in kwargs and kwargs['herd']:
name += '-h-%d' % kwargs['herd'].id
if 'maintainer' in kwargs and kwargs['maintainer']:
name += '-m-%d' % kwargs['maintainer'].id
for kw in ('-small', '-weekly', '-monthly', '-yearly'):
if kw in kwargs:
name += kw
return name + ".png"
def getpackages(**kwargs):
packages = Package.objects
if 'category' in kwargs and kwargs['category']:
packages = packages.filter(category=kwargs['category'])
if 'herd' in kwargs and kwargs['herd']:
packages = packages.filter(herds__id=kwargs['herd'].id)
if 'maintainer' in kwargs and kwargs['maintainer']:
packages = packages.filter(maintainers__id=kwargs['maintainer'].id)
return packages
def cached_pylab_chart(f):
def new_f(*args, **kwds):
name = chart_name(f.func_name, **kwds)
if not chart_alive(name):
f(*args, **kwds)
pylab.savefig(os.path.join(CHARTS_ROOT, name))
pylab.close()
return name
new_f.func_name = f.func_name
return new_f
@cached_pylab_chart
def pie_versions(**kwargs):
n_packaged = xint(getpackages(**kwargs).aggregate(Sum('n_packaged'))['n_packaged__sum'])
n_overlay = xint(getpackages(**kwargs).aggregate(Sum('n_overlay'))['n_overlay__sum'])
n_versions = xint(getpackages(**kwargs).aggregate(Sum('n_versions'))['n_versions__sum'])
n_upstream = n_versions - n_packaged - n_overlay
pylab.figure(1, figsize=(3.5,3.5))
if n_overlay:
labels = 'Gentoo', 'Overlays', 'Upstream'
fracs = [n_packaged, n_overlay, n_upstream]
colors = '#008000', '#0B17FD', '#FF0000'
else:
labels = 'Gentoo', 'Upstream'
fracs = [n_packaged, n_upstream]
colors = '#008000', '#FF0000'
pylab.pie(fracs, labels=labels, colors=colors, autopct='%1.1f%%', shadow=True)
pylab.title('Versions', bbox={'facecolor':'0.8', 'pad':5})
@cached_pylab_chart
def pie_packages(**kwargs):
n_packages = getpackages(**kwargs).count()
n_packages_uptodate_main = getpackages(**kwargs).filter(n_versions=F('n_packaged')).count()
n_packages_uptodate_all = getpackages(**kwargs).filter(n_versions=F('n_packaged') + F('n_overlay')).count()
n_packages_outdated = n_packages - n_packages_uptodate_all
n_packages_uptodate_ovl = n_packages_uptodate_all - n_packages_uptodate_main
pylab.figure(1, figsize=(3.5,3.5))
if n_packages_uptodate_ovl:
labels = 'Ok (gentoo)', 'Ok (overlays)', 'Outdated'
fracs = [n_packages_uptodate_main, n_packages_uptodate_ovl, n_packages_outdated]
colors = '#008000', '#0B17FD', '#FF0000'
else:
labels = 'Ok (gentoo)', 'Outdated'
fracs = [n_packages_uptodate_main, n_packages_outdated]
colors = '#008000', '#FF0000'
pylab.pie(fracs, labels=labels, colors=colors, autopct='%1.1f%%', shadow=True)
pylab.title('Packages', bbox={'facecolor':'0.8', 'pad':5})
def rrd_path(name):
return str(os.path.join(settings.RRD_ROOT, name + '.rrd'))
def rrd_create(name, start):
path = rrd_path(name)
if os.path.exists(path):
return
rrdtool.create(path, '--step', '86400',
'--start', '%s' % int(start - 10),
'DS:n_packages_gentoo:GAUGE:4294967295:0:U',
'DS:n_packages_overlay:GAUGE:4294967295:0:U',
'DS:n_packages_outdated:GAUGE:4294967295:0:U',
'DS:n_versions_gentoo:GAUGE:4294967295:0:U',
'DS:n_versions_overlay:GAUGE:4294967295:0:U',
'DS:n_versions_upstream:GAUGE:4294967295:0:U',
'RRA:AVERAGE:0.5:1:100',
'RRA:AVERAGE:0.5:5:200',
'RRA:AVERAGE:0.5:10:200')
def rrd_update(name, datetime, values):
now = time.mktime(datetime.timetuple())
rrd_create(name, now)
rrdtool.update(rrd_path(name),
'%d:%d:%d:%d:%d:%d:%d' % \
(now, values.n_packages_gentoo, values.n_packages_overlay, values.n_packages_outdated, \
values.n_versions_gentoo, values.n_versions_overlay, values.n_versions_upstream))
"""
[-s|--start time] [-e|--end time] [-S|--step seconds]
[-t|--title string] [-v|--vertical-label string]
[-w|--width pixels] [-h|--height pixels] [-j|--only-graph] [-D|--full-size-mode][-u|--upper-limit value] [-l|--lower-limit value]
[-u|--upper-limit value] [-l|--lower-limit value] [-r|--rigid]
[-A|--alt-autoscale]
[-M|--alt-autoscale-max]
[-J|--alt-autoscale-min]
"""
def cached_rrd_chart(f):
def new_f(*args, **kwds):
if 'period' not in kwds:
kwds['period'] = '-yearly'
name = chart_name(f.func_name, **kwds)
path = os.path.join(CHARTS_ROOT, name)
if not chart_alive(name):
kwds['title'] = '%s (%s)' % (f.func_name, kwds['period'])
kwds['steps'] = kwds['period']
kwds['vertical-label'] = f.func_name
kwds['rrd'] = rrd_path(rrd_name(**kwds))
kwds['path'] = path
kwds['end'] = 'now'
if kwds['period'] == '-weekly':
kwds['start'] = 'now-4weeks'
elif kwds['period'] == '-monthly':
kwds['start'] = 'now-12months'
else:
kwds['start'] = 'now-4years'
if '-small' in kwds and kwds['-small']:
kwds['width'] = '100'
kwds['height'] = '30'
kwds['graph-mode'] = '--only-graph'
else:
kwds['width'] = '500'
kwds['height'] = '170'
kwds['graph-mode'] = '--full-size-mode'
f(*args, **kwds)
return name
new_f.func_name = f.func_name
return new_f
@cached_rrd_chart
def packages(**kwargs):
rrdtool.graph(str(kwargs['path']),
'--imgformat', 'PNG',
'--width', kwargs['width'],
'--height', kwargs['height'],
kwargs['graph-mode'],
'--color', 'CANVAS#FFFFFF00',
'--color', 'BACK#FFFFFF00',
'--start', kwargs['start'],
'--end', kwargs['end'],
'--vertical-label', kwargs['vertical-label'],
'--title', kwargs['title'],
'--lower-limit', '0',
'DEF:n_packages_gentoo=%s:n_packages_gentoo:AVERAGE' % (kwargs['rrd']),
'DEF:n_packages_overlay=%s:n_packages_overlay:AVERAGE' % (kwargs['rrd']),
'DEF:n_packages_outdated=%s:n_packages_outdated:AVERAGE' % (kwargs['rrd']),
'LINE1.25:n_packages_gentoo#008000:Gentoo',
'LINE1.25:n_packages_overlay#0B17FD:Overlay',
'LINE1.25:n_packages_outdated#FF0000:Outdated')
@cached_rrd_chart
def versions(**kwargs):
rrdtool.graph(str(kwargs['path']),
'--imgformat', 'PNG',
'--width', kwargs['width'],
'--height', kwargs['height'],
kwargs['graph-mode'],
'--color', 'CANVAS#FFFFFF00',
'--color', 'BACK#FFFFFF00',
'--start', kwargs['start'],
'--end', kwargs['end'],
'--vertical-label', kwargs['vertical-label'],
'--title', kwargs['title'],
'--lower-limit', '0',
'DEF:n_versions_gentoo=%s:n_versions_gentoo:AVERAGE' % (kwargs['rrd']),
'DEF:n_versions_overlay=%s:n_versions_overlay:AVERAGE' % (kwargs['rrd']),
'DEF:n_versions_outdated=%s:n_versions_upstream:AVERAGE' % (kwargs['rrd']),
'LINE1.25:n_versions_gentoo#008000:Gentoo',
'LINE1.25:n_versions_overlay#0B17FD:Overlay',
'LINE1.25:n_versions_outdated#FF0000:Outdated')

View File

@ -1,147 +0,0 @@
from django.contrib.syndication.views import Feed, FeedDoesNotExist
from django.shortcuts import get_object_or_404
from django.http import Http404
from django.utils.feedgenerator import Atom1Feed
from django.core.urlresolvers import reverse
from euscan.models import Version, Package, Herd, Maintainer, VersionLog
from euscan.views import *
class BaseFeed(Feed):
feed_type = Atom1Feed
author_name = 'euscan'
item_author_name = author_name
ttl = 3600
def item_title(self, vlog):
return str(vlog)
def item_description(self, vlog):
if vlog.overlay:
txt = 'Version %s-%s [%s] of package %s ' % (vlog.version, vlog.revision,
vlog.slot, vlog.package)
else:
txt = 'Version %s of package %s ' % (vlog.version, vlog.package)
if vlog.action == vlog.VERSION_REMOVED:
if not vlog.overlay:
txt += 'has been removed upstream'
else:
txt += 'has been removed from overlay "%s"' % vlog.overlay
if vlog.action == vlog.VERSION_ADDED:
if not vlog.overlay:
txt += 'has been added upstream'
else:
txt += 'has been added to overlay "%s"' % vlog.overlay
return txt
def item_link(self, vlog):
kwargs = {'category' : vlog.package.category, 'package' : vlog.package.name }
return reverse('euscan.views.package', kwargs=kwargs) + '#' + vlog.tag()
def item_pubdate(self, vlog):
return vlog.datetime
def item_categories(self, vlog):
return [vlog.package.category]
class GlobalFeed(BaseFeed):
title = "euscan"
link = "/"
description = "Last euscan changes"
def categories(self):
categories = Package.objects.values('category').distinct();
return [ category['category'] for category in categories ]
def items(self):
return VersionLog.objects.order_by('-id')[:250]
class PackageFeed(BaseFeed):
feed_type = Atom1Feed
def get_object(self, request, category, package):
return get_object_or_404(Package, category=category, name=package)
def title(self, package):
return "%s" % package
def description(self, package):
return "Last changes for %s" % package
def link(self, package):
return reverse('euscan.views.package', args=[package.category, package.name])
def description(self, package):
return package.description
def items(self, package):
return VersionLog.objects.filter(package=package).order_by('-id')[:30]
def item_description(self, vlog):
return ''
class MaintainerFeed(BaseFeed):
feed_type = Atom1Feed
def get_object(self, request, maintainer_id):
return get_object_or_404(Maintainer, id=maintainer_id)
def title(self, maintainer):
return "%s" % maintainer
def description(self, maintainer):
return "Last changes for %s" % maintainer
def link(self, maintainer):
return reverse('euscan.views.maintainer', kwargs={'maintainer_id' : maintainer.id})
def description(self, maintainer):
return str(maintainer)
def items(self, maintainer):
q = VersionLog.objects.filter(package__maintainers__id=maintainer.id)
return q.order_by('-id')[:50]
class HerdFeed(BaseFeed):
feed_type = Atom1Feed
def get_object(self, request, herd):
return get_object_or_404(Herd, herd=herd)
def title(self, herd):
return "%s" % herd
def description(self, herd):
return "Last changes for %s" % herd
def link(self, herd):
return reverse('euscan.views.herd', kwargs={'herd' : herd.herd})
def description(self, herd):
return str(herd)
def items(self, herd):
q = VersionLog.objects.filter(package__herds__id=herd.id)
return q.order_by('-id')[:100]
class CategoryFeed(BaseFeed):
feed_type = Atom1Feed
def get_object(self, request, category):
if not Package.objects.filter(category=category).count():
raise FeedDoesNotExist
return category
def title(self, category):
return "%s" % category
def description(self, category):
return "Last changes for %s" % category
def link(self, category):
return reverse('euscan.views.category', args=[category])
def items(self, category):
q = VersionLog.objects.filter(package__category=category)
return q.order_by('-id')[:100]

View File

@ -1,7 +0,0 @@
from django import forms
class WorldForm(forms.Form):
world = forms.FileField()
class PackagesForm(forms.Form):
packages = forms.CharField(widget=forms.Textarea)

View File

@ -1,55 +0,0 @@
from optparse import make_option
from django.core.management.base import BaseCommand, CommandError
from euscanwww.euscan.models import Package
class Command(BaseCommand):
_overlays = {}
help = 'List packages'
option_list = BaseCommand.option_list + (
make_option('--after',
action='store',
dest='after',
default=False,
help='After package'),
make_option('--before',
action='store',
dest='before',
default=False,
help='Before package'),
make_option('--limit',
action='store',
dest='limit',
default=False,
help='limit'),
)
def handle(self, *args, **options):
after = None
before = None
if options['after']:
category, name = options['after'].split('/')
after = Package.objects.get(category=category, name=name)
if options['before']:
category, name = options['before'].split('/')
before = Package.objects.get(category=category, name=name)
packages = Package.objects
if after or before:
if after:
packages = packages.filter(id__gte=after.id)
if before:
packages = packages.filter(id__lte=before.id)
else:
packages = packages.all()
if options['limit']:
packages = packages[:int(options['limit'])]
for pkg in packages:
self.stdout.write('%s/%s\n' % (pkg.category, pkg.name))
self.stdout.close()

View File

@ -1,24 +0,0 @@
import datetime
from optparse import make_option
from django.core.management.base import BaseCommand, CommandError
from euscanwww.euscan.models import HerdLog, MaintainerLog, CategoryLog, WorldLog
from euscanwww.euscan import charts
class Command(BaseCommand):
_overlays = {}
help = 'Regenerate rrd database'
def handle(self, *args, **options):
for wlog in WorldLog.objects.all():
charts.rrd_update('world', wlog.datetime, wlog)
for clog in CategoryLog.objects.all():
charts.rrd_update('category-%s' % clog.category, clog.datetime, clog)
for hlog in HerdLog.objects.all():
charts.rrd_update('herd-%d' % hlog.herd.id, hlog.datetime, hlog)
for mlog in MaintainerLog.objects.all():
charts.rrd_update('maintainer-%d' % mlog.maintainer.id, mlog.datetime, mlog)

View File

@ -1,116 +0,0 @@
import subprocess
import portage
import sys
import os
import re
from portage import versions
from optparse import make_option
from django.db.transaction import commit_on_success
from django.core.management.base import BaseCommand, CommandError
from euscanwww.euscan.models import Package, Herd, Maintainer
from gentoolkit.query import Query
from gentoolkit.errors import GentoolkitFatalError
class Command(BaseCommand):
_overlays = {}
option_list = BaseCommand.option_list + (
make_option('--all',
action='store_true',
dest='all',
default=False,
help='Scan all packages'),
make_option('--quiet',
action='store_true',
dest='quiet',
default=False,
help='Be quiet'),
)
args = '<package package ...>'
help = 'Scans metadata and fills database'
def handle(self, *args, **options):
if len(args) == 0 and options['all'] == False:
raise CommandError('You must specify a package or use --all')
if len(args) == 0:
for pkg in Package.objects.all():
self.scan(options, '%s/%s' % (pkg.category, pkg.name))
else:
for package in args:
self.scan(options, package)
@commit_on_success
def scan(self, options, query=None):
matches = Query(query).find(
include_masked=True,
in_installed=False,
)
if not matches:
sys.stderr.write(self.style.ERROR("Unknown package '%s'\n" % query))
return
matches = sorted(matches)
pkg = matches.pop()
if '9999' in pkg.version and len(matches):
pkg = matches.pop()
obj, created = Package.objects.get_or_create(category=pkg.category, name=pkg.name)
try:
obj.homepage = pkg.environment("HOMEPAGE")
obj.description = pkg.environment("DESCRIPTION")
except GentoolkitFatalError, err:
sys.stderr.write(self.style.ERROR("Gentoolkit fatal error: '%s'\n" % str(err)))
if created and not options['quiet']:
sys.stdout.write('+ [p] %s/%s\n' % (pkg.category, pkg.name))
if pkg.metadata:
obj.herds.clear()
obj.maintainers.clear()
for herd in pkg.metadata.herds(True):
herd = self.store_herd(options, herd[0], herd[1])
obj.herds.add(herd)
for maintainer in pkg.metadata.maintainers():
maintainer = self.store_maintainer(options, maintainer.name, maintainer.email)
obj.maintainers.add(maintainer)
obj.save()
def store_herd(self, options, name, email):
if not name:
name = '{nil}'
name = name.strip("\r").strip("\n").strip("\t").strip()
herd, created = Herd.objects.get_or_create(herd=name)
if created and not options['quiet']:
sys.stdout.write('+ [h] %s <%s>\n' % (name, email))
herd.email = email
herd.save()
return herd
def store_maintainer(self, options, name, email):
if not name:
name = email
if not name:
name = '{nil}'
maintainer, created = Maintainer.objects.get_or_create(email=email)
if created:
if not options['quiet']:
sys.stdout.write('+ [m] %s <%s>\n' % (name.encode('utf-8'), email))
maintainer.name = name
maintainer.save()
return maintainer

View File

@ -1,218 +0,0 @@
import subprocess
import portage
import sys
import os
import re
from portage import versions
from optparse import make_option
from django.db.transaction import commit_on_success
from django.core.management.base import BaseCommand, CommandError
from euscanwww.euscan.models import Package, Version, VersionLog
class Command(BaseCommand):
_overlays = {}
option_list = BaseCommand.option_list + (
make_option('--all',
action='store_true',
dest='all',
default=False,
help='Scan all packages'),
make_option('--purge-packages',
action='store_true',
dest='purge-packages',
default=False,
help='Purge old packages'),
make_option('--purge-versions',
action='store_true',
dest='purge-versions',
default=False,
help='Purge old versions'),
make_option('--quiet',
action='store_true',
dest='quiet',
default=False,
help='Be quiet'),
)
args = '<package package ...>'
help = 'Scans portage tree and fills database'
def handle(self, *args, **options):
if len(args) == 0 and options['all'] == False:
raise CommandError('You must specify a package or use --all')
if not options['quiet']:
self.stdout.write('Scanning portage tree...\n')
if len(args) == 0:
self.scan(options)
else:
for package in args:
self.scan(options, package)
if options['purge-versions']:
self.purge_versions(options)
if not options['quiet']:
self.stdout.write('Done.\n')
def overlays(self):
if self._overlays:
return self._overlays
env = os.environ
env['OVERLAYS_LIST'] = 'all'
env['PRINT_COUNT_ALWAYS'] = 'never'
cmd = ['eix', '-!']
output = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=env).communicate()[0]
output = output.strip().strip('\n').split('\n')
overlay_re = re.compile(r'^\[(?P<key>\d+)] "(?P<name>.*?)"')
self._overlays = {}
for line in output:
match = overlay_re.match(line)
if not match:
continue
self._overlays[match.group('key')] = match.group('name')
return self._overlays
@commit_on_success
def scan(self, options, query=None):
env = os.environ
env['MY'] = "<category>/<name>-<version>:<slot> [<overlaynum>]\n"
cmd = ['eix', '--format', '<availableversions:MY>', '--pure-packages', '-x']
if query:
cmd.extend(['--exact', query])
output = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=env).communicate()[0]
output = output.strip().strip('\n')
if len(output) == 0:
if not query:
return
if options['purge-packages']:
if not options['quiet']:
sys.stdout.write('- [p] %s\n' % (query))
if '/' in query:
cat, pkg = portage.catsplit(query)
Package.objects.filter(category=cat, name=pkg).delete()
else:
Package.objects.filter(name=query).delete()
else:
sys.stderr.write(self.style.ERROR("Unknown package '%s'\n" % query))
return
output = output.split('\n')
packages = {}
line_re = re.compile(r'^(?P<cpv>.*?):(?P<slot>.*?) \[(?P<overlay>.*?)\]$')
package = None
for line in output:
match = line_re.match(line)
if not match:
continue
cpv = match.group('cpv')
slot = match.group('slot')
overlay = match.group('overlay')
cat, pkg, ver, rev = portage.catpkgsplit(cpv)
packages['%s/%s' % (cat, pkg)] = True
if not package or not (cat == package.category and pkg == package.name):
package = self.store_package(options, cat, pkg)
self.store_version(options, package, cpv, slot, overlay)
if options['purge-packages'] and not query:
for package in Package.objects.all():
cp = "%s/%s" % (package.category, package.name)
if cp not in packages:
if not options['quiet']:
sys.stdout.write('- [p] %s\n' % (package))
package.delete()
def store_package(self, options, cat, pkg):
obj, created = Package.objects.get_or_create(category=cat, name=pkg)
if created:
if not options['quiet']:
sys.stdout.write('+ [p] %s/%s\n' % (cat, pkg))
' Set all versions dead, then set found versions alive and delete old versions '
Version.objects.filter(package=obj, packaged=True).update(alive=False)
return obj
def store_version(self, options, package, cpv, slot, overlay):
cat, pkg, ver, rev = portage.catpkgsplit(cpv)
overlays = self.overlays()
if overlay in overlays:
overlay = overlays[overlay]
else:
overlay = 'gentoo'
obj, created = Version.objects.get_or_create(package=package, slot=slot,
revision=rev, version=ver,
overlay=overlay)
obj.alive = True
obj.packaged = True
obj.save()
''' nothing to do (note: it can't be an upstream version because overlay can't be empty here) '''
if not created:
return
if not options['quiet']:
sys.stdout.write('+ [v] %s \n' % (obj))
if overlay == 'gentoo':
package.n_packaged += 1
else:
package.n_overlay += 1
package.n_versions += 1
package.save()
entry = VersionLog.objects.create(package=obj.package, action=VersionLog.VERSION_ADDED)
entry.slot = obj.slot
entry.revision = obj.revision
entry.version = obj.version
entry.overlay = obj.overlay
entry.save()
@commit_on_success
def purge_versions(self, options):
' For each dead versions '
for version in Version.objects.filter(packaged=True, alive=False):
entry = VersionLog.objects.create(package=version.package, action=VersionLog.VERSION_REMOVED)
entry.slot = version.slot
entry.revision = version.revision
entry.version = version.version
entry.overlay = version.overlay
entry.save()
if version.overlay == 'gentoo':
version.package.n_packaged -= 1
else:
version.package.n_overlay -= 1
version.package.n_versions -= 1
version.package.save()
if not options['quiet']:
sys.stdout.write('- [v] %s\n' % (version))
Version.objects.filter(packaged=True, alive=False).delete()

View File

@ -1,186 +0,0 @@
import subprocess
import portage
import sys
import os
import re
from StringIO import StringIO
from datetime import datetime
from portage import versions
from optparse import make_option
from django.db.transaction import commit_on_success
from django.core.management.base import BaseCommand, CommandError
from euscanwww.euscan.models import Package, Version, EuscanResult, VersionLog
class Command(BaseCommand):
_overlays = {}
option_list = BaseCommand.option_list + (
make_option('--all',
action='store_true',
dest='all',
default=False,
help='Scan all packages'),
make_option('--feed',
action='store_true',
dest='feed',
default=False,
help='Read euscan output from stdin'),
make_option('--purge-versions',
action='store_true',
dest='purge-versions',
default=False,
help='Purge old versions'),
make_option('--quiet',
action='store_true',
dest='quiet',
default=False,
help='Be quiet'),
)
args = '<package package ...>'
help = 'Scans metadata and fills database'
def handle(self, *args, **options):
if len(args) == 0 and options['all'] == False and options['feed'] == False:
raise CommandError('You must specify a package or use --all')
if options['feed']:
self.parse_output(options, sys.stdin)
if options['purge-versions']:
self.purge_versions(options)
return
if not options['quiet']:
self.stdout.write('Scanning upstream...\n')
packages = []
if len(args) == 0:
for pkg in Package.objects.all():
packages.append('%s/%s' % (pkg.category, pkg.name))
else:
packages = list(args)
self.scan(options, packages)
if options['purge-versions']:
self.purge_versions(options)
if not options['quiet']:
self.stdout.write('Done.\n')
def scan(self, options, packages=None):
for package in packages:
cmd = ['euscan', package]
fp = subprocess.Popen(cmd, stdout=subprocess.PIPE)
output = StringIO(fp.communicate()[0])
self.parse_output(options, output)
@commit_on_success
def parse_output(self, options, output):
from portage.versions import _cp
package_re = re.compile(r'^ \* (?P<cpv>' + _cp + ') \[(?P<overlay>.*?)\]$')
version_re = re.compile(r'^Upstream Version: (?P<ver>.*?) (?P<url>.*?)$')
package = None
log = ""
while True:
line = output.readline()
if line == '':
break
match = package_re.match(line)
if match:
if package:
self.store_result(options, package, log)
cpv = match.group('cpv')
package = self.store_package(options, cpv)
log = line
continue
log += line
match = version_re.match(line)
if match:
ver = match.group('ver')
url = match.group('url')
self.store_version(options, package, ver, url)
if package:
self.store_result(options, package, log)
def store_result(self, options, package, log):
# Remove previous logs
EuscanResult.objects.filter(package=package).delete()
obj = EuscanResult()
obj.package = package
obj.result = log
obj.datetime = datetime.now()
obj.save()
def store_package(self, options, cpv):
cat, pkg, ver, rev = portage.catpkgsplit(cpv)
obj, created = Package.objects.get_or_create(category=cat, name=pkg)
if created and not options['quiet']:
sys.stdout.write('+ [p] %s/%s\n' % (cat, pkg))
' Set all versions dead, then set found versions alive and delete old versions '
Version.objects.filter(package=obj, packaged=False).update(alive=False)
return obj
def store_version(self, options, package, ver, url):
obj, created = Version.objects.get_or_create(package=package, slot='',
revision='r0', version=ver,
overlay='')
obj.alive = True
obj.urls = url
obj.packaged = False
obj.save()
''' If it's not a new version, just update the object and continue '''
if not created:
return
if not options['quiet']:
sys.stdout.write('+ [u] %s %s\n' % (obj, url))
entry = VersionLog.objects.create(package=package, action=VersionLog.VERSION_ADDED)
entry.slot = ''
entry.revision = 'r0'
entry.version = ver
entry.overlay = ''
entry.save()
package.n_versions += 1
package.save()
@commit_on_success
def purge_versions(self, options):
' For each dead versions '
for version in Version.objects.filter(packaged=False, alive=False):
entry = VersionLog.objects.create(package=version.package, action=VersionLog.VERSION_REMOVED)
entry.slot = version.slot
entry.revision = version.revision
entry.version = version.version
entry.overlay = version.overlay
entry.save()
version.package.n_versions -= 1
version.package.save()
if not options['quiet']:
sys.stdout.write('- [u] %s %s\n' % (version, version.urls))
Version.objects.filter(packaged=False, alive=False).delete()

View File

@ -1,123 +0,0 @@
import datetime
from optparse import make_option
from django.db.models import Count, Sum
from django.db.transaction import commit_on_success
from django.core.management.base import BaseCommand, CommandError
from euscanwww.euscan.models import Package, Herd, Maintainer, Version
from euscanwww.euscan.models import HerdLog, MaintainerLog, CategoryLog, WorldLog
from euscanwww.euscan import charts
class Command(BaseCommand):
_overlays = {}
help = 'Update counters'
option_list = BaseCommand.option_list + (
make_option('--quiet',
action='store_true',
dest='quiet',
default=False,
help='Be quiet'),
)
@commit_on_success
def handle(self, *args, **options):
now = datetime.datetime.now()
categories = {}
herds = {}
maintainers = {}
'''
Could be done using raw SQL queries, but I don't have time for that
right now ...
'''
wlog = WorldLog()
wlog.datetime = now
for cat in Package.objects.values('category').distinct():
clog = CategoryLog()
clog.datetime = now
clog.category = cat['category']
categories[clog.category] = clog
for herd in Herd.objects.all():
hlog = HerdLog()
hlog.datetime = now
hlog.herd = herd
herds[herd] = hlog
for maintainer in Maintainer.objects.all():
mlog = MaintainerLog()
mlog.datetime = now
mlog.maintainer = maintainer
maintainers[maintainer] = mlog
for package in Package.objects.all():
# Should not be needed, but can't hurt
package.n_versions = Version.objects.filter(package=package).count()
package.n_packaged = Version.objects.filter(package=package, packaged=True, overlay='gentoo').count()
package.n_overlay = Version.objects.filter(package=package, packaged=True).exclude(overlay='gentoo').count()
package.save()
n_packages_gentoo = int(package.n_packaged == package.n_versions)
n_packages_overlay = int(package.n_overlay and package.n_packaged + package.n_overlay == package.n_versions)
n_packages_outdated = int(package.n_packaged + package.n_overlay < package.n_versions)
for herd in package.herds.all():
herds[herd].n_packages_gentoo += n_packages_gentoo
herds[herd].n_packages_overlay += n_packages_overlay
herds[herd].n_packages_outdated += n_packages_outdated
herds[herd].n_versions_gentoo += package.n_packaged
herds[herd].n_versions_overlay += package.n_overlay
herds[herd].n_versions_upstream += package.n_versions - package.n_packaged - package.n_overlay
for maintainer in package.maintainers.all():
maintainers[maintainer].n_packages_gentoo += n_packages_gentoo
maintainers[maintainer].n_packages_overlay += n_packages_overlay
maintainers[maintainer].n_packages_outdated += n_packages_outdated
maintainers[maintainer].n_versions_gentoo += package.n_packaged
maintainers[maintainer].n_versions_overlay += package.n_overlay
maintainers[maintainer].n_versions_upstream += package.n_versions - package.n_packaged - package.n_overlay
categories[package.category].n_packages_gentoo += n_packages_gentoo
categories[package.category].n_packages_overlay += n_packages_overlay
categories[package.category].n_packages_outdated += n_packages_outdated
categories[package.category].n_versions_gentoo += package.n_packaged
categories[package.category].n_versions_overlay += package.n_overlay
categories[package.category].n_versions_upstream += package.n_versions - package.n_packaged - package.n_overlay
wlog.n_packages_gentoo += n_packages_gentoo
wlog.n_packages_overlay += n_packages_overlay
wlog.n_packages_outdated += n_packages_outdated
wlog.n_versions_gentoo += package.n_packaged
wlog.n_versions_overlay += package.n_overlay
wlog.n_versions_upstream += package.n_versions - package.n_packaged - package.n_overlay
for clog in categories.values():
if not options['quiet']:
self.stdout.write('+ [cl] %s\n' % clog)
charts.rrd_update('category-%s' % clog.category, now, clog)
clog.save()
for hlog in herds.values():
if not options['quiet']:
self.stdout.write('+ [hl] %s\n' % hlog)
charts.rrd_update('herd-%d' % hlog.herd.id, now, hlog)
hlog.save()
for mlog in maintainers.values():
if not options['quiet']:
self.stdout.write('+ [ml] %s\n' % mlog)
charts.rrd_update('maintainer-%d' % mlog.maintainer.id, now, mlog)
mlog.save()
wlog.save()
charts.rrd_update('world', now, wlog)

View File

@ -1,234 +0,0 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'Herd'
db.create_table('euscan_herd', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('herd', self.gf('django.db.models.fields.CharField')(unique=True, max_length=128)),
('email', self.gf('django.db.models.fields.CharField')(max_length=128, null=True, blank=True)),
))
db.send_create_signal('euscan', ['Herd'])
# Adding model 'Maintainer'
db.create_table('euscan_maintainer', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('name', self.gf('django.db.models.fields.CharField')(max_length=128)),
('email', self.gf('django.db.models.fields.CharField')(max_length=128)),
))
db.send_create_signal('euscan', ['Maintainer'])
# Adding unique constraint on 'Maintainer', fields ['name', 'email']
db.create_unique('euscan_maintainer', ['name', 'email'])
# Adding model 'Package'
db.create_table('euscan_package', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('category', self.gf('django.db.models.fields.CharField')(max_length=128)),
('name', self.gf('django.db.models.fields.CharField')(max_length=128)),
('description', self.gf('django.db.models.fields.TextField')(blank=True)),
('homepage', self.gf('django.db.models.fields.CharField')(max_length=256, blank=True)),
('n_versions', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_packaged', self.gf('django.db.models.fields.IntegerField')(default=0)),
))
db.send_create_signal('euscan', ['Package'])
# Adding unique constraint on 'Package', fields ['category', 'name']
db.create_unique('euscan_package', ['category', 'name'])
# Adding M2M table for field herds on 'Package'
db.create_table('euscan_package_herds', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('package', models.ForeignKey(orm['euscan.package'], null=False)),
('herd', models.ForeignKey(orm['euscan.herd'], null=False))
))
db.create_unique('euscan_package_herds', ['package_id', 'herd_id'])
# Adding M2M table for field maintainers on 'Package'
db.create_table('euscan_package_maintainers', (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('package', models.ForeignKey(orm['euscan.package'], null=False)),
('maintainer', models.ForeignKey(orm['euscan.maintainer'], null=False))
))
db.create_unique('euscan_package_maintainers', ['package_id', 'maintainer_id'])
# Adding model 'Version'
db.create_table('euscan_version', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('package', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['euscan.Package'])),
('slot', self.gf('django.db.models.fields.CharField')(max_length=128)),
('revision', self.gf('django.db.models.fields.CharField')(max_length=128)),
('version', self.gf('django.db.models.fields.CharField')(max_length=128)),
('packaged', self.gf('django.db.models.fields.BooleanField')(default=False)),
('overlay', self.gf('django.db.models.fields.CharField')(max_length=128)),
('urls', self.gf('django.db.models.fields.TextField')(blank=True)),
))
db.send_create_signal('euscan', ['Version'])
# Adding unique constraint on 'Version', fields ['package', 'slot', 'revision', 'version', 'overlay']
db.create_unique('euscan_version', ['package_id', 'slot', 'revision', 'version', 'overlay'])
# Adding model 'EuscanResult'
db.create_table('euscan_euscanresult', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('package', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['euscan.Package'])),
('datetime', self.gf('django.db.models.fields.DateTimeField')()),
('result', self.gf('django.db.models.fields.TextField')(blank=True)),
))
db.send_create_signal('euscan', ['EuscanResult'])
# Adding model 'CategoryLog'
db.create_table('euscan_categorylog', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('category', self.gf('django.db.models.fields.CharField')(max_length=128)),
('datetime', self.gf('django.db.models.fields.DateTimeField')()),
('n_packages', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_versions', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_packaged', self.gf('django.db.models.fields.IntegerField')(default=0)),
))
db.send_create_signal('euscan', ['CategoryLog'])
# Adding model 'HerdLog'
db.create_table('euscan_herdlog', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('herd', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['euscan.Herd'])),
('datetime', self.gf('django.db.models.fields.DateTimeField')()),
('n_packages', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_versions', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_packaged', self.gf('django.db.models.fields.IntegerField')(default=0)),
))
db.send_create_signal('euscan', ['HerdLog'])
# Adding model 'MaintainerLog'
db.create_table('euscan_maintainerlog', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('maintainer', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['euscan.Maintainer'])),
('datetime', self.gf('django.db.models.fields.DateTimeField')()),
('n_packages', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_versions', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_packaged', self.gf('django.db.models.fields.IntegerField')(default=0)),
))
db.send_create_signal('euscan', ['MaintainerLog'])
def backwards(self, orm):
# Removing unique constraint on 'Version', fields ['package', 'slot', 'revision', 'version', 'overlay']
db.delete_unique('euscan_version', ['package_id', 'slot', 'revision', 'version', 'overlay'])
# Removing unique constraint on 'Package', fields ['category', 'name']
db.delete_unique('euscan_package', ['category', 'name'])
# Removing unique constraint on 'Maintainer', fields ['name', 'email']
db.delete_unique('euscan_maintainer', ['name', 'email'])
# Deleting model 'Herd'
db.delete_table('euscan_herd')
# Deleting model 'Maintainer'
db.delete_table('euscan_maintainer')
# Deleting model 'Package'
db.delete_table('euscan_package')
# Removing M2M table for field herds on 'Package'
db.delete_table('euscan_package_herds')
# Removing M2M table for field maintainers on 'Package'
db.delete_table('euscan_package_maintainers')
# Deleting model 'Version'
db.delete_table('euscan_version')
# Deleting model 'EuscanResult'
db.delete_table('euscan_euscanresult')
# Deleting model 'CategoryLog'
db.delete_table('euscan_categorylog')
# Deleting model 'HerdLog'
db.delete_table('euscan_herdlog')
# Deleting model 'MaintainerLog'
db.delete_table('euscan_maintainerlog')
models = {
'euscan.categorylog': {
'Meta': {'object_name': 'CategoryLog'},
'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'euscan.euscanresult': {
'Meta': {'object_name': 'EuscanResult'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
'result': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
'euscan.herd': {
'Meta': {'object_name': 'Herd'},
'email': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
'herd': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'euscan.herdlog': {
'Meta': {'object_name': 'HerdLog'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'herd': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Herd']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'euscan.maintainer': {
'Meta': {'unique_together': "(['name', 'email'],)", 'object_name': 'Maintainer'},
'email': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.maintainerlog': {
'Meta': {'object_name': 'MaintainerLog'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'maintainer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Maintainer']"}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'euscan.package': {
'Meta': {'unique_together': "(['category', 'name'],)", 'object_name': 'Package'},
'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'herds': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['euscan.Herd']", 'symmetrical': 'False', 'blank': 'True'}),
'homepage': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'maintainers': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['euscan.Maintainer']", 'symmetrical': 'False', 'blank': 'True'}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.version': {
'Meta': {'unique_together': "(['package', 'slot', 'revision', 'version', 'overlay'],)", 'object_name': 'Version'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'overlay': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
'packaged': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'slot': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'urls': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'version': ('django.db.models.fields.CharField', [], {'max_length': '128'})
}
}
complete_apps = ['euscan']

View File

@ -1,99 +0,0 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Removing unique constraint on 'Maintainer', fields ['name', 'email']
db.delete_unique('euscan_maintainer', ['name', 'email'])
# Adding unique constraint on 'Maintainer', fields ['email']
db.create_unique('euscan_maintainer', ['email'])
def backwards(self, orm):
# Removing unique constraint on 'Maintainer', fields ['email']
db.delete_unique('euscan_maintainer', ['email'])
# Adding unique constraint on 'Maintainer', fields ['name', 'email']
db.create_unique('euscan_maintainer', ['name', 'email'])
models = {
'euscan.categorylog': {
'Meta': {'object_name': 'CategoryLog'},
'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'euscan.euscanresult': {
'Meta': {'object_name': 'EuscanResult'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
'result': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
'euscan.herd': {
'Meta': {'object_name': 'Herd'},
'email': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
'herd': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'euscan.herdlog': {
'Meta': {'object_name': 'HerdLog'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'herd': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Herd']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'euscan.maintainer': {
'Meta': {'object_name': 'Maintainer'},
'email': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.maintainerlog': {
'Meta': {'object_name': 'MaintainerLog'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'maintainer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Maintainer']"}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'euscan.package': {
'Meta': {'unique_together': "(['category', 'name'],)", 'object_name': 'Package'},
'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'herds': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['euscan.Herd']", 'symmetrical': 'False', 'blank': 'True'}),
'homepage': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'maintainers': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['euscan.Maintainer']", 'symmetrical': 'False', 'blank': 'True'}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.version': {
'Meta': {'unique_together': "(['package', 'slot', 'revision', 'version', 'overlay'],)", 'object_name': 'Version'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'overlay': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
'packaged': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'slot': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'urls': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'version': ('django.db.models.fields.CharField', [], {'max_length': '128'})
}
}
complete_apps = ['euscan']

View File

@ -1,115 +0,0 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'CategoryLog.n_overlay'
db.add_column('euscan_categorylog', 'n_overlay', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'Package.n_overlay'
db.add_column('euscan_package', 'n_overlay', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'HerdLog.n_overlay'
db.add_column('euscan_herdlog', 'n_overlay', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'MaintainerLog.n_overlay'
db.add_column('euscan_maintainerlog', 'n_overlay', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
def backwards(self, orm):
# Deleting field 'CategoryLog.n_overlay'
db.delete_column('euscan_categorylog', 'n_overlay')
# Deleting field 'Package.n_overlay'
db.delete_column('euscan_package', 'n_overlay')
# Deleting field 'HerdLog.n_overlay'
db.delete_column('euscan_herdlog', 'n_overlay')
# Deleting field 'MaintainerLog.n_overlay'
db.delete_column('euscan_maintainerlog', 'n_overlay')
models = {
'euscan.categorylog': {
'Meta': {'object_name': 'CategoryLog'},
'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'n_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'euscan.euscanresult': {
'Meta': {'object_name': 'EuscanResult'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
'result': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
'euscan.herd': {
'Meta': {'object_name': 'Herd'},
'email': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
'herd': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'euscan.herdlog': {
'Meta': {'object_name': 'HerdLog'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'herd': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Herd']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'n_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'euscan.maintainer': {
'Meta': {'object_name': 'Maintainer'},
'email': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.maintainerlog': {
'Meta': {'object_name': 'MaintainerLog'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'maintainer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Maintainer']"}),
'n_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'euscan.package': {
'Meta': {'unique_together': "(['category', 'name'],)", 'object_name': 'Package'},
'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'herds': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['euscan.Herd']", 'symmetrical': 'False', 'blank': 'True'}),
'homepage': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'maintainers': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['euscan.Maintainer']", 'symmetrical': 'False', 'blank': 'True'}),
'n_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.version': {
'Meta': {'unique_together': "(['package', 'slot', 'revision', 'version', 'overlay'],)", 'object_name': 'Version'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'overlay': ('django.db.models.fields.CharField', [], {'default': "'gentoo'", 'max_length': '128'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
'packaged': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'slot': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'urls': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'version': ('django.db.models.fields.CharField', [], {'max_length': '128'})
}
}
complete_apps = ['euscan']

View File

@ -1,277 +0,0 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Deleting field 'CategoryLog.n_versions'
db.delete_column('euscan_categorylog', 'n_versions')
# Deleting field 'CategoryLog.n_packaged'
db.delete_column('euscan_categorylog', 'n_packaged')
# Deleting field 'CategoryLog.n_packages'
db.delete_column('euscan_categorylog', 'n_packages')
# Deleting field 'CategoryLog.n_overlay'
db.delete_column('euscan_categorylog', 'n_overlay')
# Adding field 'CategoryLog.n_packages_gentoo'
db.add_column('euscan_categorylog', 'n_packages_gentoo', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'CategoryLog.n_packages_overlay'
db.add_column('euscan_categorylog', 'n_packages_overlay', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'CategoryLog.n_packages_outdated'
db.add_column('euscan_categorylog', 'n_packages_outdated', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'CategoryLog.n_versions_gentoo'
db.add_column('euscan_categorylog', 'n_versions_gentoo', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'CategoryLog.n_versions_overlay'
db.add_column('euscan_categorylog', 'n_versions_overlay', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'CategoryLog.n_versions_upstream'
db.add_column('euscan_categorylog', 'n_versions_upstream', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Deleting field 'HerdLog.n_versions'
db.delete_column('euscan_herdlog', 'n_versions')
# Deleting field 'HerdLog.n_packaged'
db.delete_column('euscan_herdlog', 'n_packaged')
# Deleting field 'HerdLog.n_packages'
db.delete_column('euscan_herdlog', 'n_packages')
# Deleting field 'HerdLog.n_overlay'
db.delete_column('euscan_herdlog', 'n_overlay')
# Adding field 'HerdLog.n_packages_gentoo'
db.add_column('euscan_herdlog', 'n_packages_gentoo', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'HerdLog.n_packages_overlay'
db.add_column('euscan_herdlog', 'n_packages_overlay', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'HerdLog.n_packages_outdated'
db.add_column('euscan_herdlog', 'n_packages_outdated', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'HerdLog.n_versions_gentoo'
db.add_column('euscan_herdlog', 'n_versions_gentoo', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'HerdLog.n_versions_overlay'
db.add_column('euscan_herdlog', 'n_versions_overlay', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'HerdLog.n_versions_upstream'
db.add_column('euscan_herdlog', 'n_versions_upstream', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Deleting field 'MaintainerLog.n_versions'
db.delete_column('euscan_maintainerlog', 'n_versions')
# Deleting field 'MaintainerLog.n_packaged'
db.delete_column('euscan_maintainerlog', 'n_packaged')
# Deleting field 'MaintainerLog.n_packages'
db.delete_column('euscan_maintainerlog', 'n_packages')
# Deleting field 'MaintainerLog.n_overlay'
db.delete_column('euscan_maintainerlog', 'n_overlay')
# Adding field 'MaintainerLog.n_packages_gentoo'
db.add_column('euscan_maintainerlog', 'n_packages_gentoo', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'MaintainerLog.n_packages_overlay'
db.add_column('euscan_maintainerlog', 'n_packages_overlay', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'MaintainerLog.n_packages_outdated'
db.add_column('euscan_maintainerlog', 'n_packages_outdated', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'MaintainerLog.n_versions_gentoo'
db.add_column('euscan_maintainerlog', 'n_versions_gentoo', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'MaintainerLog.n_versions_overlay'
db.add_column('euscan_maintainerlog', 'n_versions_overlay', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'MaintainerLog.n_versions_upstream'
db.add_column('euscan_maintainerlog', 'n_versions_upstream', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
def backwards(self, orm):
# Adding field 'CategoryLog.n_versions'
db.add_column('euscan_categorylog', 'n_versions', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'CategoryLog.n_packaged'
db.add_column('euscan_categorylog', 'n_packaged', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'CategoryLog.n_packages'
db.add_column('euscan_categorylog', 'n_packages', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'CategoryLog.n_overlay'
db.add_column('euscan_categorylog', 'n_overlay', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Deleting field 'CategoryLog.n_packages_gentoo'
db.delete_column('euscan_categorylog', 'n_packages_gentoo')
# Deleting field 'CategoryLog.n_packages_overlay'
db.delete_column('euscan_categorylog', 'n_packages_overlay')
# Deleting field 'CategoryLog.n_packages_outdated'
db.delete_column('euscan_categorylog', 'n_packages_outdated')
# Deleting field 'CategoryLog.n_versions_gentoo'
db.delete_column('euscan_categorylog', 'n_versions_gentoo')
# Deleting field 'CategoryLog.n_versions_overlay'
db.delete_column('euscan_categorylog', 'n_versions_overlay')
# Deleting field 'CategoryLog.n_versions_upstream'
db.delete_column('euscan_categorylog', 'n_versions_upstream')
# Adding field 'HerdLog.n_versions'
db.add_column('euscan_herdlog', 'n_versions', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'HerdLog.n_packaged'
db.add_column('euscan_herdlog', 'n_packaged', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'HerdLog.n_packages'
db.add_column('euscan_herdlog', 'n_packages', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'HerdLog.n_overlay'
db.add_column('euscan_herdlog', 'n_overlay', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Deleting field 'HerdLog.n_packages_gentoo'
db.delete_column('euscan_herdlog', 'n_packages_gentoo')
# Deleting field 'HerdLog.n_packages_overlay'
db.delete_column('euscan_herdlog', 'n_packages_overlay')
# Deleting field 'HerdLog.n_packages_outdated'
db.delete_column('euscan_herdlog', 'n_packages_outdated')
# Deleting field 'HerdLog.n_versions_gentoo'
db.delete_column('euscan_herdlog', 'n_versions_gentoo')
# Deleting field 'HerdLog.n_versions_overlay'
db.delete_column('euscan_herdlog', 'n_versions_overlay')
# Deleting field 'HerdLog.n_versions_upstream'
db.delete_column('euscan_herdlog', 'n_versions_upstream')
# Adding field 'MaintainerLog.n_versions'
db.add_column('euscan_maintainerlog', 'n_versions', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'MaintainerLog.n_packaged'
db.add_column('euscan_maintainerlog', 'n_packaged', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'MaintainerLog.n_packages'
db.add_column('euscan_maintainerlog', 'n_packages', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Adding field 'MaintainerLog.n_overlay'
db.add_column('euscan_maintainerlog', 'n_overlay', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False)
# Deleting field 'MaintainerLog.n_packages_gentoo'
db.delete_column('euscan_maintainerlog', 'n_packages_gentoo')
# Deleting field 'MaintainerLog.n_packages_overlay'
db.delete_column('euscan_maintainerlog', 'n_packages_overlay')
# Deleting field 'MaintainerLog.n_packages_outdated'
db.delete_column('euscan_maintainerlog', 'n_packages_outdated')
# Deleting field 'MaintainerLog.n_versions_gentoo'
db.delete_column('euscan_maintainerlog', 'n_versions_gentoo')
# Deleting field 'MaintainerLog.n_versions_overlay'
db.delete_column('euscan_maintainerlog', 'n_versions_overlay')
# Deleting field 'MaintainerLog.n_versions_upstream'
db.delete_column('euscan_maintainerlog', 'n_versions_upstream')
models = {
'euscan.categorylog': {
'Meta': {'object_name': 'CategoryLog'},
'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'n_packages_gentoo': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages_outdated': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_gentoo': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_upstream': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'euscan.euscanresult': {
'Meta': {'object_name': 'EuscanResult'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
'result': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
'euscan.herd': {
'Meta': {'object_name': 'Herd'},
'email': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
'herd': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'euscan.herdlog': {
'Meta': {'object_name': 'HerdLog'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'herd': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Herd']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'n_packages_gentoo': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages_outdated': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_gentoo': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_upstream': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'euscan.maintainer': {
'Meta': {'object_name': 'Maintainer'},
'email': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.maintainerlog': {
'Meta': {'object_name': 'MaintainerLog'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'maintainer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Maintainer']"}),
'n_packages_gentoo': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages_outdated': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_gentoo': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_upstream': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'euscan.package': {
'Meta': {'unique_together': "(['category', 'name'],)", 'object_name': 'Package'},
'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'herds': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['euscan.Herd']", 'symmetrical': 'False', 'blank': 'True'}),
'homepage': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'maintainers': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['euscan.Maintainer']", 'symmetrical': 'False', 'blank': 'True'}),
'n_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.version': {
'Meta': {'unique_together': "(['package', 'slot', 'revision', 'version', 'overlay'],)", 'object_name': 'Version'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'overlay': ('django.db.models.fields.CharField', [], {'default': "'gentoo'", 'max_length': '128'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
'packaged': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'slot': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'urls': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'version': ('django.db.models.fields.CharField', [], {'max_length': '128'})
}
}
complete_apps = ['euscan']

View File

@ -1,139 +0,0 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Deleting model 'CategoryLog'
db.delete_table('euscan_categorylog')
# Deleting model 'HerdLog'
db.delete_table('euscan_herdlog')
# Deleting model 'MaintainerLog'
db.delete_table('euscan_maintainerlog')
# Adding model 'Log'
db.create_table('euscan_log', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('datetime', self.gf('django.db.models.fields.DateTimeField')()),
('n_packages_gentoo', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_packages_overlay', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_packages_outdated', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_versions_gentoo', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_versions_overlay', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_versions_upstream', self.gf('django.db.models.fields.IntegerField')(default=0)),
))
db.send_create_signal('euscan', ['Log'])
def backwards(self, orm):
# Adding model 'CategoryLog'
db.create_table('euscan_categorylog', (
('category', self.gf('django.db.models.fields.CharField')(max_length=128)),
('n_packages_gentoo', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_packages_outdated', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_packages_overlay', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_versions_upstream', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_versions_overlay', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_versions_gentoo', self.gf('django.db.models.fields.IntegerField')(default=0)),
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('datetime', self.gf('django.db.models.fields.DateTimeField')()),
))
db.send_create_signal('euscan', ['CategoryLog'])
# Adding model 'HerdLog'
db.create_table('euscan_herdlog', (
('n_packages_gentoo', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_versions_overlay', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_packages_outdated', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_packages_overlay', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_versions_upstream', self.gf('django.db.models.fields.IntegerField')(default=0)),
('herd', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['euscan.Herd'])),
('n_versions_gentoo', self.gf('django.db.models.fields.IntegerField')(default=0)),
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('datetime', self.gf('django.db.models.fields.DateTimeField')()),
))
db.send_create_signal('euscan', ['HerdLog'])
# Adding model 'MaintainerLog'
db.create_table('euscan_maintainerlog', (
('n_packages_gentoo', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_versions_overlay', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_packages_outdated', self.gf('django.db.models.fields.IntegerField')(default=0)),
('maintainer', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['euscan.Maintainer'])),
('n_packages_overlay', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_versions_upstream', self.gf('django.db.models.fields.IntegerField')(default=0)),
('n_versions_gentoo', self.gf('django.db.models.fields.IntegerField')(default=0)),
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('datetime', self.gf('django.db.models.fields.DateTimeField')()),
))
db.send_create_signal('euscan', ['MaintainerLog'])
# Deleting model 'Log'
db.delete_table('euscan_log')
models = {
'euscan.euscanresult': {
'Meta': {'object_name': 'EuscanResult'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
'result': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
'euscan.herd': {
'Meta': {'object_name': 'Herd'},
'email': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
'herd': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'euscan.log': {
'Meta': {'object_name': 'Log'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'n_packages_gentoo': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages_outdated': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_gentoo': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_upstream': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'euscan.maintainer': {
'Meta': {'object_name': 'Maintainer'},
'email': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.package': {
'Meta': {'unique_together': "(['category', 'name'],)", 'object_name': 'Package'},
'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'herds': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['euscan.Herd']", 'symmetrical': 'False', 'blank': 'True'}),
'homepage': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'maintainers': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['euscan.Maintainer']", 'symmetrical': 'False', 'blank': 'True'}),
'n_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.version': {
'Meta': {'unique_together': "(['package', 'slot', 'revision', 'version', 'overlay'],)", 'object_name': 'Version'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'overlay': ('django.db.models.fields.CharField', [], {'default': "'gentoo'", 'max_length': '128'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
'packaged': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'slot': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'urls': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'version': ('django.db.models.fields.CharField', [], {'max_length': '128'})
}
}
complete_apps = ['euscan']

View File

@ -1,130 +0,0 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'WorldLog'
db.create_table('euscan_worldlog', (
('log_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['euscan.Log'], unique=True, primary_key=True)),
))
db.send_create_signal('euscan', ['WorldLog'])
# Adding model 'CategoryLog'
db.create_table('euscan_categorylog', (
('log_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['euscan.Log'], unique=True, primary_key=True)),
('category', self.gf('django.db.models.fields.CharField')(max_length=128)),
))
db.send_create_signal('euscan', ['CategoryLog'])
# Adding model 'HerdLog'
db.create_table('euscan_herdlog', (
('log_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['euscan.Log'], unique=True, primary_key=True)),
('herd', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['euscan.Herd'])),
))
db.send_create_signal('euscan', ['HerdLog'])
# Adding model 'MaintainerLog'
db.create_table('euscan_maintainerlog', (
('log_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['euscan.Log'], unique=True, primary_key=True)),
('maintainer', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['euscan.Maintainer'])),
))
db.send_create_signal('euscan', ['MaintainerLog'])
def backwards(self, orm):
# Deleting model 'WorldLog'
db.delete_table('euscan_worldlog')
# Deleting model 'CategoryLog'
db.delete_table('euscan_categorylog')
# Deleting model 'HerdLog'
db.delete_table('euscan_herdlog')
# Deleting model 'MaintainerLog'
db.delete_table('euscan_maintainerlog')
models = {
'euscan.categorylog': {
'Meta': {'object_name': 'CategoryLog', '_ormbases': ['euscan.Log']},
'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'log_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['euscan.Log']", 'unique': 'True', 'primary_key': 'True'})
},
'euscan.euscanresult': {
'Meta': {'object_name': 'EuscanResult'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
'result': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
'euscan.herd': {
'Meta': {'object_name': 'Herd'},
'email': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
'herd': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'euscan.herdlog': {
'Meta': {'object_name': 'HerdLog', '_ormbases': ['euscan.Log']},
'herd': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Herd']"}),
'log_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['euscan.Log']", 'unique': 'True', 'primary_key': 'True'})
},
'euscan.log': {
'Meta': {'object_name': 'Log'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'n_packages_gentoo': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages_outdated': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_gentoo': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_upstream': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'euscan.maintainer': {
'Meta': {'object_name': 'Maintainer'},
'email': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.maintainerlog': {
'Meta': {'object_name': 'MaintainerLog', '_ormbases': ['euscan.Log']},
'log_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['euscan.Log']", 'unique': 'True', 'primary_key': 'True'}),
'maintainer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Maintainer']"})
},
'euscan.package': {
'Meta': {'unique_together': "(['category', 'name'],)", 'object_name': 'Package'},
'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'herds': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['euscan.Herd']", 'symmetrical': 'False', 'blank': 'True'}),
'homepage': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'maintainers': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['euscan.Maintainer']", 'symmetrical': 'False', 'blank': 'True'}),
'n_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.version': {
'Meta': {'unique_together': "(['package', 'slot', 'revision', 'version', 'overlay'],)", 'object_name': 'Version'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'overlay': ('django.db.models.fields.CharField', [], {'default': "'gentoo'", 'max_length': '128'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
'packaged': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'slot': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'urls': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'version': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.worldlog': {
'Meta': {'object_name': 'WorldLog', '_ormbases': ['euscan.Log']},
'log_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['euscan.Log']", 'unique': 'True', 'primary_key': 'True'})
}
}
complete_apps = ['euscan']

View File

@ -1,127 +0,0 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'VersionLog'
db.create_table('euscan_versionlog', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('package', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['euscan.Package'])),
('datetime', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime(2011, 8, 22, 21, 41, 33, 285480))),
('slot', self.gf('django.db.models.fields.CharField')(max_length=128)),
('revision', self.gf('django.db.models.fields.CharField')(max_length=128)),
('version', self.gf('django.db.models.fields.CharField')(max_length=128)),
('packaged', self.gf('django.db.models.fields.BooleanField')(default=False)),
('overlay', self.gf('django.db.models.fields.CharField')(default='gentoo', max_length=128)),
('action', self.gf('django.db.models.fields.IntegerField')()),
))
db.send_create_signal('euscan', ['VersionLog'])
# Adding field 'Version.alive'
db.add_column('euscan_version', 'alive', self.gf('django.db.models.fields.BooleanField')(default=True, db_index=True), keep_default=False)
def backwards(self, orm):
# Deleting model 'VersionLog'
db.delete_table('euscan_versionlog')
# Deleting field 'Version.alive'
db.delete_column('euscan_version', 'alive')
models = {
'euscan.categorylog': {
'Meta': {'object_name': 'CategoryLog', '_ormbases': ['euscan.Log']},
'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'log_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['euscan.Log']", 'unique': 'True', 'primary_key': 'True'})
},
'euscan.euscanresult': {
'Meta': {'object_name': 'EuscanResult'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
'result': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
'euscan.herd': {
'Meta': {'object_name': 'Herd'},
'email': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
'herd': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'euscan.herdlog': {
'Meta': {'object_name': 'HerdLog', '_ormbases': ['euscan.Log']},
'herd': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Herd']"}),
'log_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['euscan.Log']", 'unique': 'True', 'primary_key': 'True'})
},
'euscan.log': {
'Meta': {'object_name': 'Log'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'n_packages_gentoo': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages_outdated': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_gentoo': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_upstream': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'euscan.maintainer': {
'Meta': {'object_name': 'Maintainer'},
'email': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.maintainerlog': {
'Meta': {'object_name': 'MaintainerLog', '_ormbases': ['euscan.Log']},
'log_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['euscan.Log']", 'unique': 'True', 'primary_key': 'True'}),
'maintainer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Maintainer']"})
},
'euscan.package': {
'Meta': {'unique_together': "(['category', 'name'],)", 'object_name': 'Package'},
'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'herds': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['euscan.Herd']", 'symmetrical': 'False', 'blank': 'True'}),
'homepage': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'maintainers': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['euscan.Maintainer']", 'symmetrical': 'False', 'blank': 'True'}),
'n_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.version': {
'Meta': {'unique_together': "(['package', 'slot', 'revision', 'version', 'overlay'],)", 'object_name': 'Version'},
'alive': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'overlay': ('django.db.models.fields.CharField', [], {'default': "'gentoo'", 'max_length': '128'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
'packaged': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'slot': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'urls': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'version': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.versionlog': {
'Meta': {'object_name': 'VersionLog'},
'action': ('django.db.models.fields.IntegerField', [], {}),
'datetime': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2011, 8, 22, 21, 41, 33, 285480)'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'overlay': ('django.db.models.fields.CharField', [], {'default': "'gentoo'", 'max_length': '128'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
'packaged': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'slot': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'version': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.worldlog': {
'Meta': {'object_name': 'WorldLog', '_ormbases': ['euscan.Log']},
'log_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['euscan.Log']", 'unique': 'True', 'primary_key': 'True'})
}
}
complete_apps = ['euscan']

View File

@ -1,110 +0,0 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding index on 'Version', fields ['overlay']
db.create_index('euscan_version', ['overlay'])
def backwards(self, orm):
# Removing index on 'Version', fields ['overlay']
db.delete_index('euscan_version', ['overlay'])
models = {
'euscan.categorylog': {
'Meta': {'object_name': 'CategoryLog', '_ormbases': ['euscan.Log']},
'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'log_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['euscan.Log']", 'unique': 'True', 'primary_key': 'True'})
},
'euscan.euscanresult': {
'Meta': {'object_name': 'EuscanResult'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
'result': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
'euscan.herd': {
'Meta': {'object_name': 'Herd'},
'email': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
'herd': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'euscan.herdlog': {
'Meta': {'object_name': 'HerdLog', '_ormbases': ['euscan.Log']},
'herd': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Herd']"}),
'log_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['euscan.Log']", 'unique': 'True', 'primary_key': 'True'})
},
'euscan.log': {
'Meta': {'object_name': 'Log'},
'datetime': ('django.db.models.fields.DateTimeField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'n_packages_gentoo': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages_outdated': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packages_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_gentoo': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions_upstream': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'euscan.maintainer': {
'Meta': {'object_name': 'Maintainer'},
'email': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.maintainerlog': {
'Meta': {'object_name': 'MaintainerLog', '_ormbases': ['euscan.Log']},
'log_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['euscan.Log']", 'unique': 'True', 'primary_key': 'True'}),
'maintainer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Maintainer']"})
},
'euscan.package': {
'Meta': {'unique_together': "(['category', 'name'],)", 'object_name': 'Package'},
'category': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'herds': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['euscan.Herd']", 'symmetrical': 'False', 'blank': 'True'}),
'homepage': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'maintainers': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['euscan.Maintainer']", 'symmetrical': 'False', 'blank': 'True'}),
'n_overlay': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_packaged': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'n_versions': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.version': {
'Meta': {'unique_together': "(['package', 'slot', 'revision', 'version', 'overlay'],)", 'object_name': 'Version'},
'alive': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'overlay': ('django.db.models.fields.CharField', [], {'default': "'gentoo'", 'max_length': '128', 'db_index': 'True'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
'packaged': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'slot': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'urls': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'version': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.versionlog': {
'Meta': {'object_name': 'VersionLog'},
'action': ('django.db.models.fields.IntegerField', [], {}),
'datetime': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2011, 11, 23, 17, 13, 34, 785901)'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'overlay': ('django.db.models.fields.CharField', [], {'default': "'gentoo'", 'max_length': '128'}),
'package': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['euscan.Package']"}),
'packaged': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'revision': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'slot': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'version': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'euscan.worldlog': {
'Meta': {'object_name': 'WorldLog', '_ormbases': ['euscan.Log']},
'log_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['euscan.Log']", 'unique': 'True', 'primary_key': 'True'})
}
}
complete_apps = ['euscan']

View File

@ -1,134 +0,0 @@
from django.db import models
from datetime import datetime
class Herd(models.Model):
herd = models.CharField(max_length=128, unique=True)
email = models.CharField(max_length=128, blank=True, null=True)
def __unicode__(self):
if self.email:
return '%s <%s>' % (self.herd, self.email)
return self.herd
class Maintainer(models.Model):
name = models.CharField(max_length=128)
email = models.CharField(max_length=128, unique=True)
def __unicode__(self):
return '%s <%s>' % (self.name, self.email)
class Package(models.Model):
category = models.CharField(max_length=128)
name = models.CharField(max_length=128)
description = models.TextField(blank=True)
homepage = models.CharField(max_length=256, blank=True)
herds = models.ManyToManyField(Herd, blank=True)
maintainers = models.ManyToManyField(Maintainer, blank=True)
' For performance, we keep pre-computed counters '
n_versions = models.IntegerField(default=0)
n_packaged = models.IntegerField(default=0)
n_overlay = models.IntegerField(default=0)
def __unicode__(self):
return '%s/%s' % (self.category, self.name)
class Meta:
unique_together = ['category', 'name']
class Version(models.Model):
package = models.ForeignKey(Package)
slot = models.CharField(max_length=128)
revision = models.CharField(max_length=128)
version = models.CharField(max_length=128)
packaged = models.BooleanField()
overlay = models.CharField(max_length=128, default='gentoo', db_index=True)
urls = models.TextField(blank=True)
alive = models.BooleanField(default=True, db_index=True)
def __unicode__(self):
return '%s/%s-%s-%s:%s [%s]' % (self.package.category, self.package.name,
self.version, self.revision, self.slot,
self.overlay)
class Meta:
unique_together = ['package', 'slot', 'revision', 'version', 'overlay']
class VersionLog(models.Model):
VERSION_ADDED = 1
VERSION_REMOVED = 2
VERSION_ACTIONS = (
(VERSION_ADDED, 'Added'),
(VERSION_REMOVED, 'Removed')
)
package = models.ForeignKey(Package)
datetime = models.DateTimeField(default=datetime.now())
slot = models.CharField(max_length=128)
revision = models.CharField(max_length=128)
version = models.CharField(max_length=128)
packaged = models.BooleanField()
overlay = models.CharField(max_length=128, default='gentoo')
action = models.IntegerField(choices=VERSION_ACTIONS)
def tag(self):
return '%s-%s:%s-[%s]' % (self.version, self.revision, self.slot,
self.overlay)
def __unicode__(self):
txt = '+ ' if self.action == self.VERSION_ADDED else '- '
txt += '%s/%s-%s-%s:%s [%s]' % (self.package.category, self.package.name,
self.version, self.revision, self.slot,
self.overlay if self.overlay else '<upstream>')
return txt
class EuscanResult(models.Model):
package = models.ForeignKey(Package)
datetime = models.DateTimeField()
result = models.TextField(blank=True)
# Keep data for charts
class Log(models.Model):
datetime = models.DateTimeField()
' Packages up to date in the main portage tree '
n_packages_gentoo = models.IntegerField(default=0)
' Packages up to date in an overlay '
n_packages_overlay = models.IntegerField(default=0)
' Packages outdated '
n_packages_outdated = models.IntegerField(default=0)
' Versions in the main portage tree '
n_versions_gentoo = models.IntegerField(default=0)
' Versions in overlays '
n_versions_overlay = models.IntegerField(default=0)
' Upstream versions, not in the main tree or overlays '
n_versions_upstream = models.IntegerField(default=0)
def __unicode__(self):
return u'[%d:%d:%d] [%d:%d:%d]' % \
(self.n_packages_gentoo, self.n_packages_overlay, self.n_packages_outdated, \
self.n_versions_gentoo, self.n_versions_overlay, self.n_versions_upstream)
class WorldLog(Log):
def __unicode__(self):
return u'world ' + Log.__unicode__(self)
class CategoryLog(Log):
category = models.CharField(max_length=128)
def __unicode__(self):
return u'%s %s' % (self.category, Log.__unicode__(self))
class HerdLog(Log):
herd = models.ForeignKey(Herd)
def __unicode__(self):
return u'%s %s' % (self.herd, Log.__unicode__(self))
class MaintainerLog(Log):
maintainer = models.ForeignKey(Maintainer)
def __unicode__(self):
return u'%s %s' % (self.maintainer, Log.__unicode__(self))

View File

@ -1,8 +0,0 @@
from django import template
register = template.Library()
def div(value, arg=None):
return value/arg
register.filter('div', div)

View File

@ -1,29 +0,0 @@
from django.template import Node, Library
import math
register = Library()
# taken from http://lybniz2.sourceforge.net/safeeval.html
# make a list of safe functions
math_safe_list = ['acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh']
# use the list to filter the local namespace
math_safe_dict = dict([(k, getattr(math, k)) for k in math_safe_list])
# add any needed builtins back in.
math_safe_dict['abs'] = abs
@register.filter('math')
def math_(lopr, expr):
"""Evals a math expression and returns it's value.
"$1" is a placeholder. Insert "$1" in the expression where the value is to be used. All math functions such as abs, sin, cos, floor are supported.
Example,
a. You will be redirected in {{ seconds|math:"$1 / 60.0" }} minutes
b. Square of {{ x }} is {{ x|math:"$1 * $1" }}
c. Square root of {{ x }} is {{ x|math:"sqrt($1)" }}
d. Given x = {{ x }}, (2 + x) * 6 = {{ x|math:"(2 + $1) * 6" }}
"""
if lopr:
return eval(expr.replace('$1', str(lopr)), {"__builtins__": None}, math_safe_dict)
return ''

View File

@ -1,8 +0,0 @@
from django import template
register = template.Library()
def mul(value, arg=None):
return value*arg
register.filter('mul', mul)

View File

@ -1,15 +0,0 @@
from django import template
register = template.Library()
@register.inclusion_tag('euscan/_packages.html')
def packages(packages):
return { 'packages' : packages }
@register.inclusion_tag('euscan/_package_cols.html')
def package_cols(infos):
return { 'infos' : infos }
@register.inclusion_tag('euscan/_package_bar.html')
def package_bar(infos):
return { 'infos' : infos }

View File

@ -1,8 +0,0 @@
from django import template
register = template.Library()
def sub(value, arg=None):
return value-arg
register.filter('sub', sub)

View File

@ -1,19 +0,0 @@
from django import template
from django.utils.timesince import timesince
from datetime import datetime
register = template.Library()
def timedelta(value, arg=None):
if not value:
return ''
if arg:
cmp = arg
else:
cmp = datetime.now()
if value > cmp:
return "in %s" % timesince(cmp,value)
else:
return "%s ago" % timesince(value,cmp)
register.filter('timedelta',timedelta)

View File

@ -1,23 +0,0 @@
"""
This file demonstrates two different styles of tests (one doctest and one
unittest). These will both pass when you run "manage.py test".
Replace these with more appropriate tests for your application.
"""
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.failUnlessEqual(1 + 1, 2)
__test__ = {"doctest": """
Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}

View File

@ -1,52 +0,0 @@
from django.conf.urls.defaults import *
from feeds import *
package_patterns = patterns('euscan.views',
url(r'^(?P<category>[\w+][\w+.-]*)/(?P<package>[\w+][\w+.-]*)/feed/$', PackageFeed(), name='package_feed'),
(r'^(?P<category>[\w+][\w+.-]*)/(?P<package>[\w+][\w+.-]*)/$', 'package'),
)
categories_patterns = patterns('euscan.views',
(r'^(?P<category>[\w+][\w+.-]*)/(view/)?$', 'category'),
url(r'^(?P<category>[\w+][\w+.-]*)/feed/$', CategoryFeed(), name='category_feed'),
(r'^(?P<category>[\w+][\w+.-]*)/charts/(?P<chart>[\w\-]+).png$', 'chart_category'),
(r'^$', 'categories'),
)
herds_patterns = patterns('euscan.views',
(r'^(?P<herd>[\@\{\}\w+.-]*)/(view/)?$', 'herd'),
url(r'^(?P<herd>[\@\{\}\w+.-]*)/feed/$', HerdFeed(), name='herd_feed'),
(r'^(?P<herd>[\@\{\}\w+.-]*)/charts/(?P<chart>[\w\-]+).png$', 'chart_herd'),
(r'^$', 'herds'),
)
maintainers_patterns = patterns('euscan.views',
(r'^(?P<maintainer_id>\d+)/(view/)?$', 'maintainer'),
url(r'^(?P<maintainer_id>\d+)/feed/$', MaintainerFeed(), name='maintainer_feed'),
(r'^(?P<maintainer_id>\d+)/charts/(?P<chart>[\w\-]+).png$', 'chart_maintainer'),
(r'^$', 'maintainers'),
)
overlays_patterns = patterns('euscan.views',
(r'^(?P<overlay>[\w+][\w+.-]*)/(view/)?$', 'overlay'),
(r'^$', 'overlays'),
)
urlpatterns = patterns('euscan.views',
# Global stuff
(r'^$', 'index'),
url(r'^feed/$', GlobalFeed(), name='global_feed'),
(r'^about/$', 'about'),
(r'^about/api$', 'api'),
(r'^statistics/$', 'statistics'),
(r'^statistics/charts/(?P<chart>[\w\-]+).png$', 'chart'),
(r'^world/$', 'world'),
(r'^world/scan/$', 'world_scan'),
# Real data
(r'^categories/', include(categories_patterns)),
(r'^herds/', include(herds_patterns)),
(r'^maintainers/', include(maintainers_patterns)),
(r'^overlays/', include(overlays_patterns)),
(r'^package/', include(package_patterns)),
)

View File

@ -1,188 +0,0 @@
from annoying.decorators import render_to
from django.http import HttpResponse, Http404
from django.shortcuts import get_object_or_404
from django.db.models import Sum, Max
from euscan.models import Version, Package, Herd, Maintainer, EuscanResult, VersionLog
from euscan.forms import WorldForm, PackagesForm
import charts
""" Views """
@render_to('euscan/index.html')
def index(request):
ctx = {}
ctx['n_packaged'] = charts.xint(Package.objects.aggregate(Sum('n_packaged'))['n_packaged__sum'])
ctx['n_overlay'] = charts.xint(Package.objects.aggregate(Sum('n_overlay'))['n_overlay__sum'])
ctx['n_versions'] = charts.xint(Package.objects.aggregate(Sum('n_versions'))['n_versions__sum'])
ctx['n_upstream'] = ctx['n_versions'] - ctx['n_packaged'] - ctx['n_overlay']
ctx['n_packages'] = Package.objects.count()
ctx['n_herds'] = Herd.objects.count()
ctx['n_maintainers'] = Maintainer.objects.count()
ctx['last_scan'] = EuscanResult.objects.get(id=EuscanResult.objects.aggregate(Max('id'))['id__max']).datetime
return ctx
@render_to('euscan/logs.html')
def logs(request):
return {}
@render_to('euscan/categories.html')
def categories(request):
categories = Package.objects.values('category').annotate(n_packaged=Sum('n_packaged'),
n_overlay=Sum('n_overlay'),
n_versions=Sum('n_versions'))
return { 'categories' : categories }
@render_to('euscan/category.html')
def category(request, category):
packages = Package.objects.filter(category=category)
if not packages:
raise Http404
return { 'category' : category, 'packages' : packages }
@render_to('euscan/herds.html')
def herds(request):
# FIXME: optimize the query, it uses 'LEFT OUTER JOIN' instead of 'INNER JOIN'
herds = Package.objects.filter(herds__isnull=False)
herds = herds.values('herds__herd').annotate(n_packaged=Sum('n_packaged'),
n_overlay=Sum('n_overlay'),
n_versions=Sum('n_versions'))
return { 'herds' : herds }
@render_to('euscan/herd.html')
def herd(request, herd):
herd = get_object_or_404(Herd, herd=herd)
packages = Package.objects.filter(herds__id=herd.id)
return { 'herd' : herd, 'packages' : packages }
@render_to('euscan/maintainers.html')
def maintainers(request):
maintainers = Package.objects.filter(maintainers__isnull=False)
maintainers = maintainers.values('maintainers__id', 'maintainers__name')
maintainers = maintainers.annotate(n_packaged=Sum('n_packaged'),
n_overlay=Sum('n_overlay'),
n_versions=Sum('n_versions'))
return { 'maintainers' : maintainers }
@render_to('euscan/maintainer.html')
def maintainer(request, maintainer_id):
maintainer = get_object_or_404(Maintainer, id=maintainer_id)
packages = Package.objects.filter(maintainers__id=maintainer.id)
return { 'maintainer' : maintainer, 'packages' : packages }
@render_to('euscan/overlays.html')
def overlays(request):
overlays = Package.objects.values('version__overlay')
overlays = overlays.exclude(version__overlay='')
overlays = overlays.distinct()
return { 'overlays' : overlays }
@render_to('euscan/overlay.html')
def overlay(request, overlay):
packages = Package.objects.values('id', 'name', 'category',
'n_versions', 'n_packaged',
'n_overlay')
packages = packages.filter(version__overlay=overlay).distinct()
if not packages:
raise Http404
return { 'overlay' : overlay, 'packages' : packages }
@render_to('euscan/package.html')
def package(request, category, package):
package = get_object_or_404(Package, category=category, name=package)
package.homepages = package.homepage.split(' ')
packaged = Version.objects.filter(package=package, packaged=True)
upstream = Version.objects.filter(package=package, packaged=False)
log = EuscanResult.objects.filter(package=package).order_by('-datetime')[:1]
log = log[0] if log else None
vlog = VersionLog.objects.filter(package=package).order_by('-id')
return { 'package' : package, 'packaged' : packaged,
'upstream' : upstream, 'log' : log, 'vlog' : vlog }
@render_to('euscan/world.html')
def world(request):
world_form = WorldForm()
packages_form = PackagesForm()
return { 'world_form' : world_form,
'packages_form' : packages_form }
@render_to('euscan/world_scan.html')
def world_scan(request):
packages = []
if 'world' in request.FILES:
data = request.FILES['world'].read()
elif 'packages' in request.POST:
data = request.POST['packages']
else:
data = ""
data = data.replace("\r", "")
for pkg in data.split('\n'):
try:
if '/' in pkg:
cat, pkg = pkg.split('/')
packages.extend(Package.objects.filter(category=cat, name=pkg))
else:
packages.extend(Package.objects.filter(name=pkg))
except:
pass
return { 'packages' : packages }
@render_to("euscan/about.html")
def about(request):
return {}
@render_to("euscan/api.html")
def api(request):
return {}
@render_to("euscan/statistics.html")
def statistics(request):
return {}
def chart(request, **kwargs):
from django.views.static import serve
chart = kwargs['chart'] if 'chart' in kwargs else None
if 'maintainer_id' in kwargs:
kwargs['maintainer'] = get_object_or_404(Maintainer, id=kwargs['maintainer_id'])
if 'herd' in kwargs:
kwargs['herd'] = get_object_or_404(Herd, herd=kwargs['herd'])
for kw in ('-small', '-weekly', '-monthly', '-yearly'):
if chart.endswith(kw):
if kw in ('-weekly', '-monthly', '-yearly'):
kwargs['period'] = kw
kwargs[kw] = True
chart = chart[:-len(kw)]
if chart == 'pie-packages':
path = charts.pie_packages(**kwargs)
elif chart == 'pie-versions':
path = charts.pie_versions(**kwargs)
elif chart == 'packages':
path = charts.packages(**kwargs)
elif chart == 'versions':
path = charts.versions(**kwargs)
else:
raise Http404()
return serve(request, path, document_root=charts.CHARTS_ROOT)
def chart_maintainer(request, **kwargs):
return chart(request, **kwargs)
def chart_herd(request, **kwargs):
return chart(request, **kwargs)
def chart_category(request, **kwargs):
return chart(request, **kwargs)

View File

@ -1,11 +0,0 @@
#!/usr/bin/env python
from django.core.management import execute_manager
try:
import settings # Assumed to be in the same directory.
except ImportError:
import sys
sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
sys.exit(1)
if __name__ == "__main__":
execute_manager(settings)

View File

@ -1,274 +0,0 @@
body
{
margin: 0;
padding: 0;
font-size: 0.8em;
font-family: Dejavu, Verdana, "Bitstream Vera Sans", "Lucida Grande", "Trebuchet MS", sans-serif;
color: #535353;
background: #D2D0D4;
}
img
{
border: none;
}
h1
{
margin-top: 0;
color: #369;
font-size: 1.6em;
}
a:link, a:visited
{
text-decoration: none;
font-weight: bold;
color: #ff8c00;
}
a:hover, a:active
{
font-weight: bold;
color: #ff4500;
text-decoration: underline;
}
#header {
/* background: url(http://packages.gentoo.org/media/packages_gentoo_logo.jpg) no-repeat;
background-color: #46347C; */
width: 100%;
height: 30px;
margin: 0;
padding: 0;
background: url(../img/gentoo-header-bar-bg.png) repeat-x;
}
#header #logo
{
float: left;
}
#content {
background: #F0F0F0;
padding: 10px;
margin-top: 10px;
/* margin-right: auto;
margin-left: auto;
*/
margin-left: 20px;
/* margin-left: 20%; */
margin-right: 250px;
/* max-width: 60em; */
border: 1px solid #67539B;
background: #FEFEFE;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}
#menu {
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
border: 1px solid #67539B;
}
#menu, #menu_dl {
width:100%;
margin-top: 75px;
background: #8076A1;
color: #FFF;
}
#menu a {
color: #fff;
}
#menu li
{
list-style-type: none;
}
#menus {
width: 200px;
position:absolute;
top:30px;
right:20px;
/*
position: fixed;
right: 10px;
top: 2em;
width: 20%;
*/
}
/*
code, pre{
background-color:transparent;
font-family:"Courier New",Courier,monospace;
font-size:small;
}
*/
a{
color: #3F4C66;
}
a:link, a:visited, a:active {
color: #3F4C66;
text-decoration: none;
}
a:hover {
color: #4C5C7B;
text-decoration: underline;
}
abbr:hover {
text-decoration: underline;
}
pre{
border-left:5px solid;
padding:0.5em 1em;
margin-left:2em;
}
dt {
font-weight: bold;
}
dd {
border-left: 1px solid #ccc;
margin: 5px;
padding: 5px;
}
h1 {
color: #000;
width: 20em;
margin-left: auto;
margin-right: auto;
}
.ok {
color:#15B100;
}
hr
{
margin: 0.3em 1em 0.3em 1em;
height: 1px;
border: #bcbcbc dashed;
border-width: 0 0 1px 0;
}
table
{
max-width: 60em;
/* width: 50%; */
border-collapse: collapse;
font-size: 1em;
margin-left: auto;
margin-right: auto;
background: #F5F5F5;
text-align: left;
}
td
{
vertical-align: top;
}
th
{
text-align: center;
border-bottom: 3px solid;
}
#footer
{
background: #8076A1;
font-size: 0.8em;
width: 100%;
margin: 0;
margin-top: 10px;
color: #FFF;
}
#footer p {
text-align: right;
margin: 5px;
}
.err,.ok,.inf
{
margin: 5px;
margin-left: auto;
margin-right: auto;
width: 70%;
font-weight:bold;
border: 1px dotted #5682AD;
}
.added {
color: #262;
}
.removed {
color: #F00;
}
.err
{
border-color: #F00;
color: #F00;
}
.ok
{
border-color: #262;
color: #262;
}
.logo {
float: right;
}
.clear {
clear: both;
}
.package_stat {
width: 40px;
float: right;
height: 5px;
border: 1px solid #ccc;
}
.package_stat div {
float: left;
height: 5px;
}
.package_stat .packaged {
background: #85ACFF;
}
.package_stat .overlay {
background: #C6D9FD;
}
.package_stat .upstream {
background: #FDEADD;
}
.log {
max-height: 100pt;
overflow: auto;
}

View File

@ -1,336 +0,0 @@
/*
* File: demo_table.css
* CVS: $Id$
* Description: CSS descriptions for DataTables demo pages
* Author: Allan Jardine
* Created: Tue May 12 06:47:22 BST 2009
* Modified: $Date$ by $Author$
* Language: CSS
* Project: DataTables
*
* Copyright 2009 Allan Jardine. All Rights Reserved.
*
* ***************************************************************************
* DESCRIPTION
*
* The styles given here are suitable for the demos that are used with the standard DataTables
* distribution (see www.datatables.net). You will most likely wish to modify these styles to
* meet the layout requirements of your site.
*
* Common issues:
* 'full_numbers' pagination - I use an extra selector on the body tag to ensure that there is
* no conflict between the two pagination types. If you want to use full_numbers pagination
* ensure that you either have "example_alt_pagination" as a body class name, or better yet,
* modify that selector.
* Note that the path used for Images is relative. All images are by default located in
* ../img/ - relative to this CSS file.
*/
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* DataTables features
*/
.dataTables_wrapper {
position: relative;
min-height: 302px;
clear: both;
_height: 302px;
zoom: 1; /* Feeling sorry for IE */
}
.dataTables_processing {
position: absolute;
top: 50%;
left: 50%;
width: 250px;
height: 30px;
margin-left: -125px;
margin-top: -15px;
padding: 14px 0 2px 0;
border: 1px solid #ddd;
text-align: center;
color: #999;
font-size: 14px;
background-color: white;
}
.dataTables_length {
width: 40%;
float: left;
}
.dataTables_filter {
width: 50%;
float: right;
text-align: right;
}
.dataTables_info {
width: 60%;
float: left;
}
.dataTables_paginate {
width: 44px;
* width: 50px;
float: right;
text-align: right;
}
/* Pagination nested */
.paginate_disabled_previous, .paginate_enabled_previous, .paginate_disabled_next, .paginate_enabled_next {
height: 19px;
width: 19px;
margin-left: 3px;
float: left;
}
.paginate_disabled_previous {
background-image: url('../img/back_disabled.jpg');
}
.paginate_enabled_previous {
background-image: url('../img/back_enabled.jpg');
}
.paginate_disabled_next {
background-image: url('../img/forward_disabled.jpg');
}
.paginate_enabled_next {
background-image: url('../img/forward_enabled.jpg');
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* DataTables display
*/
table.display {
margin: 0 auto;
clear: both;
width: 100%;
/* Note Firefox 3.5 and before have a bug with border-collapse
* ( https://bugzilla.mozilla.org/show%5Fbug.cgi?id=155955 )
* border-spacing: 0; is one possible option. Conditional-css.com is
* useful for this kind of thing
*
* Further note IE 6/7 has problems when calculating widths with border width.
* It subtracts one px relative to the other browsers from the first column, and
* adds one to the end...
*
* If you want that effect I'd suggest setting a border-top/left on th/td's and
* then filling in the gaps with other borders.
*/
}
table.display thead th {
padding: 3px 18px 3px 10px;
border-bottom: 1px solid black;
font-weight: bold;
cursor: pointer;
* cursor: hand;
}
table.display tfoot th {
padding: 3px 18px 3px 10px;
border-top: 1px solid black;
font-weight: bold;
}
table.display tr.heading2 td {
border-bottom: 1px solid #aaa;
}
table.display td {
padding: 3px 10px;
}
table.display td.center {
text-align: center;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* DataTables sorting
*/
.sorting_asc {
background: url('../img/sort_asc.png') no-repeat center right;
}
.sorting_desc {
background: url('../img/sort_desc.png') no-repeat center right;
}
.sorting {
background: url('../img/sort_both.png') no-repeat center right;
}
.sorting_asc_disabled {
background: url('../img/sort_asc_disabled.png') no-repeat center right;
}
.sorting_desc_disabled {
background: url('../img/sort_desc_disabled.png') no-repeat center right;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* DataTables row classes
*/
table.display td.bad {
background-color: #FFDFDF;
}
table.display td.ugly {
background-color: #EDB9B9;
}
tr {
background-color: #E2E4FF;
}
tr.even {
background-color: white;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Misc
*/
.dataTables_scroll {
clear: both;
}
.dataTables_scrollBody {
*margin-top: -1px;
}
.top, .bottom {
padding: 15px;
background-color: #F5F5F5;
border: 1px solid #CCCCCC;
}
.top .dataTables_info {
float: none;
}
.clear {
clear: both;
}
.dataTables_empty {
text-align: center;
}
tfoot input {
margin: 0.5em 0;
width: 100%;
color: #444;
}
tfoot input.search_init {
color: #999;
}
td.group {
background-color: #d1cfd0;
border-bottom: 2px solid #A19B9E;
border-top: 2px solid #A19B9E;
}
td.details {
background-color: #d1cfd0;
border: 2px solid #A19B9E;
}
.example_alt_pagination div.dataTables_info {
width: 40%;
}
.paging_full_numbers {
width: 400px;
height: 22px;
line-height: 22px;
}
.paging_full_numbers span.paginate_button,
.paging_full_numbers span.paginate_active {
border: 1px solid #aaa;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
padding: 2px 5px;
margin: 0 3px;
cursor: pointer;
*cursor: hand;
}
.paging_full_numbers span.paginate_button {
background-color: #ddd;
}
.paging_full_numbers span.paginate_button:hover {
background-color: #ccc;
}
.paging_full_numbers span.paginate_active {
background-color: #99B3FF;
}
table.display tr.row_selected td {
background-color: #9FAFD1;
}
/*
* Row highlighting example
*/
tbody tr:hover, #example tbody tr td.highlighted {
background-color: #E6FF99;
}
tr:hover {
background-color: #ECFFB3;
}
tr:hover td.sorting_1 {
background-color: #DDFF75;
}
tr:hover td.sorting_2 {
background-color: #E7FF9E;
}
tr:hover td.sorting_3 {
background-color: #E2FF89;
}
/*
* KeyTable
*/
table.KeyTable td {
border: 3px solid transparent;
}
table.KeyTable td.focus {
border: 3px solid #3366FF;
}
div.box {
height: 100px;
padding: 10px;
overflow: auto;
border: 1px solid #8080FF;
background-color: #E5E5FF;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 807 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 800 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 635 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 852 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 B

File diff suppressed because it is too large Load Diff

View File

@ -1,143 +0,0 @@
/*
* File: jquery.dataTables.min.js
* Version: 1.7.6
* Author: Allan Jardine (www.sprymedia.co.uk)
* Info: www.datatables.net
*
* Copyright 2008-2011 Allan Jardine, all rights reserved.
*
* This source file is free software, under either the GPL v2 license or a
* BSD style license, as supplied with this software.
*
* This source file 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 license files for details.
*/
(function(j,ra,p){j.fn.dataTableSettings=[];var D=j.fn.dataTableSettings;j.fn.dataTableExt={};var n=j.fn.dataTableExt;n.sVersion="1.7.6";n.sErrMode="alert";n.iApiIndex=0;n.oApi={};n.afnFiltering=[];n.aoFeatures=[];n.ofnSearch={};n.afnSortData=[];n.oStdClasses={sPagePrevEnabled:"paginate_enabled_previous",sPagePrevDisabled:"paginate_disabled_previous",sPageNextEnabled:"paginate_enabled_next",sPageNextDisabled:"paginate_disabled_next",sPageJUINext:"",sPageJUIPrev:"",sPageButton:"paginate_button",sPageButtonActive:"paginate_active",
sPageButtonStaticDisabled:"paginate_button",sPageFirst:"first",sPagePrevious:"previous",sPageNext:"next",sPageLast:"last",sStripOdd:"odd",sStripEven:"even",sRowEmpty:"dataTables_empty",sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_asc_disabled",sSortableDesc:"sorting_desc_disabled",
sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sSortJUIWrapper:"",sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead",sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sFooterTH:""};n.oJUIClasses={sPagePrevEnabled:"fg-button ui-button ui-state-default ui-corner-left",sPagePrevDisabled:"fg-button ui-button ui-state-default ui-corner-left ui-state-disabled",
sPageNextEnabled:"fg-button ui-button ui-state-default ui-corner-right",sPageNextDisabled:"fg-button ui-button ui-state-default ui-corner-right ui-state-disabled",sPageJUINext:"ui-icon ui-icon-circle-arrow-e",sPageJUIPrev:"ui-icon ui-icon-circle-arrow-w",sPageButton:"fg-button ui-button ui-state-default",sPageButtonActive:"fg-button ui-button ui-state-default ui-state-disabled",sPageButtonStaticDisabled:"fg-button ui-button ui-state-default ui-state-disabled",sPageFirst:"first ui-corner-tl ui-corner-bl",
sPagePrevious:"previous",sPageNext:"next",sPageLast:"last ui-corner-tr ui-corner-br",sStripOdd:"odd",sStripEven:"even",sRowEmpty:"dataTables_empty",sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi ui-buttonset-multi paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"ui-state-default",sSortDesc:"ui-state-default",sSortable:"ui-state-default",sSortableAsc:"ui-state-default",
sSortableDesc:"ui-state-default",sSortableNone:"ui-state-default",sSortColumn:"sorting_",sSortJUIAsc:"css_right ui-icon ui-icon-triangle-1-n",sSortJUIDesc:"css_right ui-icon ui-icon-triangle-1-s",sSortJUI:"css_right ui-icon ui-icon-carat-2-n-s",sSortJUIAscAllowed:"css_right ui-icon ui-icon-carat-1-n",sSortJUIDescAllowed:"css_right ui-icon ui-icon-carat-1-s",sSortJUIWrapper:"DataTables_sort_wrapper",sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead ui-state-default",sScrollHeadInner:"dataTables_scrollHeadInner",
sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot ui-state-default",sScrollFootInner:"dataTables_scrollFootInner",sFooterTH:"ui-state-default"};n.oPagination={two_button:{fnInit:function(g,m,r){var s,w,y;if(g.bJUI){s=p.createElement("a");w=p.createElement("a");y=p.createElement("span");y.className=g.oClasses.sPageJUINext;w.appendChild(y);y=p.createElement("span");y.className=g.oClasses.sPageJUIPrev;s.appendChild(y)}else{s=p.createElement("div");w=p.createElement("div")}s.className=
g.oClasses.sPagePrevDisabled;w.className=g.oClasses.sPageNextDisabled;s.title=g.oLanguage.oPaginate.sPrevious;w.title=g.oLanguage.oPaginate.sNext;m.appendChild(s);m.appendChild(w);j(s).bind("click.DT",function(){g.oApi._fnPageChange(g,"previous")&&r(g)});j(w).bind("click.DT",function(){g.oApi._fnPageChange(g,"next")&&r(g)});j(s).bind("selectstart.DT",function(){return false});j(w).bind("selectstart.DT",function(){return false});if(g.sTableId!==""&&typeof g.aanFeatures.p=="undefined"){m.setAttribute("id",
g.sTableId+"_paginate");s.setAttribute("id",g.sTableId+"_previous");w.setAttribute("id",g.sTableId+"_next")}},fnUpdate:function(g){if(g.aanFeatures.p)for(var m=g.aanFeatures.p,r=0,s=m.length;r<s;r++)if(m[r].childNodes.length!==0){m[r].childNodes[0].className=g._iDisplayStart===0?g.oClasses.sPagePrevDisabled:g.oClasses.sPagePrevEnabled;m[r].childNodes[1].className=g.fnDisplayEnd()==g.fnRecordsDisplay()?g.oClasses.sPageNextDisabled:g.oClasses.sPageNextEnabled}}},iFullNumbersShowPages:5,full_numbers:{fnInit:function(g,
m,r){var s=p.createElement("span"),w=p.createElement("span"),y=p.createElement("span"),F=p.createElement("span"),x=p.createElement("span");s.innerHTML=g.oLanguage.oPaginate.sFirst;w.innerHTML=g.oLanguage.oPaginate.sPrevious;F.innerHTML=g.oLanguage.oPaginate.sNext;x.innerHTML=g.oLanguage.oPaginate.sLast;var u=g.oClasses;s.className=u.sPageButton+" "+u.sPageFirst;w.className=u.sPageButton+" "+u.sPagePrevious;F.className=u.sPageButton+" "+u.sPageNext;x.className=u.sPageButton+" "+u.sPageLast;m.appendChild(s);
m.appendChild(w);m.appendChild(y);m.appendChild(F);m.appendChild(x);j(s).bind("click.DT",function(){g.oApi._fnPageChange(g,"first")&&r(g)});j(w).bind("click.DT",function(){g.oApi._fnPageChange(g,"previous")&&r(g)});j(F).bind("click.DT",function(){g.oApi._fnPageChange(g,"next")&&r(g)});j(x).bind("click.DT",function(){g.oApi._fnPageChange(g,"last")&&r(g)});j("span",m).bind("mousedown.DT",function(){return false}).bind("selectstart.DT",function(){return false});if(g.sTableId!==""&&typeof g.aanFeatures.p==
"undefined"){m.setAttribute("id",g.sTableId+"_paginate");s.setAttribute("id",g.sTableId+"_first");w.setAttribute("id",g.sTableId+"_previous");F.setAttribute("id",g.sTableId+"_next");x.setAttribute("id",g.sTableId+"_last")}},fnUpdate:function(g,m){if(g.aanFeatures.p){var r=n.oPagination.iFullNumbersShowPages,s=Math.floor(r/2),w=Math.ceil(g.fnRecordsDisplay()/g._iDisplayLength),y=Math.ceil(g._iDisplayStart/g._iDisplayLength)+1,F="",x,u=g.oClasses;if(w<r){s=1;x=w}else if(y<=s){s=1;x=r}else if(y>=w-s){s=
w-r+1;x=w}else{s=y-Math.ceil(r/2)+1;x=s+r-1}for(r=s;r<=x;r++)F+=y!=r?'<span class="'+u.sPageButton+'">'+r+"</span>":'<span class="'+u.sPageButtonActive+'">'+r+"</span>";x=g.aanFeatures.p;var z,U=function(){g._iDisplayStart=(this.innerHTML*1-1)*g._iDisplayLength;m(g);return false},C=function(){return false};r=0;for(s=x.length;r<s;r++)if(x[r].childNodes.length!==0){z=j("span:eq(2)",x[r]);z.html(F);j("span",z).bind("click.DT",U).bind("mousedown.DT",C).bind("selectstart.DT",C);z=x[r].getElementsByTagName("span");
z=[z[0],z[1],z[z.length-2],z[z.length-1]];j(z).removeClass(u.sPageButton+" "+u.sPageButtonActive+" "+u.sPageButtonStaticDisabled);if(y==1){z[0].className+=" "+u.sPageButtonStaticDisabled;z[1].className+=" "+u.sPageButtonStaticDisabled}else{z[0].className+=" "+u.sPageButton;z[1].className+=" "+u.sPageButton}if(w===0||y==w||g._iDisplayLength==-1){z[2].className+=" "+u.sPageButtonStaticDisabled;z[3].className+=" "+u.sPageButtonStaticDisabled}else{z[2].className+=" "+u.sPageButton;z[3].className+=" "+
u.sPageButton}}}}}};n.oSort={"string-asc":function(g,m){g=g.toLowerCase();m=m.toLowerCase();return g<m?-1:g>m?1:0},"string-desc":function(g,m){g=g.toLowerCase();m=m.toLowerCase();return g<m?1:g>m?-1:0},"html-asc":function(g,m){g=g.replace(/<.*?>/g,"").toLowerCase();m=m.replace(/<.*?>/g,"").toLowerCase();return g<m?-1:g>m?1:0},"html-desc":function(g,m){g=g.replace(/<.*?>/g,"").toLowerCase();m=m.replace(/<.*?>/g,"").toLowerCase();return g<m?1:g>m?-1:0},"date-asc":function(g,m){g=Date.parse(g);m=Date.parse(m);
if(isNaN(g)||g==="")g=Date.parse("01/01/1970 00:00:00");if(isNaN(m)||m==="")m=Date.parse("01/01/1970 00:00:00");return g-m},"date-desc":function(g,m){g=Date.parse(g);m=Date.parse(m);if(isNaN(g)||g==="")g=Date.parse("01/01/1970 00:00:00");if(isNaN(m)||m==="")m=Date.parse("01/01/1970 00:00:00");return m-g},"numeric-asc":function(g,m){return(g=="-"||g===""?0:g*1)-(m=="-"||m===""?0:m*1)},"numeric-desc":function(g,m){return(m=="-"||m===""?0:m*1)-(g=="-"||g===""?0:g*1)}};n.aTypes=[function(g){if(g.length===
0)return"numeric";var m,r=false;m=g.charAt(0);if("0123456789-".indexOf(m)==-1)return null;for(var s=1;s<g.length;s++){m=g.charAt(s);if("0123456789.".indexOf(m)==-1)return null;if(m=="."){if(r)return null;r=true}}return"numeric"},function(g){var m=Date.parse(g);if(m!==null&&!isNaN(m)||g.length===0)return"date";return null},function(g){if(g.indexOf("<")!=-1&&g.indexOf(">")!=-1)return"html";return null}];n.fnVersionCheck=function(g){var m=function(x,u){for(;x.length<u;)x+="0";return x},r=n.sVersion.split(".");
g=g.split(".");for(var s="",w="",y=0,F=g.length;y<F;y++){s+=m(r[y],3);w+=m(g[y],3)}return parseInt(s,10)>=parseInt(w,10)};n._oExternConfig={iNextUnique:0};j.fn.dataTable=function(g){function m(){this.fnRecordsTotal=function(){return this.oFeatures.bServerSide?parseInt(this._iRecordsTotal,10):this.aiDisplayMaster.length};this.fnRecordsDisplay=function(){return this.oFeatures.bServerSide?parseInt(this._iRecordsDisplay,10):this.aiDisplay.length};this.fnDisplayEnd=function(){return this.oFeatures.bServerSide?
this.oFeatures.bPaginate===false||this._iDisplayLength==-1?this._iDisplayStart+this.aiDisplay.length:Math.min(this._iDisplayStart+this._iDisplayLength,this._iRecordsDisplay):this._iDisplayEnd};this.sInstance=this.oInstance=null;this.oFeatures={bPaginate:true,bLengthChange:true,bFilter:true,bSort:true,bInfo:true,bAutoWidth:true,bProcessing:false,bSortClasses:true,bStateSave:false,bServerSide:false};this.oScroll={sX:"",sXInner:"",sY:"",bCollapse:false,bInfinite:false,iLoadGap:100,iBarWidth:0,bAutoCss:true};
this.aanFeatures=[];this.oLanguage={sProcessing:"Processing...",sLengthMenu:"Show _MENU_ entries",sZeroRecords:"No matching records found",sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sSearch:"Search:",sUrl:"",oPaginate:{sFirst:"First",sPrevious:"Previous",sNext:"Next",sLast:"Last"},fnInfoCallback:null};this.aoData=[];this.aiDisplay=[];this.aiDisplayMaster=
[];this.aoColumns=[];this.iNextId=0;this.asDataSearch=[];this.oPreviousSearch={sSearch:"",bRegex:false,bSmart:true};this.aoPreSearchCols=[];this.aaSorting=[[0,"asc",0]];this.aaSortingFixed=null;this.asStripClasses=[];this.asDestoryStrips=[];this.sDestroyWidth=0;this.fnFooterCallback=this.fnHeaderCallback=this.fnRowCallback=null;this.aoDrawCallback=[];this.fnInitComplete=null;this.sTableId="";this.nTableWrapper=this.nTBody=this.nTFoot=this.nTHead=this.nTable=null;this.bInitialised=false;this.aoOpenRows=
[];this.sDom="lfrtip";this.sPaginationType="two_button";this.iCookieDuration=7200;this.sCookiePrefix="SpryMedia_DataTables_";this.fnCookieCallback=null;this.aoStateSave=[];this.aoStateLoad=[];this.sAjaxSource=this.oLoadedState=null;this.bAjaxDataGet=true;this.fnServerData=function(a,b,c){j.ajax({url:a,data:b,success:c,dataType:"json",cache:false,error:function(d,f){f=="parsererror"&&alert("DataTables warning: JSON data from server could not be parsed. This is caused by a JSON formatting error.")}})};
this.fnFormatNumber=function(a){if(a<1E3)return a;else{var b=a+"";a=b.split("");var c="";b=b.length;for(var d=0;d<b;d++){if(d%3===0&&d!==0)c=","+c;c=a[b-d-1]+c}}return c};this.aLengthMenu=[10,25,50,100];this.bDrawing=this.iDraw=0;this.iDrawError=-1;this._iDisplayLength=10;this._iDisplayStart=0;this._iDisplayEnd=10;this._iRecordsDisplay=this._iRecordsTotal=0;this.bJUI=false;this.oClasses=n.oStdClasses;this.bSorted=this.bFiltered=false;this.oInit=null}function r(a){return function(){var b=[A(this[n.iApiIndex])].concat(Array.prototype.slice.call(arguments));
return n.oApi[a].apply(this,b)}}function s(a){var b,c;if(a.bInitialised===false)setTimeout(function(){s(a)},200);else{sa(a);U(a);K(a,true);a.oFeatures.bAutoWidth&&$(a);b=0;for(c=a.aoColumns.length;b<c;b++)if(a.aoColumns[b].sWidth!==null)a.aoColumns[b].nTh.style.width=v(a.aoColumns[b].sWidth);if(a.oFeatures.bSort)O(a);else{a.aiDisplay=a.aiDisplayMaster.slice();E(a);C(a)}if(a.sAjaxSource!==null&&!a.oFeatures.bServerSide)a.fnServerData.call(a.oInstance,a.sAjaxSource,[],function(d){for(b=0;b<d.aaData.length;b++)u(a,
d.aaData[b]);a.iInitDisplayStart=a._iDisplayStart;if(a.oFeatures.bSort)O(a);else{a.aiDisplay=a.aiDisplayMaster.slice();E(a);C(a)}K(a,false);w(a,d)});else if(!a.oFeatures.bServerSide){K(a,false);w(a)}}}function w(a,b){a._bInitComplete=true;if(typeof a.fnInitComplete=="function")typeof b!="undefined"?a.fnInitComplete.call(a.oInstance,a,b):a.fnInitComplete.call(a.oInstance,a)}function y(a,b,c){o(a.oLanguage,b,"sProcessing");o(a.oLanguage,b,"sLengthMenu");o(a.oLanguage,b,"sEmptyTable");o(a.oLanguage,
b,"sZeroRecords");o(a.oLanguage,b,"sInfo");o(a.oLanguage,b,"sInfoEmpty");o(a.oLanguage,b,"sInfoFiltered");o(a.oLanguage,b,"sInfoPostFix");o(a.oLanguage,b,"sSearch");if(typeof b.oPaginate!="undefined"){o(a.oLanguage.oPaginate,b.oPaginate,"sFirst");o(a.oLanguage.oPaginate,b.oPaginate,"sPrevious");o(a.oLanguage.oPaginate,b.oPaginate,"sNext");o(a.oLanguage.oPaginate,b.oPaginate,"sLast")}typeof b.sEmptyTable=="undefined"&&typeof b.sZeroRecords!="undefined"&&o(a.oLanguage,b,"sZeroRecords","sEmptyTable");
c&&s(a)}function F(a,b){a.aoColumns[a.aoColumns.length++]={sType:null,_bAutoType:true,bVisible:true,bSearchable:true,bSortable:true,asSorting:["asc","desc"],sSortingClass:a.oClasses.sSortable,sSortingClassJUI:a.oClasses.sSortJUI,sTitle:b?b.innerHTML:"",sName:"",sWidth:null,sWidthOrig:null,sClass:null,fnRender:null,bUseRendered:true,iDataSort:a.aoColumns.length-1,sSortDataType:"std",nTh:b?b:p.createElement("th"),nTf:null,anThExtra:[],anTfExtra:[]};b=a.aoColumns.length-1;if(typeof a.aoPreSearchCols[b]==
"undefined"||a.aoPreSearchCols[b]===null)a.aoPreSearchCols[b]={sSearch:"",bRegex:false,bSmart:true};else{if(typeof a.aoPreSearchCols[b].bRegex=="undefined")a.aoPreSearchCols[b].bRegex=true;if(typeof a.aoPreSearchCols[b].bSmart=="undefined")a.aoPreSearchCols[b].bSmart=true}x(a,b,null)}function x(a,b,c){b=a.aoColumns[b];if(typeof c!="undefined"&&c!==null){if(typeof c.sType!="undefined"){b.sType=c.sType;b._bAutoType=false}o(b,c,"bVisible");o(b,c,"bSearchable");o(b,c,"bSortable");o(b,c,"sTitle");o(b,
c,"sName");o(b,c,"sWidth");o(b,c,"sWidth","sWidthOrig");o(b,c,"sClass");o(b,c,"fnRender");o(b,c,"bUseRendered");o(b,c,"iDataSort");o(b,c,"asSorting");o(b,c,"sSortDataType")}if(!a.oFeatures.bSort)b.bSortable=false;if(!b.bSortable||j.inArray("asc",b.asSorting)==-1&&j.inArray("desc",b.asSorting)==-1){b.sSortingClass=a.oClasses.sSortableNone;b.sSortingClassJUI=""}else if(j.inArray("asc",b.asSorting)!=-1&&j.inArray("desc",b.asSorting)==-1){b.sSortingClass=a.oClasses.sSortableAsc;b.sSortingClassJUI=a.oClasses.sSortJUIAscAllowed}else if(j.inArray("asc",
b.asSorting)==-1&&j.inArray("desc",b.asSorting)!=-1){b.sSortingClass=a.oClasses.sSortableDesc;b.sSortingClassJUI=a.oClasses.sSortJUIDescAllowed}}function u(a,b){if(b.length!=a.aoColumns.length&&a.iDrawError!=a.iDraw){H(a,0,"Added data (size "+b.length+") does not match known number of columns ("+a.aoColumns.length+")");a.iDrawError=a.iDraw;return-1}b=b.slice();var c=a.aoData.length;a.aoData.push({nTr:p.createElement("tr"),_iId:a.iNextId++,_aData:b,_anHidden:[],_sRowStripe:""});for(var d,f,e=0;e<b.length;e++){d=
p.createElement("td");if(b[e]===null)b[e]="";if(typeof a.aoColumns[e].fnRender=="function"){f=a.aoColumns[e].fnRender({iDataRow:c,iDataColumn:e,aData:b,oSettings:a});d.innerHTML=f;if(a.aoColumns[e].bUseRendered)a.aoData[c]._aData[e]=f}else d.innerHTML=b[e];if(typeof b[e]!="string")b[e]+="";b[e]=j.trim(b[e]);if(a.aoColumns[e].sClass!==null)d.className=a.aoColumns[e].sClass;if(a.aoColumns[e]._bAutoType&&a.aoColumns[e].sType!="string"){f=aa(a.aoData[c]._aData[e]);if(a.aoColumns[e].sType===null)a.aoColumns[e].sType=
f;else if(a.aoColumns[e].sType!=f)a.aoColumns[e].sType="string"}if(a.aoColumns[e].bVisible){a.aoData[c].nTr.appendChild(d);a.aoData[c]._anHidden[e]=null}else a.aoData[c]._anHidden[e]=d}a.aiDisplayMaster.push(c);return c}function z(a){var b,c,d,f,e,i,h,k;if(a.sAjaxSource===null){h=a.nTBody.childNodes;b=0;for(c=h.length;b<c;b++)if(h[b].nodeName.toUpperCase()=="TR"){i=a.aoData.length;a.aoData.push({nTr:h[b],_iId:a.iNextId++,_aData:[],_anHidden:[],_sRowStripe:""});a.aiDisplayMaster.push(i);k=a.aoData[i]._aData;
i=h[b].childNodes;d=e=0;for(f=i.length;d<f;d++)if(i[d].nodeName.toUpperCase()=="TD"){k[e]=j.trim(i[d].innerHTML);e++}}}h=R(a);i=[];b=0;for(c=h.length;b<c;b++){d=0;for(f=h[b].childNodes.length;d<f;d++){e=h[b].childNodes[d];e.nodeName.toUpperCase()=="TD"&&i.push(e)}}i.length!=h.length*a.aoColumns.length&&H(a,1,"Unexpected number of TD elements. Expected "+h.length*a.aoColumns.length+" and got "+i.length+". DataTables does not support rowspan / colspan in the table body, and there must be one cell for each row/column combination.");
h=0;for(d=a.aoColumns.length;h<d;h++){if(a.aoColumns[h].sTitle===null)a.aoColumns[h].sTitle=a.aoColumns[h].nTh.innerHTML;f=a.aoColumns[h]._bAutoType;e=typeof a.aoColumns[h].fnRender=="function";k=a.aoColumns[h].sClass!==null;var l=a.aoColumns[h].bVisible,q,t;if(f||e||k||!l){b=0;for(c=a.aoData.length;b<c;b++){q=i[b*d+h];if(f)if(a.aoColumns[h].sType!="string"){t=aa(a.aoData[b]._aData[h]);if(a.aoColumns[h].sType===null)a.aoColumns[h].sType=t;else if(a.aoColumns[h].sType!=t)a.aoColumns[h].sType="string"}if(e){t=
a.aoColumns[h].fnRender({iDataRow:b,iDataColumn:h,aData:a.aoData[b]._aData,oSettings:a});q.innerHTML=t;if(a.aoColumns[h].bUseRendered)a.aoData[b]._aData[h]=t}if(k)q.className+=" "+a.aoColumns[h].sClass;if(l)a.aoData[b]._anHidden[h]=null;else{a.aoData[b]._anHidden[h]=q;q.parentNode.removeChild(q)}}}}}function U(a){var b,c,d,f,e,i=a.nTHead.getElementsByTagName("tr"),h=0,k;if(a.nTHead.getElementsByTagName("th").length!==0){b=0;for(d=a.aoColumns.length;b<d;b++){c=a.aoColumns[b].nTh;a.aoColumns[b].sClass!==
null&&j(c).addClass(a.aoColumns[b].sClass);f=1;for(e=i.length;f<e;f++){k=j(i[f]).children();a.aoColumns[b].anThExtra.push(k[b-h]);a.aoColumns[b].bVisible||i[f].removeChild(k[b-h])}if(a.aoColumns[b].bVisible){if(a.aoColumns[b].sTitle!=c.innerHTML)c.innerHTML=a.aoColumns[b].sTitle}else{c.parentNode.removeChild(c);h++}}}else{f=p.createElement("tr");b=0;for(d=a.aoColumns.length;b<d;b++){c=a.aoColumns[b].nTh;c.innerHTML=a.aoColumns[b].sTitle;a.aoColumns[b].sClass!==null&&j(c).addClass(a.aoColumns[b].sClass);
a.aoColumns[b].bVisible&&f.appendChild(c)}j(a.nTHead).html("")[0].appendChild(f)}if(a.bJUI){b=0;for(d=a.aoColumns.length;b<d;b++){c=a.aoColumns[b].nTh;f=p.createElement("div");f.className=a.oClasses.sSortJUIWrapper;j(c).contents().appendTo(f);f.appendChild(p.createElement("span"));c.appendChild(f)}}d=function(){this.onselectstart=function(){return false};return false};if(a.oFeatures.bSort)for(b=0;b<a.aoColumns.length;b++)if(a.aoColumns[b].bSortable!==false){ba(a,a.aoColumns[b].nTh,b);j(a.aoColumns[b].nTh).bind("mousedown.DT",
d)}else j(a.aoColumns[b].nTh).addClass(a.oClasses.sSortableNone);if(a.nTFoot!==null){h=0;i=a.nTFoot.getElementsByTagName("tr");c=i[0].getElementsByTagName("th");b=0;for(d=c.length;b<d;b++)if(typeof a.aoColumns[b]!="undefined"){a.aoColumns[b].nTf=c[b-h];if(a.oClasses.sFooterTH!=="")a.aoColumns[b].nTf.className+=" "+a.oClasses.sFooterTH;f=1;for(e=i.length;f<e;f++){k=j(i[f]).children();a.aoColumns[b].anTfExtra.push(k[b-h]);a.aoColumns[b].bVisible||i[f].removeChild(k[b-h])}if(!a.aoColumns[b].bVisible){c[b-
h].parentNode.removeChild(c[b-h]);h++}}}}function C(a){var b,c,d=[],f=0,e=false;b=a.asStripClasses.length;c=a.aoOpenRows.length;a.bDrawing=true;if(typeof a.iInitDisplayStart!="undefined"&&a.iInitDisplayStart!=-1){a._iDisplayStart=a.oFeatures.bServerSide?a.iInitDisplayStart:a.iInitDisplayStart>=a.fnRecordsDisplay()?0:a.iInitDisplayStart;a.iInitDisplayStart=-1;E(a)}if(!(!a.bDestroying&&a.oFeatures.bServerSide&&!ta(a))){a.oFeatures.bServerSide||a.iDraw++;if(a.aiDisplay.length!==0){var i=a._iDisplayStart,
h=a._iDisplayEnd;if(a.oFeatures.bServerSide){i=0;h=a.aoData.length}for(i=i;i<h;i++){var k=a.aoData[a.aiDisplay[i]],l=k.nTr;if(b!==0){var q=a.asStripClasses[f%b];if(k._sRowStripe!=q){j(l).removeClass(k._sRowStripe).addClass(q);k._sRowStripe=q}}if(typeof a.fnRowCallback=="function"){l=a.fnRowCallback.call(a.oInstance,l,a.aoData[a.aiDisplay[i]]._aData,f,i);if(!l&&!e){H(a,0,"A node was not returned by fnRowCallback");e=true}}d.push(l);f++;if(c!==0)for(k=0;k<c;k++)l==a.aoOpenRows[k].nParent&&d.push(a.aoOpenRows[k].nTr)}}else{d[0]=
p.createElement("tr");if(typeof a.asStripClasses[0]!="undefined")d[0].className=a.asStripClasses[0];e=p.createElement("td");e.setAttribute("valign","top");e.colSpan=S(a);e.className=a.oClasses.sRowEmpty;e.innerHTML=typeof a.oLanguage.sEmptyTable!="undefined"&&a.fnRecordsTotal()===0?a.oLanguage.sEmptyTable:a.oLanguage.sZeroRecords.replace("_MAX_",a.fnFormatNumber(a.fnRecordsTotal()));d[f].appendChild(e)}typeof a.fnHeaderCallback=="function"&&a.fnHeaderCallback.call(a.oInstance,j(">tr",a.nTHead)[0],
V(a),a._iDisplayStart,a.fnDisplayEnd(),a.aiDisplay);typeof a.fnFooterCallback=="function"&&a.fnFooterCallback.call(a.oInstance,j(">tr",a.nTFoot)[0],V(a),a._iDisplayStart,a.fnDisplayEnd(),a.aiDisplay);f=p.createDocumentFragment();b=p.createDocumentFragment();if(a.nTBody){e=a.nTBody.parentNode;b.appendChild(a.nTBody);if(!a.oScroll.bInfinite||!a._bInitComplete||a.bSorted||a.bFiltered){c=a.nTBody.childNodes;for(b=c.length-1;b>=0;b--)c[b].parentNode.removeChild(c[b])}b=0;for(c=d.length;b<c;b++)f.appendChild(d[b]);
a.nTBody.appendChild(f);e!==null&&e.appendChild(a.nTBody)}for(b=a.aoDrawCallback.length-1;b>=0;b--)a.aoDrawCallback[b].fn.call(a.oInstance,a);a.bSorted=false;a.bFiltered=false;a.bDrawing=false;if(a.oFeatures.bServerSide){K(a,false);typeof a._bInitComplete=="undefined"&&w(a)}}}function W(a){if(a.oFeatures.bSort)O(a,a.oPreviousSearch);else if(a.oFeatures.bFilter)P(a,a.oPreviousSearch);else{E(a);C(a)}}function ta(a){if(a.bAjaxDataGet){K(a,true);var b=a.aoColumns.length,c=[],d;a.iDraw++;c.push({name:"sEcho",
value:a.iDraw});c.push({name:"iColumns",value:b});c.push({name:"sColumns",value:ca(a)});c.push({name:"iDisplayStart",value:a._iDisplayStart});c.push({name:"iDisplayLength",value:a.oFeatures.bPaginate!==false?a._iDisplayLength:-1});if(a.oFeatures.bFilter!==false){c.push({name:"sSearch",value:a.oPreviousSearch.sSearch});c.push({name:"bRegex",value:a.oPreviousSearch.bRegex});for(d=0;d<b;d++){c.push({name:"sSearch_"+d,value:a.aoPreSearchCols[d].sSearch});c.push({name:"bRegex_"+d,value:a.aoPreSearchCols[d].bRegex});
c.push({name:"bSearchable_"+d,value:a.aoColumns[d].bSearchable})}}if(a.oFeatures.bSort!==false){var f=a.aaSortingFixed!==null?a.aaSortingFixed.length:0,e=a.aaSorting.length;c.push({name:"iSortingCols",value:f+e});for(d=0;d<f;d++){c.push({name:"iSortCol_"+d,value:a.aaSortingFixed[d][0]});c.push({name:"sSortDir_"+d,value:a.aaSortingFixed[d][1]})}for(d=0;d<e;d++){c.push({name:"iSortCol_"+(d+f),value:a.aaSorting[d][0]});c.push({name:"sSortDir_"+(d+f),value:a.aaSorting[d][1]})}for(d=0;d<b;d++)c.push({name:"bSortable_"+
d,value:a.aoColumns[d].bSortable})}a.fnServerData.call(a.oInstance,a.sAjaxSource,c,function(i){ua(a,i)});return false}else return true}function ua(a,b){if(typeof b.sEcho!="undefined")if(b.sEcho*1<a.iDraw)return;else a.iDraw=b.sEcho*1;if(!a.oScroll.bInfinite||a.oScroll.bInfinite&&(a.bSorted||a.bFiltered))da(a);a._iRecordsTotal=b.iTotalRecords;a._iRecordsDisplay=b.iTotalDisplayRecords;var c=ca(a);if(c=typeof b.sColumns!="undefined"&&c!==""&&b.sColumns!=c)var d=va(a,b.sColumns);for(var f=0,e=b.aaData.length;f<
e;f++)if(c){for(var i=[],h=0,k=a.aoColumns.length;h<k;h++)i.push(b.aaData[f][d[h]]);u(a,i)}else u(a,b.aaData[f]);a.aiDisplay=a.aiDisplayMaster.slice();a.bAjaxDataGet=false;C(a);a.bAjaxDataGet=true;K(a,false)}function sa(a){var b=p.createElement("div");a.nTable.parentNode.insertBefore(b,a.nTable);a.nTableWrapper=p.createElement("div");a.nTableWrapper.className=a.oClasses.sWrapper;a.sTableId!==""&&a.nTableWrapper.setAttribute("id",a.sTableId+"_wrapper");for(var c=a.nTableWrapper,d=a.sDom.split(""),
f,e,i,h,k,l,q,t=0;t<d.length;t++){e=0;i=d[t];if(i=="<"){h=p.createElement("div");k=d[t+1];if(k=="'"||k=='"'){l="";for(q=2;d[t+q]!=k;){l+=d[t+q];q++}if(l=="H")l="fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix";else if(l=="F")l="fg-toolbar ui-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix";if(l.indexOf(".")!=-1){k=l.split(".");h.setAttribute("id",k[0].substr(1,k[0].length-1));h.className=k[1]}else if(l.charAt(0)=="#")h.setAttribute("id",l.substr(1,
l.length-1));else h.className=l;t+=q}c.appendChild(h);c=h}else if(i==">")c=c.parentNode;else if(i=="l"&&a.oFeatures.bPaginate&&a.oFeatures.bLengthChange){f=wa(a);e=1}else if(i=="f"&&a.oFeatures.bFilter){f=xa(a);e=1}else if(i=="r"&&a.oFeatures.bProcessing){f=ya(a);e=1}else if(i=="t"){f=za(a);e=1}else if(i=="i"&&a.oFeatures.bInfo){f=Aa(a);e=1}else if(i=="p"&&a.oFeatures.bPaginate){f=Ba(a);e=1}else if(n.aoFeatures.length!==0){h=n.aoFeatures;q=0;for(k=h.length;q<k;q++)if(i==h[q].cFeature){if(f=h[q].fnInit(a))e=
1;break}}if(e==1&&f!==null){if(typeof a.aanFeatures[i]!="object")a.aanFeatures[i]=[];a.aanFeatures[i].push(f);c.appendChild(f)}}b.parentNode.replaceChild(a.nTableWrapper,b)}function za(a){if(a.oScroll.sX===""&&a.oScroll.sY==="")return a.nTable;var b=p.createElement("div"),c=p.createElement("div"),d=p.createElement("div"),f=p.createElement("div"),e=p.createElement("div"),i=p.createElement("div"),h=a.nTable.cloneNode(false),k=a.nTable.cloneNode(false),l=a.nTable.getElementsByTagName("thead")[0],q=a.nTable.getElementsByTagName("tfoot").length===
0?null:a.nTable.getElementsByTagName("tfoot")[0],t=typeof g.bJQueryUI!="undefined"&&g.bJQueryUI?n.oJUIClasses:n.oStdClasses;c.appendChild(d);e.appendChild(i);f.appendChild(a.nTable);b.appendChild(c);b.appendChild(f);d.appendChild(h);h.appendChild(l);if(q!==null){b.appendChild(e);i.appendChild(k);k.appendChild(q)}b.className=t.sScrollWrapper;c.className=t.sScrollHead;d.className=t.sScrollHeadInner;f.className=t.sScrollBody;e.className=t.sScrollFoot;i.className=t.sScrollFootInner;if(a.oScroll.bAutoCss){c.style.overflow=
"hidden";c.style.position="relative";e.style.overflow="hidden";f.style.overflow="auto"}c.style.border="0";c.style.width="100%";e.style.border="0";d.style.width="150%";h.removeAttribute("id");h.style.marginLeft="0";a.nTable.style.marginLeft="0";if(q!==null){k.removeAttribute("id");k.style.marginLeft="0"}d=j(">caption",a.nTable);i=0;for(k=d.length;i<k;i++)h.appendChild(d[i]);if(a.oScroll.sX!==""){c.style.width=v(a.oScroll.sX);f.style.width=v(a.oScroll.sX);if(q!==null)e.style.width=v(a.oScroll.sX);j(f).scroll(function(){c.scrollLeft=
this.scrollLeft;if(q!==null)e.scrollLeft=this.scrollLeft})}if(a.oScroll.sY!=="")f.style.height=v(a.oScroll.sY);a.aoDrawCallback.push({fn:Ca,sName:"scrolling"});a.oScroll.bInfinite&&j(f).scroll(function(){if(!a.bDrawing)if(j(this).scrollTop()+j(this).height()>j(a.nTable).height()-a.oScroll.iLoadGap)if(a.fnDisplayEnd()<a.fnRecordsDisplay()){ea(a,"next");E(a);C(a)}});a.nScrollHead=c;a.nScrollFoot=e;return b}function Ca(a){var b=a.nScrollHead.getElementsByTagName("div")[0],c=b.getElementsByTagName("table")[0],
d=a.nTable.parentNode,f,e,i,h,k,l,q,t,G=[];i=a.nTable.getElementsByTagName("thead");i.length>0&&a.nTable.removeChild(i[0]);if(a.nTFoot!==null){k=a.nTable.getElementsByTagName("tfoot");k.length>0&&a.nTable.removeChild(k[0])}i=a.nTHead.cloneNode(true);a.nTable.insertBefore(i,a.nTable.childNodes[0]);if(a.nTFoot!==null){k=a.nTFoot.cloneNode(true);a.nTable.insertBefore(k,a.nTable.childNodes[1])}var J=fa(i);f=0;for(e=J.length;f<e;f++){q=ga(a,f);J[f].style.width=a.aoColumns[q].sWidth}a.nTFoot!==null&&L(function(B){B.style.width=
""},k.getElementsByTagName("tr"));f=j(a.nTable).outerWidth();if(a.oScroll.sX===""){a.nTable.style.width="100%";if(j.browser.msie&&j.browser.version<=7)a.nTable.style.width=v(j(a.nTable).outerWidth()-a.oScroll.iBarWidth)}else if(a.oScroll.sXInner!=="")a.nTable.style.width=v(a.oScroll.sXInner);else if(f==j(d).width()&&j(d).height()<j(a.nTable).height()){a.nTable.style.width=v(f-a.oScroll.iBarWidth);if(j(a.nTable).outerWidth()>f-a.oScroll.iBarWidth)a.nTable.style.width=v(f)}else a.nTable.style.width=
v(f);f=j(a.nTable).outerWidth();e=a.nTHead.getElementsByTagName("tr");i=i.getElementsByTagName("tr");L(function(B,I){l=B.style;l.paddingTop="0";l.paddingBottom="0";l.borderTopWidth="0";l.borderBottomWidth="0";l.height=0;t=j(B).width();I.style.width=v(t);G.push(t)},i,e);j(i).height(0);if(a.nTFoot!==null){h=k.getElementsByTagName("tr");k=a.nTFoot.getElementsByTagName("tr");L(function(B,I){l=B.style;l.paddingTop="0";l.paddingBottom="0";l.borderTopWidth="0";l.borderBottomWidth="0";l.height=0;t=j(B).width();
I.style.width=v(t);G.push(t)},h,k);j(h).height(0)}L(function(B){B.innerHTML="";B.style.width=v(G.shift())},i);a.nTFoot!==null&&L(function(B){B.innerHTML="";B.style.width=v(G.shift())},h);if(j(a.nTable).outerWidth()<f)if(a.oScroll.sX==="")H(a,1,"The table cannot fit into the current element which will cause column misalignment. It is suggested that you enable x-scrolling or increase the width the table has in which to be drawn");else a.oScroll.sXInner!==""&&H(a,1,"The table cannot fit into the current element which will cause column misalignment. It is suggested that you increase the sScrollXInner property to allow it to draw in a larger area, or simply remove that parameter to allow automatic calculation");
if(a.oScroll.sY==="")if(j.browser.msie&&j.browser.version<=7)d.style.height=v(a.nTable.offsetHeight+a.oScroll.iBarWidth);if(a.oScroll.sY!==""&&a.oScroll.bCollapse){d.style.height=v(a.oScroll.sY);h=a.oScroll.sX!==""&&a.nTable.offsetWidth>d.offsetWidth?a.oScroll.iBarWidth:0;if(a.nTable.offsetHeight<d.offsetHeight)d.style.height=v(j(a.nTable).height()+h)}h=j(a.nTable).outerWidth();c.style.width=v(h);b.style.width=v(h+a.oScroll.iBarWidth);if(a.nTFoot!==null){b=a.nScrollFoot.getElementsByTagName("div")[0];
c=b.getElementsByTagName("table")[0];b.style.width=v(a.nTable.offsetWidth+a.oScroll.iBarWidth);c.style.width=v(a.nTable.offsetWidth)}if(a.bSorted||a.bFiltered)d.scrollTop=0}function X(a){if(a.oFeatures.bAutoWidth===false)return false;$(a);for(var b=0,c=a.aoColumns.length;b<c;b++)a.aoColumns[b].nTh.style.width=a.aoColumns[b].sWidth}function xa(a){var b=p.createElement("div");a.sTableId!==""&&typeof a.aanFeatures.f=="undefined"&&b.setAttribute("id",a.sTableId+"_filter");b.className=a.oClasses.sFilter;
b.innerHTML=a.oLanguage.sSearch+(a.oLanguage.sSearch===""?"":" ")+'<input type="text" />';var c=j("input",b);c.val(a.oPreviousSearch.sSearch.replace('"',"&quot;"));c.bind("keyup.DT",function(){for(var d=a.aanFeatures.f,f=0,e=d.length;f<e;f++)d[f]!=this.parentNode&&j("input",d[f]).val(this.value);this.value!=a.oPreviousSearch.sSearch&&P(a,{sSearch:this.value,bRegex:a.oPreviousSearch.bRegex,bSmart:a.oPreviousSearch.bSmart})});c.bind("keypress.DT",function(d){if(d.keyCode==13)return false});return b}
function P(a,b,c){Da(a,b.sSearch,c,b.bRegex,b.bSmart);for(b=0;b<a.aoPreSearchCols.length;b++)Ea(a,a.aoPreSearchCols[b].sSearch,b,a.aoPreSearchCols[b].bRegex,a.aoPreSearchCols[b].bSmart);n.afnFiltering.length!==0&&Fa(a);a.bFiltered=true;a._iDisplayStart=0;E(a);C(a);ha(a,0)}function Fa(a){for(var b=n.afnFiltering,c=0,d=b.length;c<d;c++)for(var f=0,e=0,i=a.aiDisplay.length;e<i;e++){var h=a.aiDisplay[e-f];if(!b[c](a,a.aoData[h]._aData,h)){a.aiDisplay.splice(e-f,1);f++}}}function Ea(a,b,c,d,f){if(b!==
""){var e=0;b=ia(b,d,f);for(d=a.aiDisplay.length-1;d>=0;d--){f=ja(a.aoData[a.aiDisplay[d]]._aData[c],a.aoColumns[c].sType);if(!b.test(f)){a.aiDisplay.splice(d,1);e++}}}}function Da(a,b,c,d,f){var e=ia(b,d,f);if(typeof c=="undefined"||c===null)c=0;if(n.afnFiltering.length!==0)c=1;if(b.length<=0){a.aiDisplay.splice(0,a.aiDisplay.length);a.aiDisplay=a.aiDisplayMaster.slice()}else if(a.aiDisplay.length==a.aiDisplayMaster.length||a.oPreviousSearch.sSearch.length>b.length||c==1||b.indexOf(a.oPreviousSearch.sSearch)!==
0){a.aiDisplay.splice(0,a.aiDisplay.length);ha(a,1);for(c=0;c<a.aiDisplayMaster.length;c++)e.test(a.asDataSearch[c])&&a.aiDisplay.push(a.aiDisplayMaster[c])}else{var i=0;for(c=0;c<a.asDataSearch.length;c++)if(!e.test(a.asDataSearch[c])){a.aiDisplay.splice(c-i,1);i++}}a.oPreviousSearch.sSearch=b;a.oPreviousSearch.bRegex=d;a.oPreviousSearch.bSmart=f}function ha(a,b){a.asDataSearch.splice(0,a.asDataSearch.length);b=typeof b!="undefined"&&b==1?a.aiDisplayMaster:a.aiDisplay;for(var c=0,d=b.length;c<d;c++)a.asDataSearch[c]=
ka(a,a.aoData[b[c]]._aData)}function ka(a,b){for(var c="",d=p.createElement("div"),f=0,e=a.aoColumns.length;f<e;f++)if(a.aoColumns[f].bSearchable)c+=ja(b[f],a.aoColumns[f].sType)+" ";if(c.indexOf("&")!==-1){d.innerHTML=c;c=d.textContent?d.textContent:d.innerText;c=c.replace(/\n/g," ").replace(/\r/g,"")}return c}function ia(a,b,c){if(c){a=b?a.split(" "):la(a).split(" ");a="^(?=.*?"+a.join(")(?=.*?")+").*$";return new RegExp(a,"i")}else{a=b?a:la(a);return new RegExp(a,"i")}}function ja(a,b){if(typeof n.ofnSearch[b]==
"function")return n.ofnSearch[b](a);else if(b=="html")return a.replace(/\n/g," ").replace(/<.*?>/g,"");else if(typeof a=="string")return a.replace(/\n/g," ");return a}function O(a,b){var c,d,f,e,i,h,k=[],l=[],q=n.oSort,t=a.aoData,G=a.aoColumns;if(!a.oFeatures.bServerSide&&(a.aaSorting.length!==0||a.aaSortingFixed!==null)){k=a.aaSortingFixed!==null?a.aaSortingFixed.concat(a.aaSorting):a.aaSorting.slice();for(f=0;f<k.length;f++){e=k[f][0];i=M(a,e);h=a.aoColumns[e].sSortDataType;if(typeof n.afnSortData[h]!=
"undefined"){var J=n.afnSortData[h](a,e,i);i=0;for(h=t.length;i<h;i++)t[i]._aData[e]=J[i]}}f=0;for(e=a.aiDisplayMaster.length;f<e;f++)l[a.aiDisplayMaster[f]]=f;var B=k.length;a.aiDisplayMaster.sort(function(I,Y){var N;for(f=0;f<B;f++){c=G[k[f][0]].iDataSort;d=G[c].sType;N=q[d+"-"+k[f][1]](t[I]._aData[c],t[Y]._aData[c]);if(N!==0)return N}return q["numeric-asc"](l[I],l[Y])})}if(typeof b=="undefined"||b)T(a);a.bSorted=true;if(a.oFeatures.bFilter)P(a,a.oPreviousSearch,1);else{a.aiDisplay=a.aiDisplayMaster.slice();
a._iDisplayStart=0;E(a);C(a)}}function ba(a,b,c,d){j(b).bind("click.DT",function(f){if(a.aoColumns[c].bSortable!==false){var e=function(){var i,h;if(f.shiftKey){for(var k=false,l=0;l<a.aaSorting.length;l++)if(a.aaSorting[l][0]==c){k=true;i=a.aaSorting[l][0];h=a.aaSorting[l][2]+1;if(typeof a.aoColumns[i].asSorting[h]=="undefined")a.aaSorting.splice(l,1);else{a.aaSorting[l][1]=a.aoColumns[i].asSorting[h];a.aaSorting[l][2]=h}break}k===false&&a.aaSorting.push([c,a.aoColumns[c].asSorting[0],0])}else if(a.aaSorting.length==
1&&a.aaSorting[0][0]==c){i=a.aaSorting[0][0];h=a.aaSorting[0][2]+1;if(typeof a.aoColumns[i].asSorting[h]=="undefined")h=0;a.aaSorting[0][1]=a.aoColumns[i].asSorting[h];a.aaSorting[0][2]=h}else{a.aaSorting.splice(0,a.aaSorting.length);a.aaSorting.push([c,a.aoColumns[c].asSorting[0],0])}O(a)};if(a.oFeatures.bProcessing){K(a,true);setTimeout(function(){e();a.oFeatures.bServerSide||K(a,false)},0)}else e();typeof d=="function"&&d(a)}})}function T(a){var b,c,d,f,e,i=a.aoColumns.length,h=a.oClasses;for(b=
0;b<i;b++)a.aoColumns[b].bSortable&&j(a.aoColumns[b].nTh).removeClass(h.sSortAsc+" "+h.sSortDesc+" "+a.aoColumns[b].sSortingClass);f=a.aaSortingFixed!==null?a.aaSortingFixed.concat(a.aaSorting):a.aaSorting.slice();for(b=0;b<a.aoColumns.length;b++)if(a.aoColumns[b].bSortable){e=a.aoColumns[b].sSortingClass;d=-1;for(c=0;c<f.length;c++)if(f[c][0]==b){e=f[c][1]=="asc"?h.sSortAsc:h.sSortDesc;d=c;break}j(a.aoColumns[b].nTh).addClass(e);if(a.bJUI){c=j("span",a.aoColumns[b].nTh);c.removeClass(h.sSortJUIAsc+
" "+h.sSortJUIDesc+" "+h.sSortJUI+" "+h.sSortJUIAscAllowed+" "+h.sSortJUIDescAllowed);c.addClass(d==-1?a.aoColumns[b].sSortingClassJUI:f[d][1]=="asc"?h.sSortJUIAsc:h.sSortJUIDesc)}}else j(a.aoColumns[b].nTh).addClass(a.aoColumns[b].sSortingClass);e=h.sSortColumn;if(a.oFeatures.bSort&&a.oFeatures.bSortClasses){d=Z(a);if(d.length>=i)for(b=0;b<i;b++)if(d[b].className.indexOf(e+"1")!=-1){c=0;for(a=d.length/i;c<a;c++)d[i*c+b].className=j.trim(d[i*c+b].className.replace(e+"1",""))}else if(d[b].className.indexOf(e+
"2")!=-1){c=0;for(a=d.length/i;c<a;c++)d[i*c+b].className=j.trim(d[i*c+b].className.replace(e+"2",""))}else if(d[b].className.indexOf(e+"3")!=-1){c=0;for(a=d.length/i;c<a;c++)d[i*c+b].className=j.trim(d[i*c+b].className.replace(" "+e+"3",""))}h=1;var k;for(b=0;b<f.length;b++){k=parseInt(f[b][0],10);c=0;for(a=d.length/i;c<a;c++)d[i*c+k].className+=" "+e+h;h<3&&h++}}}function Ba(a){if(a.oScroll.bInfinite)return null;var b=p.createElement("div");b.className=a.oClasses.sPaging+a.sPaginationType;n.oPagination[a.sPaginationType].fnInit(a,
b,function(c){E(c);C(c)});typeof a.aanFeatures.p=="undefined"&&a.aoDrawCallback.push({fn:function(c){n.oPagination[c.sPaginationType].fnUpdate(c,function(d){E(d);C(d)})},sName:"pagination"});return b}function ea(a,b){var c=a._iDisplayStart;if(b=="first")a._iDisplayStart=0;else if(b=="previous"){a._iDisplayStart=a._iDisplayLength>=0?a._iDisplayStart-a._iDisplayLength:0;if(a._iDisplayStart<0)a._iDisplayStart=0}else if(b=="next")if(a._iDisplayLength>=0){if(a._iDisplayStart+a._iDisplayLength<a.fnRecordsDisplay())a._iDisplayStart+=
a._iDisplayLength}else a._iDisplayStart=0;else if(b=="last")if(a._iDisplayLength>=0){b=parseInt((a.fnRecordsDisplay()-1)/a._iDisplayLength,10)+1;a._iDisplayStart=(b-1)*a._iDisplayLength}else a._iDisplayStart=0;else H(a,0,"Unknown paging action: "+b);return c!=a._iDisplayStart}function Aa(a){var b=p.createElement("div");b.className=a.oClasses.sInfo;if(typeof a.aanFeatures.i=="undefined"){a.aoDrawCallback.push({fn:Ga,sName:"information"});a.sTableId!==""&&b.setAttribute("id",a.sTableId+"_info")}return b}
function Ga(a){if(!(!a.oFeatures.bInfo||a.aanFeatures.i.length===0)){var b=a._iDisplayStart+1,c=a.fnDisplayEnd(),d=a.fnRecordsTotal(),f=a.fnRecordsDisplay(),e=a.fnFormatNumber(b),i=a.fnFormatNumber(c),h=a.fnFormatNumber(d),k=a.fnFormatNumber(f);if(a.oScroll.bInfinite)e=a.fnFormatNumber(1);e=a.fnRecordsDisplay()===0&&a.fnRecordsDisplay()==a.fnRecordsTotal()?a.oLanguage.sInfoEmpty+a.oLanguage.sInfoPostFix:a.fnRecordsDisplay()===0?a.oLanguage.sInfoEmpty+" "+a.oLanguage.sInfoFiltered.replace("_MAX_",
h)+a.oLanguage.sInfoPostFix:a.fnRecordsDisplay()==a.fnRecordsTotal()?a.oLanguage.sInfo.replace("_START_",e).replace("_END_",i).replace("_TOTAL_",k)+a.oLanguage.sInfoPostFix:a.oLanguage.sInfo.replace("_START_",e).replace("_END_",i).replace("_TOTAL_",k)+" "+a.oLanguage.sInfoFiltered.replace("_MAX_",a.fnFormatNumber(a.fnRecordsTotal()))+a.oLanguage.sInfoPostFix;if(a.oLanguage.fnInfoCallback!==null)e=a.oLanguage.fnInfoCallback(a,b,c,d,f,e);a=a.aanFeatures.i;b=0;for(c=a.length;b<c;b++)j(a[b]).html(e)}}
function wa(a){if(a.oScroll.bInfinite)return null;var b='<select size="1" '+(a.sTableId===""?"":'name="'+a.sTableId+'_length"')+">",c,d;if(a.aLengthMenu.length==2&&typeof a.aLengthMenu[0]=="object"&&typeof a.aLengthMenu[1]=="object"){c=0;for(d=a.aLengthMenu[0].length;c<d;c++)b+='<option value="'+a.aLengthMenu[0][c]+'">'+a.aLengthMenu[1][c]+"</option>"}else{c=0;for(d=a.aLengthMenu.length;c<d;c++)b+='<option value="'+a.aLengthMenu[c]+'">'+a.aLengthMenu[c]+"</option>"}b+="</select>";var f=p.createElement("div");
a.sTableId!==""&&typeof a.aanFeatures.l=="undefined"&&f.setAttribute("id",a.sTableId+"_length");f.className=a.oClasses.sLength;f.innerHTML=a.oLanguage.sLengthMenu.replace("_MENU_",b);j('select option[value="'+a._iDisplayLength+'"]',f).attr("selected",true);j("select",f).bind("change.DT",function(){var e=j(this).val(),i=a.aanFeatures.l;c=0;for(d=i.length;c<d;c++)i[c]!=this.parentNode&&j("select",i[c]).val(e);a._iDisplayLength=parseInt(e,10);E(a);if(a.fnDisplayEnd()==a.fnRecordsDisplay()){a._iDisplayStart=
a.fnDisplayEnd()-a._iDisplayLength;if(a._iDisplayStart<0)a._iDisplayStart=0}if(a._iDisplayLength==-1)a._iDisplayStart=0;C(a)});return f}function ya(a){var b=p.createElement("div");a.sTableId!==""&&typeof a.aanFeatures.r=="undefined"&&b.setAttribute("id",a.sTableId+"_processing");b.innerHTML=a.oLanguage.sProcessing;b.className=a.oClasses.sProcessing;a.nTable.parentNode.insertBefore(b,a.nTable);return b}function K(a,b){if(a.oFeatures.bProcessing){a=a.aanFeatures.r;for(var c=0,d=a.length;c<d;c++)a[c].style.visibility=
b?"visible":"hidden"}}function ga(a,b){for(var c=-1,d=0;d<a.aoColumns.length;d++){a.aoColumns[d].bVisible===true&&c++;if(c==b)return d}return null}function M(a,b){for(var c=-1,d=0;d<a.aoColumns.length;d++){a.aoColumns[d].bVisible===true&&c++;if(d==b)return a.aoColumns[d].bVisible===true?c:null}return null}function Q(a,b){var c,d;c=a._iDisplayStart;for(d=a._iDisplayEnd;c<d;c++)if(a.aoData[a.aiDisplay[c]].nTr==b)return a.aiDisplay[c];c=0;for(d=a.aoData.length;c<d;c++)if(a.aoData[c].nTr==b)return c;
return null}function S(a){for(var b=0,c=0;c<a.aoColumns.length;c++)a.aoColumns[c].bVisible===true&&b++;return b}function E(a){a._iDisplayEnd=a.oFeatures.bPaginate===false?a.aiDisplay.length:a._iDisplayStart+a._iDisplayLength>a.aiDisplay.length||a._iDisplayLength==-1?a.aiDisplay.length:a._iDisplayStart+a._iDisplayLength}function Ha(a,b){if(!a||a===null||a==="")return 0;if(typeof b=="undefined")b=p.getElementsByTagName("body")[0];var c=p.createElement("div");c.style.width=a;b.appendChild(c);a=c.offsetWidth;
b.removeChild(c);return a}function $(a){var b=0,c,d=0,f=a.aoColumns.length,e,i=j("th",a.nTHead);for(e=0;e<f;e++)if(a.aoColumns[e].bVisible){d++;if(a.aoColumns[e].sWidth!==null){c=Ha(a.aoColumns[e].sWidthOrig,a.nTable.parentNode);if(c!==null)a.aoColumns[e].sWidth=v(c);b++}}if(f==i.length&&b===0&&d==f&&a.oScroll.sX===""&&a.oScroll.sY==="")for(e=0;e<a.aoColumns.length;e++){c=j(i[e]).width();if(c!==null)a.aoColumns[e].sWidth=v(c)}else{b=a.nTable.cloneNode(false);e=p.createElement("tbody");c=p.createElement("tr");
b.removeAttribute("id");b.appendChild(a.nTHead.cloneNode(true));if(a.nTFoot!==null){b.appendChild(a.nTFoot.cloneNode(true));L(function(h){h.style.width=""},b.getElementsByTagName("tr"))}b.appendChild(e);e.appendChild(c);e=j("thead th",b);if(e.length===0)e=j("tbody tr:eq(0)>td",b);e.each(function(h){this.style.width="";h=ga(a,h);if(h!==null&&a.aoColumns[h].sWidthOrig!=="")this.style.width=a.aoColumns[h].sWidthOrig});for(e=0;e<f;e++)if(a.aoColumns[e].bVisible){d=Ia(a,e);if(d!==null){d=d.cloneNode(true);
c.appendChild(d)}}e=a.nTable.parentNode;e.appendChild(b);if(a.oScroll.sX!==""&&a.oScroll.sXInner!=="")b.style.width=v(a.oScroll.sXInner);else if(a.oScroll.sX!==""){b.style.width="";if(j(b).width()<e.offsetWidth)b.style.width=v(e.offsetWidth)}else if(a.oScroll.sY!=="")b.style.width=v(e.offsetWidth);b.style.visibility="hidden";Ja(a,b);f=j("tbody tr:eq(0)>td",b);if(f.length===0)f=j("thead tr:eq(0)>th",b);for(e=c=0;e<a.aoColumns.length;e++)if(a.aoColumns[e].bVisible){d=j(f[c]).outerWidth();if(d!==null&&
d>0)a.aoColumns[e].sWidth=v(d);c++}a.nTable.style.width=v(j(b).outerWidth());b.parentNode.removeChild(b)}}function Ja(a,b){if(a.oScroll.sX===""&&a.oScroll.sY!==""){j(b).width();b.style.width=v(j(b).outerWidth()-a.oScroll.iBarWidth)}else if(a.oScroll.sX!=="")b.style.width=v(j(b).outerWidth())}function Ia(a,b,c){if(typeof c=="undefined"||c){c=Ka(a,b);b=M(a,b);if(c<0)return null;return a.aoData[c].nTr.getElementsByTagName("td")[b]}var d=-1,f,e;c=-1;var i=p.createElement("div");i.style.visibility="hidden";
i.style.position="absolute";p.body.appendChild(i);f=0;for(e=a.aoData.length;f<e;f++){i.innerHTML=a.aoData[f]._aData[b];if(i.offsetWidth>d){d=i.offsetWidth;c=f}}p.body.removeChild(i);if(c>=0){b=M(a,b);if(a=a.aoData[c].nTr.getElementsByTagName("td")[b])return a}return null}function Ka(a,b){for(var c=-1,d=-1,f=0;f<a.aoData.length;f++){var e=a.aoData[f]._aData[b];if(e.length>c){c=e.length;d=f}}return d}function v(a){if(a===null)return"0px";if(typeof a=="number"){if(a<0)return"0px";return a+"px"}var b=
a.charCodeAt(a.length-1);if(b<48||b>57)return a;return a+"px"}function Oa(a,b){if(a.length!=b.length)return 1;for(var c=0;c<a.length;c++)if(a[c]!=b[c])return 2;return 0}function aa(a){for(var b=n.aTypes,c=b.length,d=0;d<c;d++){var f=b[d](a);if(f!==null)return f}return"string"}function A(a){for(var b=0;b<D.length;b++)if(D[b].nTable==a)return D[b];return null}function V(a){for(var b=[],c=a.aoData.length,d=0;d<c;d++)b.push(a.aoData[d]._aData);return b}function R(a){for(var b=[],c=a.aoData.length,d=0;d<
c;d++)b.push(a.aoData[d].nTr);return b}function Z(a){var b=R(a),c=[],d,f=[],e,i,h,k;e=0;for(i=b.length;e<i;e++){c=[];h=0;for(k=b[e].childNodes.length;h<k;h++){d=b[e].childNodes[h];d.nodeName.toUpperCase()=="TD"&&c.push(d)}h=d=0;for(k=a.aoColumns.length;h<k;h++)if(a.aoColumns[h].bVisible)f.push(c[h-d]);else{f.push(a.aoData[e]._anHidden[h]);d++}}return f}function la(a){return a.replace(new RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^)","g"),"\\$1")}function ma(a,b){for(var c=
-1,d=0,f=a.length;d<f;d++)if(a[d]==b)c=d;else a[d]>b&&a[d]--;c!=-1&&a.splice(c,1)}function va(a,b){b=b.split(",");for(var c=[],d=0,f=a.aoColumns.length;d<f;d++)for(var e=0;e<f;e++)if(a.aoColumns[d].sName==b[e]){c.push(e);break}return c}function ca(a){for(var b="",c=0,d=a.aoColumns.length;c<d;c++)b+=a.aoColumns[c].sName+",";if(b.length==d)return"";return b.slice(0,-1)}function H(a,b,c){a=a.sTableId===""?"DataTables warning: "+c:"DataTables warning (table id = '"+a.sTableId+"'): "+c;if(b===0)if(n.sErrMode==
"alert")alert(a);else throw a;else typeof console!="undefined"&&typeof console.log!="undefined"&&console.log(a)}function da(a){a.aoData.splice(0,a.aoData.length);a.aiDisplayMaster.splice(0,a.aiDisplayMaster.length);a.aiDisplay.splice(0,a.aiDisplay.length);E(a)}function na(a){if(!(!a.oFeatures.bStateSave||typeof a.bDestroying!="undefined")){var b,c,d,f="{";f+='"iCreate":'+(new Date).getTime()+",";f+='"iStart":'+a._iDisplayStart+",";f+='"iEnd":'+a._iDisplayEnd+",";f+='"iLength":'+a._iDisplayLength+
",";f+='"sFilter":"'+encodeURIComponent(a.oPreviousSearch.sSearch)+'",';f+='"sFilterEsc":'+!a.oPreviousSearch.bRegex+",";f+='"aaSorting":[ ';for(b=0;b<a.aaSorting.length;b++)f+="["+a.aaSorting[b][0]+',"'+a.aaSorting[b][1]+'"],';f=f.substring(0,f.length-1);f+="],";f+='"aaSearchCols":[ ';for(b=0;b<a.aoPreSearchCols.length;b++)f+='["'+encodeURIComponent(a.aoPreSearchCols[b].sSearch)+'",'+!a.aoPreSearchCols[b].bRegex+"],";f=f.substring(0,f.length-1);f+="],";f+='"abVisCols":[ ';for(b=0;b<a.aoColumns.length;b++)f+=
a.aoColumns[b].bVisible+",";f=f.substring(0,f.length-1);f+="]";b=0;for(c=a.aoStateSave.length;b<c;b++){d=a.aoStateSave[b].fn(a,f);if(d!=="")f=d}f+="}";La(a.sCookiePrefix+a.sInstance,f,a.iCookieDuration,a.sCookiePrefix,a.fnCookieCallback)}}function Ma(a,b){if(a.oFeatures.bStateSave){var c,d,f;d=oa(a.sCookiePrefix+a.sInstance);if(d!==null&&d!==""){try{c=typeof j.parseJSON=="function"?j.parseJSON(d.replace(/'/g,'"')):eval("("+d+")")}catch(e){return}d=0;for(f=a.aoStateLoad.length;d<f;d++)if(!a.aoStateLoad[d].fn(a,
c))return;a.oLoadedState=j.extend(true,{},c);a._iDisplayStart=c.iStart;a.iInitDisplayStart=c.iStart;a._iDisplayEnd=c.iEnd;a._iDisplayLength=c.iLength;a.oPreviousSearch.sSearch=decodeURIComponent(c.sFilter);a.aaSorting=c.aaSorting.slice();a.saved_aaSorting=c.aaSorting.slice();if(typeof c.sFilterEsc!="undefined")a.oPreviousSearch.bRegex=!c.sFilterEsc;if(typeof c.aaSearchCols!="undefined")for(d=0;d<c.aaSearchCols.length;d++)a.aoPreSearchCols[d]={sSearch:decodeURIComponent(c.aaSearchCols[d][0]),bRegex:!c.aaSearchCols[d][1]};
if(typeof c.abVisCols!="undefined"){b.saved_aoColumns=[];for(d=0;d<c.abVisCols.length;d++){b.saved_aoColumns[d]={};b.saved_aoColumns[d].bVisible=c.abVisCols[d]}}}}}function La(a,b,c,d,f){var e=new Date;e.setTime(e.getTime()+c*1E3);c=ra.location.pathname.split("/");a=a+"_"+c.pop().replace(/[\/:]/g,"").toLowerCase();var i;if(f!==null){i=typeof j.parseJSON=="function"?j.parseJSON(b):eval("("+b+")");b=f(a,i,e.toGMTString(),c.join("/")+"/")}else b=a+"="+encodeURIComponent(b)+"; expires="+e.toGMTString()+
"; path="+c.join("/")+"/";f="";e=9999999999999;if((oa(a)!==null?p.cookie.length:b.length+p.cookie.length)+10>4096){a=p.cookie.split(";");for(var h=0,k=a.length;h<k;h++)if(a[h].indexOf(d)!=-1){var l=a[h].split("=");try{i=eval("("+decodeURIComponent(l[1])+")")}catch(q){continue}if(typeof i.iCreate!="undefined"&&i.iCreate<e){f=l[0];e=i.iCreate}}if(f!=="")p.cookie=f+"=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path="+c.join("/")+"/"}p.cookie=b}function oa(a){var b=ra.location.pathname.split("/");a=a+"_"+
b[b.length-1].replace(/[\/:]/g,"").toLowerCase()+"=";b=p.cookie.split(";");for(var c=0;c<b.length;c++){for(var d=b[c];d.charAt(0)==" ";)d=d.substring(1,d.length);if(d.indexOf(a)===0)return decodeURIComponent(d.substring(a.length,d.length))}return null}function fa(a){a=a.getElementsByTagName("tr");if(a.length==1)return a[0].getElementsByTagName("th");var b=[],c=[],d,f,e,i,h,k,l=function(I,Y,N){for(;typeof I[Y][N]!="undefined";)N++;return N},q=function(I){if(typeof b[I]=="undefined")b[I]=[]};d=0;for(i=
a.length;d<i;d++){q(d);var t=0,G=[];f=0;for(h=a[d].childNodes.length;f<h;f++)if(a[d].childNodes[f].nodeName.toUpperCase()=="TD"||a[d].childNodes[f].nodeName.toUpperCase()=="TH")G.push(a[d].childNodes[f]);f=0;for(h=G.length;f<h;f++){var J=G[f].getAttribute("colspan")*1,B=G[f].getAttribute("rowspan")*1;if(!J||J===0||J===1){k=l(b,d,t);b[d][k]=G[f].nodeName.toUpperCase()=="TD"?4:G[f];if(B||B===0||B===1)for(e=1;e<B;e++){q(d+e);b[d+e][k]=2}t++}else{k=l(b,d,t);for(e=0;e<J;e++)b[d][k+e]=3;t+=J}}}d=0;for(i=
b.length;d<i;d++){f=0;for(h=b[d].length;f<h;f++)if(typeof b[d][f]=="object"&&typeof c[f]=="undefined")c[f]=b[d][f]}return c}function Na(){var a=p.createElement("p"),b=a.style;b.width="100%";b.height="200px";var c=p.createElement("div");b=c.style;b.position="absolute";b.top="0px";b.left="0px";b.visibility="hidden";b.width="200px";b.height="150px";b.overflow="hidden";c.appendChild(a);p.body.appendChild(c);b=a.offsetWidth;c.style.overflow="scroll";a=a.offsetWidth;if(b==a)a=c.clientWidth;p.body.removeChild(c);
return b-a}function L(a,b,c){for(var d=0,f=b.length;d<f;d++)for(var e=0,i=b[d].childNodes.length;e<i;e++)if(b[d].childNodes[e].nodeType==1)typeof c!="undefined"?a(b[d].childNodes[e],c[d].childNodes[e]):a(b[d].childNodes[e])}function o(a,b,c,d){if(typeof d=="undefined")d=c;if(typeof b[c]!="undefined")a[d]=b[c]}this.oApi={};this.fnDraw=function(a){var b=A(this[n.iApiIndex]);if(typeof a!="undefined"&&a===false){E(b);C(b)}else W(b)};this.fnFilter=function(a,b,c,d,f){var e=A(this[n.iApiIndex]);if(e.oFeatures.bFilter){if(typeof c==
"undefined")c=false;if(typeof d=="undefined")d=true;if(typeof f=="undefined")f=true;if(typeof b=="undefined"||b===null){P(e,{sSearch:a,bRegex:c,bSmart:d},1);if(f&&typeof e.aanFeatures.f!="undefined"){b=e.aanFeatures.f;c=0;for(d=b.length;c<d;c++)j("input",b[c]).val(a)}}else{e.aoPreSearchCols[b].sSearch=a;e.aoPreSearchCols[b].bRegex=c;e.aoPreSearchCols[b].bSmart=d;P(e,e.oPreviousSearch,1)}}};this.fnSettings=function(){return A(this[n.iApiIndex])};this.fnVersionCheck=n.fnVersionCheck;this.fnSort=function(a){var b=
A(this[n.iApiIndex]);b.aaSorting=a;O(b)};this.fnSortListener=function(a,b,c){ba(A(this[n.iApiIndex]),a,b,c)};this.fnAddData=function(a,b){if(a.length===0)return[];var c=[],d,f=A(this[n.iApiIndex]);if(typeof a[0]=="object")for(var e=0;e<a.length;e++){d=u(f,a[e]);if(d==-1)return c;c.push(d)}else{d=u(f,a);if(d==-1)return c;c.push(d)}f.aiDisplay=f.aiDisplayMaster.slice();if(typeof b=="undefined"||b)W(f);return c};this.fnDeleteRow=function(a,b,c){var d=A(this[n.iApiIndex]);a=typeof a=="object"?Q(d,a):
a;var f=d.aoData.splice(a,1),e=j.inArray(a,d.aiDisplay);d.asDataSearch.splice(e,1);ma(d.aiDisplayMaster,a);ma(d.aiDisplay,a);typeof b=="function"&&b.call(this,d,f);if(d._iDisplayStart>=d.aiDisplay.length){d._iDisplayStart-=d._iDisplayLength;if(d._iDisplayStart<0)d._iDisplayStart=0}if(typeof c=="undefined"||c){E(d);C(d)}return f};this.fnClearTable=function(a){var b=A(this[n.iApiIndex]);da(b);if(typeof a=="undefined"||a)C(b)};this.fnOpen=function(a,b,c){var d=A(this[n.iApiIndex]);this.fnClose(a);var f=
p.createElement("tr"),e=p.createElement("td");f.appendChild(e);e.className=c;e.colSpan=S(d);e.innerHTML=b;b=j("tr",d.nTBody);j.inArray(a,b)!=-1&&j(f).insertAfter(a);d.aoOpenRows.push({nTr:f,nParent:a});return f};this.fnClose=function(a){for(var b=A(this[n.iApiIndex]),c=0;c<b.aoOpenRows.length;c++)if(b.aoOpenRows[c].nParent==a){(a=b.aoOpenRows[c].nTr.parentNode)&&a.removeChild(b.aoOpenRows[c].nTr);b.aoOpenRows.splice(c,1);return 0}return 1};this.fnGetData=function(a){var b=A(this[n.iApiIndex]);if(typeof a!=
"undefined"){a=typeof a=="object"?Q(b,a):a;return(aRowData=b.aoData[a])?aRowData._aData:null}return V(b)};this.fnGetNodes=function(a){var b=A(this[n.iApiIndex]);if(typeof a!="undefined")return(aRowData=b.aoData[a])?aRowData.nTr:null;return R(b)};this.fnGetPosition=function(a){var b=A(this[n.iApiIndex]);if(a.nodeName.toUpperCase()=="TR")return Q(b,a);else if(a.nodeName.toUpperCase()=="TD")for(var c=Q(b,a.parentNode),d=0,f=0;f<b.aoColumns.length;f++)if(b.aoColumns[f].bVisible){if(b.aoData[c].nTr.getElementsByTagName("td")[f-
d]==a)return[c,f-d,f]}else d++;return null};this.fnUpdate=function(a,b,c,d,f){var e=A(this[n.iApiIndex]),i,h;b=typeof b=="object"?Q(e,b):b;if(typeof a!="object"){h=a;e.aoData[b]._aData[c]=h;if(e.aoColumns[c].fnRender!==null){h=e.aoColumns[c].fnRender({iDataRow:b,iDataColumn:c,aData:e.aoData[b]._aData,oSettings:e});if(e.aoColumns[c].bUseRendered)e.aoData[b]._aData[c]=h}i=M(e,c);if(i!==null)e.aoData[b].nTr.getElementsByTagName("td")[i].innerHTML=h;else e.aoData[b]._anHidden[c].innerHTML=h}else{if(a.length!=
e.aoColumns.length){H(e,0,"An array passed to fnUpdate must have the same number of columns as the table in question - in this case "+e.aoColumns.length);return 1}for(c=0;c<a.length;c++){h=a[c];e.aoData[b]._aData[c]=h;if(e.aoColumns[c].fnRender!==null){h=e.aoColumns[c].fnRender({iDataRow:b,iDataColumn:c,aData:e.aoData[b]._aData,oSettings:e});if(e.aoColumns[c].bUseRendered)e.aoData[b]._aData[c]=h}i=M(e,c);if(i!==null)e.aoData[b].nTr.getElementsByTagName("td")[i].innerHTML=h;else e.aoData[b]._anHidden[c].innerHTML=
h}}a=j.inArray(b,e.aiDisplay);e.asDataSearch[a]=ka(e,e.aoData[b]._aData);if(typeof f=="undefined"||f)X(e);if(typeof d=="undefined"||d)W(e);return 0};this.fnSetColumnVis=function(a,b,c){var d=A(this[n.iApiIndex]),f,e;e=d.aoColumns.length;var i,h,k,l,q;if(d.aoColumns[a].bVisible!=b){l=j(">tr",d.nTHead)[0];i=j(">tr",d.nTFoot)[0];q=[];h=[];for(f=0;f<e;f++){q.push(d.aoColumns[f].nTh);h.push(d.aoColumns[f].nTf)}if(b){for(f=b=0;f<a;f++)d.aoColumns[f].bVisible&&b++;if(b>=S(d)){l.appendChild(q[a]);l=j(">tr",
d.nTHead);f=1;for(e=l.length;f<e;f++)l[f].appendChild(d.aoColumns[a].anThExtra[f-1]);if(i){i.appendChild(h[a]);l=j(">tr",d.nTFoot);f=1;for(e=l.length;f<e;f++)l[f].appendChild(d.aoColumns[a].anTfExtra[f-1])}f=0;for(e=d.aoData.length;f<e;f++){i=d.aoData[f]._anHidden[a];d.aoData[f].nTr.appendChild(i)}}else{for(f=a;f<e;f++){k=M(d,f);if(k!==null)break}l.insertBefore(q[a],l.getElementsByTagName("th")[k]);l=j(">tr",d.nTHead);f=1;for(e=l.length;f<e;f++){q=j(l[f]).children();l[f].insertBefore(d.aoColumns[a].anThExtra[f-
1],q[k])}if(i){i.insertBefore(h[a],i.getElementsByTagName("th")[k]);l=j(">tr",d.nTFoot);f=1;for(e=l.length;f<e;f++){q=j(l[f]).children();l[f].insertBefore(d.aoColumns[a].anTfExtra[f-1],q[k])}}Z(d);f=0;for(e=d.aoData.length;f<e;f++){i=d.aoData[f]._anHidden[a];d.aoData[f].nTr.insertBefore(i,j(">td:eq("+k+")",d.aoData[f].nTr)[0])}}d.aoColumns[a].bVisible=true}else{l.removeChild(q[a]);f=0;for(e=d.aoColumns[a].anThExtra.length;f<e;f++){k=d.aoColumns[a].anThExtra[f];k.parentNode.removeChild(k)}if(i){i.removeChild(h[a]);
f=0;for(e=d.aoColumns[a].anTfExtra.length;f<e;f++){k=d.aoColumns[a].anTfExtra[f];k.parentNode.removeChild(k)}}h=Z(d);f=0;for(e=d.aoData.length;f<e;f++){i=h[f*d.aoColumns.length+a*1];d.aoData[f]._anHidden[a]=i;i.parentNode.removeChild(i)}d.aoColumns[a].bVisible=false}f=0;for(e=d.aoOpenRows.length;f<e;f++)d.aoOpenRows[f].nTr.colSpan=S(d);if(typeof c=="undefined"||c){X(d);C(d)}na(d)}};this.fnPageChange=function(a,b){var c=A(this[n.iApiIndex]);ea(c,a);E(c);if(typeof b=="undefined"||b)C(c)};this.fnDestroy=
function(){var a=A(this[n.iApiIndex]),b=a.nTableWrapper.parentNode,c=a.nTBody,d,f;a.bDestroying=true;j(a.nTableWrapper).find("*").andSelf().unbind(".DT");d=0;for(f=a.aoColumns.length;d<f;d++)a.aoColumns[d].bVisible===false&&this.fnSetColumnVis(d,true);j("tbody>tr>td."+a.oClasses.sRowEmpty,a.nTable).parent().remove();if(a.nTable!=a.nTHead.parentNode){j(">thead",a.nTable).remove();a.nTable.appendChild(a.nTHead)}if(a.nTFoot&&a.nTable!=a.nTFoot.parentNode){j(">tfoot",a.nTable).remove();a.nTable.appendChild(a.nTFoot)}a.nTable.parentNode.removeChild(a.nTable);
j(a.nTableWrapper).remove();a.aaSorting=[];a.aaSortingFixed=[];T(a);j(R(a)).removeClass(a.asStripClasses.join(" "));if(a.bJUI){j("th",a.nTHead).removeClass([n.oStdClasses.sSortable,n.oJUIClasses.sSortableAsc,n.oJUIClasses.sSortableDesc,n.oJUIClasses.sSortableNone].join(" "));j("th span",a.nTHead).remove()}else j("th",a.nTHead).removeClass([n.oStdClasses.sSortable,n.oStdClasses.sSortableAsc,n.oStdClasses.sSortableDesc,n.oStdClasses.sSortableNone].join(" "));b.appendChild(a.nTable);d=0;for(f=a.aoData.length;d<
f;d++)c.appendChild(a.aoData[d].nTr);a.nTable.style.width=v(a.sDestroyWidth);j(">tr:even",c).addClass(a.asDestoryStrips[0]);j(">tr:odd",c).addClass(a.asDestoryStrips[1]);d=0;for(f=D.length;d<f;d++)D[d]==a&&D.splice(d,1)};this.fnAdjustColumnSizing=function(a){var b=A(this[n.iApiIndex]);X(b);if(typeof a=="undefined"||a)this.fnDraw(false);else if(b.oScroll.sX!==""||b.oScroll.sY!=="")this.oApi._fnScrollDraw(b)};for(var pa in n.oApi)if(pa)this[pa]=r(pa);this.oApi._fnExternApiFunc=r;this.oApi._fnInitalise=
s;this.oApi._fnLanguageProcess=y;this.oApi._fnAddColumn=F;this.oApi._fnColumnOptions=x;this.oApi._fnAddData=u;this.oApi._fnGatherData=z;this.oApi._fnDrawHead=U;this.oApi._fnDraw=C;this.oApi._fnReDraw=W;this.oApi._fnAjaxUpdate=ta;this.oApi._fnAjaxUpdateDraw=ua;this.oApi._fnAddOptionsHtml=sa;this.oApi._fnFeatureHtmlTable=za;this.oApi._fnScrollDraw=Ca;this.oApi._fnAjustColumnSizing=X;this.oApi._fnFeatureHtmlFilter=xa;this.oApi._fnFilterComplete=P;this.oApi._fnFilterCustom=Fa;this.oApi._fnFilterColumn=
Ea;this.oApi._fnFilter=Da;this.oApi._fnBuildSearchArray=ha;this.oApi._fnBuildSearchRow=ka;this.oApi._fnFilterCreateSearch=ia;this.oApi._fnDataToSearch=ja;this.oApi._fnSort=O;this.oApi._fnSortAttachListener=ba;this.oApi._fnSortingClasses=T;this.oApi._fnFeatureHtmlPaginate=Ba;this.oApi._fnPageChange=ea;this.oApi._fnFeatureHtmlInfo=Aa;this.oApi._fnUpdateInfo=Ga;this.oApi._fnFeatureHtmlLength=wa;this.oApi._fnFeatureHtmlProcessing=ya;this.oApi._fnProcessingDisplay=K;this.oApi._fnVisibleToColumnIndex=ga;
this.oApi._fnColumnIndexToVisible=M;this.oApi._fnNodeToDataIndex=Q;this.oApi._fnVisbleColumns=S;this.oApi._fnCalculateEnd=E;this.oApi._fnConvertToWidth=Ha;this.oApi._fnCalculateColumnWidths=$;this.oApi._fnScrollingWidthAdjust=Ja;this.oApi._fnGetWidestNode=Ia;this.oApi._fnGetMaxLenString=Ka;this.oApi._fnStringToCss=v;this.oApi._fnArrayCmp=Oa;this.oApi._fnDetectType=aa;this.oApi._fnSettingsFromNode=A;this.oApi._fnGetDataMaster=V;this.oApi._fnGetTrNodes=R;this.oApi._fnGetTdNodes=Z;this.oApi._fnEscapeRegex=
la;this.oApi._fnDeleteIndex=ma;this.oApi._fnReOrderIndex=va;this.oApi._fnColumnOrdering=ca;this.oApi._fnLog=H;this.oApi._fnClearTable=da;this.oApi._fnSaveState=na;this.oApi._fnLoadState=Ma;this.oApi._fnCreateCookie=La;this.oApi._fnReadCookie=oa;this.oApi._fnGetUniqueThs=fa;this.oApi._fnScrollBarWidth=Na;this.oApi._fnApplyToChildren=L;this.oApi._fnMap=o;var qa=this;return this.each(function(){var a=0,b,c,d,f;a=0;for(b=D.length;a<b;a++){if(D[a].nTable==this)if(typeof g=="undefined"||typeof g.bRetrieve!=
"undefined"&&g.bRetrieve===true)return D[a].oInstance;else if(typeof g.bDestroy!="undefined"&&g.bDestroy===true){D[a].oInstance.fnDestroy();break}else{H(D[a],0,"Cannot reinitialise DataTable.\n\nTo retrieve the DataTables object for this table, please pass either no arguments to the dataTable() function, or set bRetrieve to true. Alternatively, to destory the old table and create a new one, set bDestroy to true (note that a lot of changes to the configuration can be made through the API which is usually much faster).");
return}if(D[a].sTableId!==""&&D[a].sTableId==this.getAttribute("id")){D.splice(a,1);break}}var e=new m;D.push(e);var i=false,h=false;a=this.getAttribute("id");if(a!==null){e.sTableId=a;e.sInstance=a}else e.sInstance=n._oExternConfig.iNextUnique++;if(this.nodeName.toLowerCase()!="table")H(e,0,"Attempted to initialise DataTables on a node which is not a table: "+this.nodeName);else{e.nTable=this;e.oInstance=qa.length==1?qa:j(this).dataTable();e.oApi=qa.oApi;e.sDestroyWidth=j(this).width();if(typeof g!=
"undefined"&&g!==null){e.oInit=g;o(e.oFeatures,g,"bPaginate");o(e.oFeatures,g,"bLengthChange");o(e.oFeatures,g,"bFilter");o(e.oFeatures,g,"bSort");o(e.oFeatures,g,"bInfo");o(e.oFeatures,g,"bProcessing");o(e.oFeatures,g,"bAutoWidth");o(e.oFeatures,g,"bSortClasses");o(e.oFeatures,g,"bServerSide");o(e.oScroll,g,"sScrollX","sX");o(e.oScroll,g,"sScrollXInner","sXInner");o(e.oScroll,g,"sScrollY","sY");o(e.oScroll,g,"bScrollCollapse","bCollapse");o(e.oScroll,g,"bScrollInfinite","bInfinite");o(e.oScroll,
g,"iScrollLoadGap","iLoadGap");o(e.oScroll,g,"bScrollAutoCss","bAutoCss");o(e,g,"asStripClasses");o(e,g,"fnRowCallback");o(e,g,"fnHeaderCallback");o(e,g,"fnFooterCallback");o(e,g,"fnCookieCallback");o(e,g,"fnInitComplete");o(e,g,"fnServerData");o(e,g,"fnFormatNumber");o(e,g,"aaSorting");o(e,g,"aaSortingFixed");o(e,g,"aLengthMenu");o(e,g,"sPaginationType");o(e,g,"sAjaxSource");o(e,g,"iCookieDuration");o(e,g,"sCookiePrefix");o(e,g,"sDom");o(e,g,"oSearch","oPreviousSearch");o(e,g,"aoSearchCols","aoPreSearchCols");
o(e,g,"iDisplayLength","_iDisplayLength");o(e,g,"bJQueryUI","bJUI");o(e.oLanguage,g,"fnInfoCallback");typeof g.fnDrawCallback=="function"&&e.aoDrawCallback.push({fn:g.fnDrawCallback,sName:"user"});typeof g.fnStateSaveCallback=="function"&&e.aoStateSave.push({fn:g.fnStateSaveCallback,sName:"user"});typeof g.fnStateLoadCallback=="function"&&e.aoStateLoad.push({fn:g.fnStateLoadCallback,sName:"user"});e.oFeatures.bServerSide&&e.oFeatures.bSort&&e.oFeatures.bSortClasses&&e.aoDrawCallback.push({fn:T,sName:"server_side_sort_classes"});
if(typeof g.bJQueryUI!="undefined"&&g.bJQueryUI){e.oClasses=n.oJUIClasses;if(typeof g.sDom=="undefined")e.sDom='<"H"lfr>t<"F"ip>'}if(e.oScroll.sX!==""||e.oScroll.sY!=="")e.oScroll.iBarWidth=Na();if(typeof g.iDisplayStart!="undefined"&&typeof e.iInitDisplayStart=="undefined"){e.iInitDisplayStart=g.iDisplayStart;e._iDisplayStart=g.iDisplayStart}if(typeof g.bStateSave!="undefined"){e.oFeatures.bStateSave=g.bStateSave;Ma(e,g);e.aoDrawCallback.push({fn:na,sName:"state_save"})}if(typeof g.aaData!="undefined")h=
true;if(typeof g!="undefined"&&typeof g.aoData!="undefined")g.aoColumns=g.aoData;if(typeof g.oLanguage!="undefined")if(typeof g.oLanguage.sUrl!="undefined"&&g.oLanguage.sUrl!==""){e.oLanguage.sUrl=g.oLanguage.sUrl;j.getJSON(e.oLanguage.sUrl,null,function(q){y(e,q,true)});i=true}else y(e,g.oLanguage,false)}else g={};if(typeof g.asStripClasses=="undefined"){e.asStripClasses.push(e.oClasses.sStripOdd);e.asStripClasses.push(e.oClasses.sStripEven)}c=false;d=j(">tbody>tr",this);a=0;for(b=e.asStripClasses.length;a<
b;a++)if(d.filter(":lt(2)").hasClass(e.asStripClasses[a])){c=true;break}if(c){e.asDestoryStrips=["",""];if(j(d[0]).hasClass(e.oClasses.sStripOdd))e.asDestoryStrips[0]+=e.oClasses.sStripOdd+" ";if(j(d[0]).hasClass(e.oClasses.sStripEven))e.asDestoryStrips[0]+=e.oClasses.sStripEven;if(j(d[1]).hasClass(e.oClasses.sStripOdd))e.asDestoryStrips[1]+=e.oClasses.sStripOdd+" ";if(j(d[1]).hasClass(e.oClasses.sStripEven))e.asDestoryStrips[1]+=e.oClasses.sStripEven;d.removeClass(e.asStripClasses.join(" "))}a=this.getElementsByTagName("thead");
c=a.length===0?[]:fa(a[0]);var k;if(typeof g.aoColumns=="undefined"){k=[];a=0;for(b=c.length;a<b;a++)k.push(null)}else k=g.aoColumns;a=0;for(b=k.length;a<b;a++){if(typeof g.saved_aoColumns!="undefined"&&g.saved_aoColumns.length==b){if(k[a]===null)k[a]={};k[a].bVisible=g.saved_aoColumns[a].bVisible}F(e,c?c[a]:null)}if(typeof g.aoColumnDefs!="undefined")for(a=g.aoColumnDefs.length-1;a>=0;a--){var l=g.aoColumnDefs[a].aTargets;j.isArray(l)||H(e,1,"aTargets must be an array of targets, not a "+typeof l);
c=0;for(d=l.length;c<d;c++)if(typeof l[c]=="number"&&l[c]>=0){for(;e.aoColumns.length<=l[c];)F(e);x(e,l[c],g.aoColumnDefs[a])}else if(typeof l[c]=="number"&&l[c]<0)x(e,e.aoColumns.length+l[c],g.aoColumnDefs[a]);else if(typeof l[c]=="string"){b=0;for(f=e.aoColumns.length;b<f;b++)if(l[c]=="_all"||e.aoColumns[b].nTh.className.indexOf(l[c])!=-1)x(e,b,g.aoColumnDefs[a])}}if(typeof k!="undefined"){a=0;for(b=k.length;a<b;a++)x(e,a,k[a])}a=0;for(b=e.aaSorting.length;a<b;a++){if(e.aaSorting[a][0]>=e.aoColumns.length)e.aaSorting[a][0]=
0;k=e.aoColumns[e.aaSorting[a][0]];if(typeof e.aaSorting[a][2]=="undefined")e.aaSorting[a][2]=0;if(typeof g.aaSorting=="undefined"&&typeof e.saved_aaSorting=="undefined")e.aaSorting[a][1]=k.asSorting[0];c=0;for(d=k.asSorting.length;c<d;c++)if(e.aaSorting[a][1]==k.asSorting[c]){e.aaSorting[a][2]=c;break}}T(e);this.getElementsByTagName("thead").length===0&&this.appendChild(p.createElement("thead"));this.getElementsByTagName("tbody").length===0&&this.appendChild(p.createElement("tbody"));e.nTHead=this.getElementsByTagName("thead")[0];
e.nTBody=this.getElementsByTagName("tbody")[0];if(this.getElementsByTagName("tfoot").length>0)e.nTFoot=this.getElementsByTagName("tfoot")[0];if(h)for(a=0;a<g.aaData.length;a++)u(e,g.aaData[a]);else z(e);e.aiDisplay=e.aiDisplayMaster.slice();e.bInitialised=true;i===false&&s(e)}})}})(jQuery,window,document);

File diff suppressed because one or more lines are too long

View File

@ -1,43 +0,0 @@
#!/bin/sh
## Setup some vars to use local portage tree
# export PATH=${HOME}/euscan/:${PATH}
# export ROOT=${HOME}/local
# export PORTAGE_CONFIGROOT=${ROOT}
# export EIX_CACHEFILE=${HOME}/local/var/cache/eix
## Update local trees
# emerge --sync --root=${ROOT} --config-root=${PORTAGE_CONFIGROOT}
# ROOT="/" layman -S --config=${ROOT}/etc/layman/layman.cfg
## Generate ebuild cache to speed up eix
# cd ${ROOT}/var/lib/layman/ && \
# for overlay in **/; do
# [ ! -f ${overlay}profiles/repo_name ] && continue
#
# echo "egencache ${overlay}"
# egencache --jobs=8 --rsync \
# --repo=$(cat ${overlay}profiles/repo_name) \
# --config-root=${PORTAGE_CONFIGROOT} \
# --update --update-use-local-desc
# done
## Also update eix database, because we use eix internaly
# eix-update
## Go to euscanwww dir
# cd ${HOME}/euscan/euscanwww/
## Scan portage (packages, versions)
# python manage.py scan-portage --all --purge-versions --purge-packages
# eix --only-names -x | sort --random-sort | gparallel --eta --load 8 --jobs 400% --max-args=64 python manage.py scan-metadata
## Scan metadata (herds, maintainers, homepages, ...)
# python manage.py scan-metadata --all
## Scan uptsream packages
# python manage.py scan-upstream --all
# eix --only-names -x | gparallel --jobs 400% euscan | python manage.py scan-upstream --feed --purge-versions
## Update counters
# python manage.py update-counters

View File

@ -1,17 +0,0 @@
#!/usr/bin/python
import sys, os
import os.path
PROJECT = '/path/to/euscanwww'
sys.path.insert(0, os.path.dirname(PROJECT))
sys.path.insert(0, PROJECT)
os.chdir(PROJECT)
os.environ['DJANGO_SETTINGS_MODULE'] = "euscanwww.settings"
os.environ['HOME'] = "/path/to/home"
from django.core.servers.fastcgi import runfastcgi
runfastcgi(method="threaded", daemonize="false", maxspare=1)

View File

@ -1,81 +0,0 @@
[MAIN]
#-----------------------------------------------------------
# Defines the directory where overlays should be installed
storage : /path/to/euscan/local/var/lib/layman
#-----------------------------------------------------------
# Remote overlay lists will be stored here
# layman will append _md5(url).xml to each filename
cache : %(storage)s/cache
#-----------------------------------------------------------
# The list of locally installed overlays
local_list: %(storage)s/overlays.xml
#-----------------------------------------------------------
# Path to the make.conf file that should be modified by
# layman
make_conf : %(storage)s/make.conf
#-----------------------------------------------------------
# URLs of the remote lists of overlays (one per line) or
# local overlay definitions
#
#overlays : http://www.gentoo.org/proj/en/overlays/repositories.xml
# http://dev.gentoo.org/~wrobel/layman/global-overlays.xml
# http://mydomain.org/my-layman-list.xml
# file:///var/lib/layman/my-list.xml
overlays : http://www.gentoo.org/proj/en/overlays/repositories.xml
#-----------------------------------------------------------
# Proxy support
# If unset, layman will use the http_proxy environment variable.
#
#proxy : http://[user:pass@]www.my-proxy.org:3128
#-----------------------------------------------------------
# Strict checking of overlay definitions
#
# Set either to "yes" or "no". If "no" layman will issue
# warnings if an overlay definition is missing either
# description or contact information.
#
nocheck : yes
#-----------------------------------------------------------
# Umask settings
#
# layman should usually work with a umask of 0022. You should
# only change this setting if you are absolutely certain that
# you know what you are doing.
#
#umask : 0022
#-----------------------------------------------------------
# Command overrides
#
# You can have commands point to either a binary at a different
# location, e.g.
#
# /home/you/local/bin/git
#
# or just the command, e.g.
#
# git
#
# to use PATH-based resolution of the binary to call.
#
#bzr_command : /usr/bin/bzr
#cvs_command : /usr/bin/cvs
#darcs_command : /usr/bin/darcs
#git_command : /usr/bin/git
#mercurial_command : /usr/bin/hg
#rsync_command : /usr/bin/rsync
#svn_command : /usr/bin/svn
#tar_command : /bin/tar

View File

@ -1,19 +0,0 @@
CFLAGS="-march=native -O2 -pipe"
CXXFLAGS="${CFLAGS}"
CHOST="x86_64-pc-linux-gnu"
USE=""
ACCEPT_LICENSE="*"
EUSCAN_ROOT="/path/to/euscan/local"
PORTDIR="${EUSCAN_ROOT}/usr/portage"
PORTDIR_OVERLAY="$PORTDIR"
FEATURES="$FEATURES -strict metadata-transfer"
## Add overlays here
# PORTDIR_OVERLAY="${EUSCAN_ROOT}/usr/local/portage $PORTDIR_OVERLAY"
## Or use layman
# source ${EUSCAN_ROOT}/var/lib/layman/make.conf

Binary file not shown.

View File

@ -1,24 +0,0 @@
import os, sys
sys.path.insert(0, '../')
os.environ['DJANGO_SETTINGS_MODULE'] = 'euscanwww.settings'
from django import db
c = db.connection.cursor()
try:
c.execute(r"""SELECT c.relname
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind IN ('S','')
AND n.nspname NOT IN ('pg_catalog', 'pg_toast')
AND pg_catalog.pg_table_is_visible(c.oid)
""")
to_update = []
for row in c:
seq_name = row[0]
rel_name = seq_name.split("_id_seq")[0]
to_update.append((seq_name, rel_name,))
for row in to_update:
c.execute(r"SELECT setval('%s', max(id)) FROM %s"%row)
finally:
c.close()

View File

@ -1,144 +0,0 @@
# Django settings for euscanwww project.
import os.path
DEBUG = True
TEMPLATE_DEBUG = DEBUG
ADMINS = (
('admin', 'admin@example.com'),
)
MANAGERS = ADMINS
"""
# MySQL Example:
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'euscan',
'USER': 'euscan',
'PASSWORD': 'password',
'HOST': 'localhost',
'PORT': '',
'OPTIONS': {
'init_command': 'SET storage_engine=INNODB',
}
},
# PostGreSQL Example:
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'euscan',
'USER': 'euscan',
'PASSWORD': '',
'HOST': 'localhost',
'PORT': '',
},
"""
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(os.path.dirname( __file__ ), 'euscan.db')
},
}
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': os.path.join(os.path.dirname( __file__ ), 'euscan.cache'),
}
}
RRD_ROOT = os.path.join(os.path.dirname( __file__ ), 'rrd')
# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
# On Unix systems, a value of None will cause Django to use the same
# timezone as the operating system.
# If running in a Windows environment this must be set to the same as your
# system time zone.
TIME_ZONE = 'Europe/Paris'
# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'en-us'
SITE_ID = 1
# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = True
# If you set this to False, Django will not format dates, numbers and
# calendars according to the current locale
USE_L10N = True
# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/"
MEDIA_ROOT = os.path.join(os.path.dirname( __file__ ), 'media/')
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash if there is a path component (optional in other cases).
# Examples: "http://media.lawrence.com", "http://example.com/media/"
MEDIA_URL = '/media/'
# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
# trailing slash.
# Examples: "http://foo.com/media/", "/media/".
ADMIN_MEDIA_PREFIX = '/admin-media/'
# Make this unique, and don't share it with anybody.
SECRET_KEY = '00000000000000000000000000000000000000000000000000'
# List of callables that know how to import templates from various sources.
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
# 'django.template.loaders.eggs.Loader',
)
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
CACHE_MIDDLEWARE_SECONDS=3600
CACHE_MIDDLEWARE_ANONYMOUS_ONLY=True
ROOT_URLCONF = 'euscanwww.urls'
FORCE_SCRIPT_NAME=""
TEMPLATE_DIRS = (
os.path.join(os.path.dirname( __file__ ), 'templates'),
)
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.admin',
'south',
'euscan',
# Uncomment the next line to enable admin documentation:
# 'django.contrib.admindocs',
)
try:
from local_settings import *
except ImportError, ex:
import sys
sys.stderr.write(\
("settings.py: error importing local settings file:\n" + \
"\t%s\n" + \
"Do you have a local_settings.py module?\n") % str(ex))
raise

View File

@ -1,68 +0,0 @@
<?xml version="1.0" encoding="utf8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">
<head>
<title>{% block title %}euscan{% endblock %}</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
{% block meta %}
<link rel="alternate" type="application/atom+xml" title="Global log" href="{% url global_feed %}" />
{% endblock %}
{% block css %}
<link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}css/style.css" media="screen" title="Normal" />
{% endblock %}
{% block javascript %}
{% endblock %}
</head>
<body>
<div id="header">
<a href="http://www.gentoo.org">
<img id="logo" src="{{ MEDIA_URL }}img/gentoo_org.png" />
</a>
{% block header %}<h1>Ebuild Upstream Scanner (euscan)</h1>{% endblock %}
</div>
<div id="content">
{% block content %}{% endblock %}
</div>
<div id="menus">
{% block menus %}
<div id="menu">
<ul>
{% block menu %}
<li><a href="{% url euscan.views.index %}">Home</a></li>
<li><a href="{% url euscan.views.categories %}">Categories</a></li>
<li><a href="{% url euscan.views.herds %}">Herds</a></li>
<li><a href="{% url euscan.views.maintainers %}">Maintainers</a></li>
<li><a href="{% url euscan.views.overlays %}">Overlays</a></li>
<li><a href="{% url euscan.views.world %}">Scan World</a></li>
<li><a href="{% url euscan.views.statistics %}">Statistics</a></li>
<!--
<li>---</li>
<li><a href="#">Login</a></li>
<li><a href="#">Register</a></li>
-->
<li>---</li>
{% block menu_feed %}
<li>
<img src="{{ MEDIA_URL }}/img/feed.png" alt="feed" />
<a title="Global Feed" href="{% url global_feed %}">Global Feed</a>
</li>
{% endblock %}
<li>---</li>
<li><a href="{% url euscan.views.api %}">API</a></li>
<li><a href="{% url euscan.views.about %}">About</a></li>
{% endblock %}
</ul>
</div>
{% endblock %}
</div>
<div id="footer">
<p>
Questions, Comments, Corrections ?
Email: corentin.chary at gmail.com<br />
Copyright (C) 2011 <strong>Corentin Chary</strong><br />
Original Gentoo artwork and logos copyright (C) Gentoo Foundation.<br />
Design inspired by (stolen from) gentoo.org and bugs.gentoo.org.<br />
<em>This site is not an official Gentoo website.</em>
</p>
</div>
</body>
</html>

View File

@ -1,23 +0,0 @@
{% extends "_base.html" %}
{% block css %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{{MEDIA_URL}}css/table.css" media="screen" title="Normal" />
{% endblock %}
{% block javascript %}
{{ block.super }}
<script type="text/javascript" language="javascript" src="{{MEDIA_URL}}js/jquery.js"></script>
<script type="text/javascript" language="javascript" src="{{MEDIA_URL}}js/jquery.dataTables.js"></script>
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
$('#table').dataTable( {
"bPaginate": false,
"bInfo": false,
"bStateSave": true,
"sCookiePrefix": "datatables_"
} );
});
</script>
{% endblock %}

View File

@ -1,9 +0,0 @@
{% load mul %}
{% load sub %}
{% load div %}
<div class="package_stat">
<div class="packaged" style="width: {{ infos.n_packaged|mul:100.0|div:infos.n_versions }}%"></div>
<div class="overlay" style="width: {{ infos.n_overlay|mul:100.0|div:infos.n_versions }}%"></div>
<div class="upstream" style="width: {{ infos.n_versions|sub:infos.n_overlay|sub:infos.n_packaged|mul:100.0|div:infos.n_versions }}%"></div>
</div>

View File

@ -1,24 +0,0 @@
{% load packages %}
{% load mul %}
{% load sub %}
{% load div %}
<td>{{ infos.n_packaged }}</td>
{% if infos.n_overlay == 0 or infos.n_overlay <= infos.n_packaged %}
<td>
{% else %}{% if infos.n_overlay < infos.n_packaged %}
<td class="bad">
{% else %}
<td class="ugly">
{% endif %}{% endif %}
{{ infos.n_overlay }}
</td>
{% if infos.n_versions == infos.n_packaged|add:infos.n_overlay %}
<td>
{% else %}{% if infos.n_versions < infos.n_packaged|add:infos.n_overlay|mul:2 %}
<td class="bad">
{% else %}
<td class="ugly">
{% endif %}{% endif %}
{{ infos.n_versions|sub:infos.n_packaged|sub:infos.n_overlay }}
</td>

View File

@ -1,23 +0,0 @@
{% load packages %}
<table id="table" class="display">
<thead>
<th>Package</th>
<th>Gentoo</th>
<th>Overlays</th>
<th>Unpackaged</th>
</thead>
<tbody>
{% for package in packages %}
<tr>
<td>
<a href="{% url euscan.views.package package.category package.name %}">
{{ package.category }}/{{ package.name }}
</a>
{% package_bar package %}
</td>
{% package_cols package %}
</tr>
{% endfor %}
</tbody>
</table>

Some files were not shown because too many files have changed in this diff Show More