Compare commits

..

405 Commits

Author SHA1 Message Date
ef2a739df4 Release 1.5.4 2024-09-20 17:02:19 +02:00
b4af591361 autoport-launcher: call dnf refresh before update 2024-09-20 16:52:27 +02:00
dc76be906a autodist-cleanold: skip processing SPECPARTS files in spec folder 2024-09-20 16:50:57 +02:00
f54041d4df repology-openmamba.py: provide a custom user agent as required by repology.org policy 2024-09-14 15:00:16 +02:00
0c2162fe62 update-specfile: remove post scripts calling ldconfig replaced by trigger 2024-09-14 14:56:05 +02:00
36b00b7e43 webbuild-cgi: keep spec create fields to editr on failure 2024-09-14 14:53:23 +02:00
b8e6a0a960 webbuild: fix: urlencode spec version update field vefore submitting 2024-06-07 13:49:45 +02:00
a292621b9c webbuild-cgi: add log message for invalid secret; added a check for /var/autoport existence 2024-05-13 19:36:42 +02:00
2ed572f76b Release 1.5.3 2024-05-13 18:23:48 +02:00
0979292b54 autodist-cleanold: replace cron script with executable run by autoport-launcher 2024-05-13 18:23:03 +02:00
9904607872 autoport: same fix as previous commit needs to be applied to autoport 2024-05-02 19:27:51 +02:00
931dbd1dce autodist: fix authenticating social log sent messages by encoding secret 2024-05-02 11:04:32 +02:00
35abe2122a webbuild.html: fix for editor change callback and other minor fixes 2024-05-01 19:13:24 +02:00
506e531ec8 webbuild-cgi: social log exception for "autodist" when WEBBUILD_URL is set at localhost 2024-04-22 00:35:00 +02:00
9fc3f8373c Release 1.5.2 2024-04-22 00:33:52 +02:00
10514b4e49 webbuild: autobuilds.html: layout fixes 2024-04-20 20:31:31 +02:00
007b280870 webbuild: set codemirror height to 500 2024-04-18 20:07:20 +02:00
72ce4f5115 webbuild-cgi: show current user social log messages when WEBBUILD_URL is not set 2024-04-18 17:32:44 +02:00
b24249e474 webbuild-cgi: fix autodist checkbox not working if no permissions for maintainer mode 2024-04-18 13:36:48 +02:00
91c50976a9 webbuild.html: update js and css paths for updated codemirror 2024-04-18 13:18:25 +02:00
3717880b21 webbuild: create webbuild.db if missing 2024-04-18 13:06:06 +02:00
13407f5e51 autodist/config: update site and repo urls 2024-04-18 12:22:42 +02:00
92a582306e webbuild: also update webbuild.html 2024-04-18 01:33:48 +02:00
bcda06c59c Release 1.5.0 2024-04-17 21:57:04 +02:00
f594957e25 autoport: added AUTOPORT_IGNORE_LIST configuration to provide a list of ignored autoport packages 2024-04-17 21:54:27 +02:00
9fbe4e715e webbuild: codemirror update to same as wordpress-theme-openmamba 2024-04-17 21:46:55 +02:00
8ee611b7ac webbuild: update css and webbuild-cgi for stand-alone mode 2024-04-17 21:44:36 +02:00
c46535f109 Release 1.4.3 2024-04-13 14:41:23 +02:00
5e4081a335 autodist-cgi: increase default size of build output and support for full output 2024-04-13 14:10:42 +02:00
cebe696e6e autodist,update-specfile: support for update version as argument; cleanups
autodist-inspect: update repositories list
2024-04-13 14:08:06 +02:00
6144945c31 Release 1.4.2 2024-02-08 17:11:01 +01:00
ea5c285270 repology-openmamba.py: switch from ignore to a more generic update-conf.json file to parse with ignore and more information 2024-02-08 17:08:30 +01:00
9d218a005a webbuild-sudo: fix parsing SPECFILE_BUILDDIR since rpmspec started expanding %setup macro 2024-02-08 17:06:19 +01:00
5354160b25 webbuild-cgi: fix getting processes pid with more than one '+' sign appended 2024-02-08 17:05:34 +01:00
4d29a63a34 Release 1.4.1 2024-01-06 14:12:19 +01:00
e01964e86a 40-autodist-upstream-updates: remove obsolete nightly autodist-upstream-updates cron launcher 2024-01-06 13:08:58 +01:00
cafa354501 45-autodist-git-sync: added daily cron file for autodist-git repository sync 2024-01-06 13:07:48 +01:00
07285b0cc7 autospec-conf: update sample autospec configuration 2024-01-06 13:03:33 +01:00
fe984b1da2 autoport: no longer search and reschedule other providing packages on prepare failed 2024-01-06 12:46:20 +01:00
e8ae210c2d autodist-repository: integration with autodist-git for import and release functionalities 2024-01-06 12:42:38 +01:00
e629f9561c autodist-git: many improvements to reach working repository and package sync functionality 2024-01-06 12:40:32 +01:00
7f1ecb9f41 Release 1.4.0 2024-01-02 20:28:27 +01:00
fcdbff1da2 autodist-git: new tool for syncing rpm repository with new git server at src.openmamba.org 2024-01-02 20:18:19 +01:00
5bac010c6d autodist-inspect,40-autodist-cleanold: commit minor changes done in production 2024-01-02 20:14:46 +01:00
d0b8d56db4 Release 1.3.3 2023-10-09 19:56:57 +02:00
0bc98d2bf8 autodist-inpsect: new tool added 2023-10-09 19:56:45 +02:00
10e566b640 update-specfile: sync with current build server changes 2023-10-09 19:54:26 +02:00
8b6c1367f0 Release 1.3.2 2023-09-19 15:42:55 +02:00
8be0311320 Makefile: install forgotten autodist-launcher 2023-09-19 15:42:37 +02:00
aecf691938 autoport: rebuild dependant mode: do not add empty epoch value if empty 2023-08-20 13:13:55 +02:00
fcc2302ac9 Release 1.3.1 2023-08-17 11:33:36 +02:00
096b6d6f69 autoport: fetch repfiles for all archs but only if local files are older than 60 minutes 2023-08-17 11:30:12 +02:00
0d5bc034b1 Release 1.3 2023-08-16 18:41:00 +02:00
92246206dc Update repository from devel to base and other changes for devel to rolling distribution 2023-08-16 18:38:48 +02:00
519f8d5656 Release 1.2 2023-08-11 10:55:44 +02:00
cafae574a8 40-autodist-cleanold: minor fix for chroot environments 2023-08-11 10:49:49 +02:00
88643910fb autoport: update with current production changes 2023-08-11 10:35:50 +02:00
ceea7ef522 autodist-repository: change default destination repository from devel to base 2023-08-11 10:32:33 +02:00
d85e5aae68 telegram/openmamba_bot.py: update repositories list 2022-10-08 13:01:52 +02:00
e4fcd8d6cf openmambabot: update service and add requirements to run in virtualenv (/var/autodist/env) 2022-10-02 14:56:26 +02:00
ac040bff56 Release 1.1 2022-10-02 13:15:47 +02:00
af92aad66e 65-autoport: minor changes 2022-10-02 13:05:28 +02:00
702d3cfe09 autodist-launcher: move code in 60-autodist-update to /usr/bin script 2022-10-02 13:02:40 +02:00
8794727a6a 40-autodist-cleanold: sync with current build server 2022-10-02 12:57:49 +02:00
78c85dcc7d etc/autodist/blacklist: update to current production build server 2022-10-02 12:53:11 +02:00
6b784c66d3 update-specfile: update to current production 2022-10-02 12:51:43 +02:00
4902ab352f autodist, autoport: update to current production code 2022-10-02 12:47:45 +02:00
193a41413a repology-openmamba.py: update to current production code 2022-10-02 12:43:26 +02:00
e9c5cbbdbf Makefile: update systemd unitdir path 2022-10-02 12:41:04 +02:00
3013fcd2d1 autoport: fix check for -devel suffix in rebuild dependant mode 2022-06-25 14:28:23 +02:00
5bbf2f8715 webbuild-cgi: check for zero length cache files (disk full); add -b descriptive argument to patches 2022-06-11 11:03:08 +02:00
5c9a10871d autoport: added epoch support for added BuildRequirements in rebuild mode 2022-06-08 15:40:24 +02:00
de810c1bd7 automaint: update to current build server usage 2022-01-25 14:28:23 +01:00
f32788002f telegram/openmamba_bot: added support for arch aarch64 2022-01-25 14:27:38 +01:00
a7cbefbe18 autoport-launcher, 65-autoport: new launcher and single cron script to improve background processes launch with systemd 2021-12-19 15:00:23 +01:00
f852838441 automaint: update with changes from current operating version 2021-09-04 14:56:26 +02:00
33c3a3ca36 webbuild/webbuild-functions: pipe iconv to build outputs to fix invalid UTF-8 characters 2021-06-05 10:57:06 +02:00
70def57d53 Merge branch 'master' of ssh://gitlab.mambasoft.it:4424/openmamba/autodist 2021-05-15 13:42:29 +02:00
b451ee800b repology-openmamba.py: support for ignore json list; autodist-upstream-updates: replace usage of obsolete tempfile with mktemp 2021-05-15 13:41:26 +02:00
f97c3c4598 webbuild-cgi: add free space information from any chroot environment 2021-05-08 22:42:42 +02:00
acd4178c8b webbuild-cgi: filter out invalid characters from some responses 2021-05-08 22:40:25 +02:00
b6d3b83d1e autodist-upstream-updates: add support to fetch updates from repology API (repology.org) 2021-03-14 11:55:11 +01:00
9d003905df autodist, webbuild-cgi: add -b to autospec command to update build requrements in specfiles; other fixes to webbuild-cgi 2021-03-14 11:51:42 +01:00
27d32d110e autoport: add safety check that .spec version matches srcpkglist to fix packages sent in wrong repositories when the latter file is not up to date 2021-02-20 17:28:14 +01:00
7dcd16b2ca autoport: use all archs as base arch to find packages to port 2020-12-16 20:40:35 +01:00
dab56b358f webbuild-cgi: fix for lost messages in social log 2020-12-16 20:39:46 +01:00
51a0c3a449 More aarch64 support 2020-11-26 19:09:06 +01:00
b95cb79e69 aarch64 support 2020-11-25 19:18:24 +01:00
d4241631f2 autoport: fix after uname change: use uname -m instead of uname -i 2020-11-25 19:18:02 +01:00
8fda5d4d82 telegram: update to Telegram Bot api v.13.0 2020-11-19 14:43:39 +01:00
a69962724a telegram: switch to python3 2020-11-19 12:34:53 +01:00
64394b8110 Release 1.0.3 2020-09-27 18:02:04 +02:00
9ad95404ec Other old fixes on server applied 2020-09-27 15:59:08 +02:00
ac8340c0d6 Switch from using smart to dnf and integrate other old changes 2020-09-27 15:56:38 +02:00
f23570f228 Release 1.2 (formerly released) 2020-09-27 15:49:51 +02:00
79af8764e1 webbuild-cgi: css fixes 2019-07-30 19:39:22 +02:00
94f1ffcf9a webbuild: more css support for output boxes 2019-07-28 21:57:52 +02:00
1c15fcfb25 webbuild: fixes for sociallog from webbuild.db 2019-07-28 20:40:09 +02:00
5a0fa63a96 webbuild-sudo: switch to using rpmspec from rpm4 instead of rpm --specedit 2019-07-21 11:37:20 +02:00
bbcfce5260 Release 1.0.1 2019-07-15 17:54:01 +02:00
db0354041e webbuild: minor updates synced from running build server 2019-07-15 17:42:52 +02:00
c7d8a76d80 autodist: minor updates synced from running server installation 2019-07-15 17:39:27 +02:00
058a0baa7e Added openmamba bot for telegram 2017-12-30 23:14:48 +01:00
38c75eea33 autoport-fix-environment: fix a syntax error in sed 2017-07-04 19:04:08 +02:00
4cee459385 Release 1.0.0 2017-06-19 15:18:07 +02:00
f47b80b1cc autodist-update: disable icecc to workaround some problems 2017-06-19 14:49:40 +02:00
092e90e004 autoport-native: only upgrade native packages on first loop cycle 2017-06-19 14:49:12 +02:00
e53a62198a automaint: minor fixes 2017-06-19 14:48:35 +02:00
68bacbc599 autodist-upstream-updates: added support for blacklisting 2017-06-19 14:48:01 +02:00
681b2e5ec7 autodist: added --rebuild-srpms 2017-06-19 14:47:30 +02:00
a6d6fd03e4 webbuild: login fix for problem when password is changed on main site 2017-06-19 14:39:08 +02:00
c3cbf7c0e8 webbuild: switch social_log to sqlite3 db; display status also when there are no processes to display 2016-10-30 13:41:46 +01:00
ced497545e webbuild: support for different archs in downloads and some fixes 2016-10-17 12:57:27 +02:00
ee1a94af6f webbuild-functions: some optimizations of sed parsing functions 2016-07-04 21:39:40 +02:00
2c09744bbd Webbuild: support for running a console command from web interface input 2016-05-29 00:23:38 +02:00
7d21e2fa60 webbuild-cgi: red color for Updating indicator in jobs panel 2016-05-04 15:51:41 +02:00
7e78d60c90 webbuild-cgi: fix for files upload and minor cosmetic changes to rebuild deps function 2016-03-11 14:46:59 +01:00
537b80a4c4 update-specfile: remove Requires: kde-workspace from many kde4->kde5 packages and fix kde download url 2016-02-21 14:41:58 +01:00
db8fa88b9b autoport: apply strict repository check at first step only
This means check is applied to command-line passed packages only
2016-02-19 12:06:41 +01:00
f93a093134 40-autodist-cleanold: refresh with currently in use modifications 2016-02-16 13:45:18 +01:00
a49c4ec447 autodist: add --repository-string to limit autoport of pacakges from specified repository
autoport: update accordingly
2016-02-15 08:07:58 +01:00
1c8a7cbbdf webbuild-cgi: add icon button to refresh spec list 2016-01-10 17:10:57 +01:00
73f032afda webbuild-cgi: use https for gravatar 2015-12-08 14:59:48 +01:00
8b9ee4a7b2 webbuild-cgi: alway exit early on refreshsocial request 2015-09-19 23:15:48 +02:00
c3c5a9009e webbuild: fully div based layout and responsive support 2015-08-23 15:59:13 +02:00
4fba9537b5 webbuild: split css adding webbuild-standalone.css and webbuild-post.css 2015-08-22 18:44:38 +02:00
a191ef0eb3 webbuild: fixes to matching autodist jobs with package name and other small fixes 2015-08-22 17:58:14 +02:00
5f2e54f58a webbuild-cgi: small refining of rpmbuild processes detection 2015-05-16 14:28:02 +02:00
90a0d85269 webbuild-cgi: display live server stats in first line of jobs window 2015-05-14 17:13:34 +02:00
6e6d92d5a2 webbuild: redesign of operation panel in maintainance mode 2015-05-07 00:14:06 +02:00
8f2eb49563 webbuild.css: float maintainer panel to the left 2015-05-04 20:46:37 +02:00
4ee59fdbd2 Sync with current server files before releasing 2015-04-18 16:33:42 +02:00
d1493a2edf webbuild: create uploads directory 2015-04-18 15:56:38 +02:00
c6db4b05c9 autodist-cgi: fix showing last log file 2015-04-14 22:08:31 +02:00
3f8d3fb9b2 webbuild: change error background color from red to darkred 2015-04-13 23:16:34 +02:00
77ecc7566d webbuild: implement a var2html function to filter for security variable to html
Currently used in chat messages
2015-04-04 18:49:49 +02:00
aca1323856 webbuild-cgi: fixes for rpm manager install/upgrade from repositories 2015-01-30 11:11:23 +01:00
a6b14a1aa9 autoport: port packages also in milestone rebuild mode and display fetched files in verbose mode (-v) 2015-01-04 10:58:10 +01:00
2e6f2dd33e autoport: don't increment first release number in REBUILD_MILESTONE mode 2014-12-31 14:52:23 +01:00
fe8a60addd Release 0.9.22 2014-12-04 14:42:44 +01:00
ef649ef1c4 webbuild-cgi: some more milestone3 support 2014-12-04 14:41:33 +01:00
a044057f9f webbuild-cgi: fix for distroquery usage while searching for already existing package 2014-11-24 12:48:02 +01:00
8623f8bfd8 autodist-cgi: small changes after wordpress integration 2014-11-23 22:18:37 +01:00
f47f80416d Release 0.9.21 2014-11-22 23:00:08 +01:00
177629094c webbuild: other layout changes 2014-11-22 22:57:12 +01:00
f5a01c61a6 webbuild: move most rpm buttons below the editor plus some other layout adjustements 2014-11-22 19:51:49 +01:00
f492d02d7d webbuild: reallow html tags in processtail to display colors, only filter <[/]pre> tags for now 2014-11-22 12:35:08 +01:00
367e2f7dee webbuild-cgi: fix support for multiple words queries 2014-11-16 16:08:06 +01:00
144f1b0eb6 Release 0.9.20
Added forgotten autodist-tmpfilesd new file
2014-11-13 14:58:59 +01:00
faa153d41e Move pid directory to /run/autodist providing systemd tmpfiles.d configuration 2014-11-13 14:57:50 +01:00
d435051d50 webbuild-cgi: fixes to existing package check through distroquery 2014-11-13 14:30:28 +01:00
9afdb96444 40-autodist-cleanold cron: minor adjustments 2014-11-13 14:29:50 +01:00
eaf4e0220c cgi_getvars(): fix warning when empty key is received 2014-11-13 14:28:19 +01:00
3b032d1d8c webbuild: use distroquery to check and warn about already extisting package when creating a new package 2014-10-31 22:27:05 +01:00
6032d80cdb webbuild: fix autodist prepare and update; run ldconfig in build requirements; support version in autodist update 2014-10-29 22:36:58 +01:00
66ce879682 webbuild.html, autobuilds.html: restrict xmlhttp to fix too many sockets pending in chromium bug 2014-10-12 23:18:14 +02:00
3b15ee14b7 40-autodist-cleanold: improvements in daily file cleaning cron file 2014-10-09 16:14:39 +02:00
949a4c35df webbuild-cgi: support target arch in rpm prepare 2014-10-05 19:27:35 +02:00
d77d29fd37 webbuild: support adding BASE_URL to search result links 2014-10-05 19:26:55 +02:00
4d8a804eee webbuild-cgi: add remote fetch for maintainer recent packages and distromatic log plus add caching support 2014-09-28 12:34:41 +02:00
60f8e3cff0 webbuild: increase logs size before cutting; cache environment info, update every 5 minutes 2014-09-21 02:34:47 +02:00
73791f2c58 Release 0.9.19 2014-09-05 22:39:23 +02:00
8aaf239342 webbuild-cgi: honour selected target arch when sending package 2014-09-05 22:36:46 +02:00
9ab37c25c2 autodist-upstream-updates: only accept even numbers (also 1.x and 2.x) as stable from Gnome upstream list 2014-09-05 19:10:42 +02:00
491357aebb autodist-repository: new "install" option to install packages with rpm directly from local repositories 2014-09-05 19:08:34 +02:00
bf3085f435 autodist-cgi: check if host is up before fetching cgi data from secondary sites 2014-08-23 13:30:45 +02:00
f6543e78fa Release 0.9.18 2014-08-21 13:26:47 +02:00
ea098185e1 autoport: check if source is present in target arch, not source, before rebuilding 2014-08-21 13:13:36 +02:00
52f9b3e9e0 autodist-upstream-updates: try to detect and remove unstable releases in parse_gnome() 2014-07-27 13:49:10 +02:00
55224a3ecb webbuild-cgi: other adjustements using binary calls to webbuild-sudo 2014-07-10 13:31:20 +02:00
bbcc9460b4 webbuild-cgi: need to pass binary to some SUDO_WRAPPER calls after previous change 2014-07-08 18:55:58 +02:00
8e4e790104 webbuild-sudo: pipe send output to parse_generic_output 2014-07-08 17:56:49 +02:00
487dbb2824 autodist: maybe fix for packages being sent to wrong repositories 2014-07-08 02:08:53 +02:00
f05b31368f webbuild: add support for mass rebuild of dependant packages 2014-07-06 23:23:55 +02:00
fa602e75e0 autoport: add -ud option to rebuild dependant packages of given package(s) using new distromatic pkg_needrebuild info 2014-07-06 22:18:49 +02:00
45b347da76 webbuild: add mass rebuilt build requirement update box; redesign and move chat box 2014-07-05 23:54:48 +02:00
5927784c85 Release 0.9.16 2014-07-05 23:53:15 +02:00
59a1ad0317 autodist,autoport: allow to pass arguments to update-specfile script
update-specfile: accept --buildreq multiple arguments to edit build requirements with version
2014-07-05 17:50:53 +02:00
3e0f261856 webbuild: add apache configuration file with 'Timeout 600'; not installed for now 2014-06-28 18:51:12 +02:00
85e7950c4e webbuild-functions: silence a warning which should be harmful and can't fix on client side 2014-06-28 18:50:15 +02:00
58d61d51e3 Release 0.9.15 2014-06-24 11:38:48 +02:00
b59c024914 webbuild: show build host on title and in environment panel 2014-06-18 13:15:44 +02:00
82c5f79f27 webbuild: allow modified autodist ports is AUTOPORT_PORT_REPOSITORY is set 2014-06-18 13:09:29 +02:00
5241fa7e82 webbuild-cgi: need to call specinfo in speccreate to set $SPECVAR_WORKINGHOME variable 2014-06-14 16:01:54 +02:00
a89e2b9a13 autodist: fix manual version update and autoupdate script management 2014-06-13 14:35:54 +02:00
f72d0b3663 Release 0.9.14 2014-06-13 12:53:58 +02:00
56f41ede80 autodist-tool: use autodist --list-jobs instead of directly reading DISTDB 2014-06-13 12:47:16 +02:00
a59ea180af 66-autoport-chroot: fix trivial mistake in previous change 2014-06-11 00:31:45 +02:00
e3e4104f4e autodist: add support for running <pkgname>-autoupdate script in /SOURCES after version update if found 2014-06-10 14:21:02 +02:00
4f12cc4969 Release 0.9.13 2014-06-10 14:15:13 +02:00
1da0a6d971 40-autodist-upstream-updates daily cron: don't run if AUTOPORT_UPDATE_NO_DISTROMATIC is set 2014-06-10 01:52:14 +02:00
a66a8f8029 66-autoport-chroot: fix finding log path for autodist user special case 2014-06-10 01:44:26 +02:00
2dd4d2632d webbuild-cgi: fix rpmbuild -bs and other rpmbuild calls by passing correct %_topdir according to environment 2014-06-10 00:19:26 +02:00
6dd2bb37bc Release 0.9.12 2014-06-10 00:18:03 +02:00
79c00b9f50 66-autoport-chroot: fix chroot command to start/stop icecream 2014-06-07 19:30:39 +02:00
f4dbf4b5c2 autodist-repository, webbuild-cgi: use 'ls --color=none' to access local repository to speed up when using NFS 2014-06-07 19:20:56 +02:00
13e52f18d5 60-autodist-update cron: add AUTOPORT_UPDATE_NO_AUTOMAINT and AUTOPORT_UPDATE_NO_DISTROMATIC configuration settings
These variables are set to 1 by default
2014-06-07 19:13:48 +02:00
1979751f33 autodist-repository: make sure to return 0 if import_package() succeeds 2014-06-05 10:51:55 +02:00
ed2de4963a autodist-repository: set return code as the number of import or release errors 2014-06-05 10:36:47 +02:00
ae9e5c3be5 autodist: return error code when package to be imported does not exist any longer 2014-06-05 10:24:49 +02:00
457d02194c Release 0.9.11 2014-06-05 10:09:03 +02:00
7107f7884f autodist: don't raise error for missing $SYSCONFDIR/distdb*
First use repository distdb* if available or load $SYSCONFDIR/distdb*
Use $SYSCONFDIR/distdb.d/*.db for adding local custom definitions.
2014-06-04 22:39:38 +02:00
159432b669 Remove configuration files that have been moved to repository in a previous commit 2014-06-04 18:13:33 +02:00
c73ba35d74 autodist-upstream-updates: fix exiting with an error message if srcpkglist is bad 2014-06-04 18:03:36 +02:00
2d950512e4 autoport: add AUTOPORT_UNSTAGE_ARCHS to globally define unstaged archs (current default: i586) 2014-06-04 15:37:41 +02:00
30e8c88970 webbuild.html: don't set expire date for cookies 2014-05-31 15:30:20 +02:00
eff79c5bf8 autodist, autoport: support for distdb.*, legacy.*, unstage.* from repository 2014-05-31 14:43:42 +02:00
e6ee8dbd5b autodist-repository: direct error and warning message to stderr 2014-05-29 15:35:40 +02:00
9643cf4103 webbuild.html, autobuilds.html: added favicon 2014-05-29 14:35:20 +02:00
bb64fe0188 Release 0.9.10 2014-05-29 14:13:08 +02:00
1617e30950 Add .bashrc and .bash_profile to autodist home 2014-05-28 14:07:37 +02:00
f0eaac941b autodist-repository: allow reading secret settings from file config-secret if it is readable 2014-05-28 10:49:15 +02:00
c0b7304aa4 autodist: make --list-jobs and --list-pkgs faster by running before reading unneeded package status from repository 2014-05-27 21:58:37 +02:00
7a268ce0c8 /etc/sysconfig/autoport: add ICECREAM_MONITOR_HOST to configuration template 2014-05-27 19:26:15 +02:00
49a1ed773b webbuild: add logrotate file 2014-05-27 19:11:16 +02:00
99ab1fe252 autodist-repository: manage merging of packages without relying on base arch (i586) 2014-05-27 13:13:47 +02:00
112abc68c6 webbuild: fix for forwarding requests 2014-05-27 01:40:53 +02:00
f2bb820de8 webbuild: check if WEBBUILD_URL is localhost to avoid recursive request to itself 2014-05-27 00:05:15 +02:00
0f96bedecd automaint: fixes to support any architecture build instead of base arch (i586) 2014-05-25 16:18:35 +02:00
70548ea687 automaint: support importing from any architecture, not just base arch (i586) 2014-05-24 20:17:44 +02:00
67497d1d4f Release 0.9.9 2014-05-24 18:29:08 +02:00
50d38312db webbuild.html: restore setting cookies 2014-05-24 17:26:59 +02:00
82ab9d49c9 65-autoport-native cron: fix detecting home dir for log 2014-05-24 16:43:32 +02:00
24f57a4cd4 unstage.x86_64: update 2014-05-24 16:36:05 +02:00
0c9f7b442e autodist cgi: support for REP variable to fix multiple log windows showing bug 2014-05-24 16:35:05 +02:00
03d939419c Add local autobuild interface autobuilds.html and other fixes 2014-05-24 16:05:40 +02:00
ea9bd6e623 Default config update for latest changes 2014-05-23 21:28:22 +02:00
6fc6b0bda6 Added autodist-repository tool, further fixes to support a central sociallog and more fixes 2014-05-23 21:17:27 +02:00
2979f8d61b Release 0.9.8 2014-05-23 21:07:05 +02:00
25b48ad735 Latest fix to make webbuild work on new installation 2014-05-22 19:10:42 +02:00
5df925c70b Sync to current status before releasing 2014-05-22 18:20:42 +02:00
34796d0b38 Updates to distd.i586 and legacy autodist files 2014-04-25 12:16:17 +02:00
9076297743 autodist/autoport: minor fixes 2014-04-25 12:12:07 +02:00
49f415f364 webbuild: sync recent minor fixes 2014-04-25 12:10:30 +02:00
bdc9145d01 webbuild.js: detect package as Python if name starting with 'py' 2014-02-01 15:12:03 +01:00
49bda1c6c3 webbuild: change matrix to single column and vertical scrolling 2014-02-01 15:10:56 +01:00
82337b4343 webbuild-functions-private: use stdbuf to prevent buffering in processtail 2014-02-01 15:00:21 +01:00
9ab269e0f7 webbuild-functions: fix killtree function to avoid killing http server 2014-02-01 14:57:30 +01:00
d73319d4ea webbuild: fixes in processes list management 2014-02-01 14:56:17 +01:00
aee7f737b1 webbuild-sudo: fix getting job pid in background mode 2014-02-01 14:55:11 +01:00
14d27be655 autoport: find_requirements(): fix parsing for 'is needed by' 2014-01-12 19:58:00 +01:00
f5d91a52fc webbuild: sync to current running version:
- refine socialbox refresh to avoid high browser cpu usage
- support for ruby specfile creation template and fixes for source creation from git
- make processes list a scroll-pane scrollbox
- other small webbuild fixes
2013-12-14 11:57:03 +01:00
ecc3ed74a2 autoport cron: added support for running icecream in chroot environment 2013-12-14 11:51:37 +01:00
dd9fb71c1b autodist-upstream-updates: fixes and some code rework 2013-11-09 14:34:49 +01:00
094174a2b6 cron files: sync to current running code with some changes 2013-11-09 14:33:39 +01:00
a939e6217a webbuild: sync to current running files with lots of fixes and small changes 2013-11-09 14:31:17 +01:00
10b3f8eff0 autoport: more checks on releases, repository fetch code reworked and more 2013-11-09 14:21:25 +01:00
4cf07b63e5 autodist: fix for rebuild and other small fixes 2013-11-09 14:19:34 +01:00
0669999e60 automaint: added verbose output (-v) and test mode (-t); skip package with same release as upstream 2013-07-13 13:52:23 +02:00
a6bcf08a21 automaint: added -v option to display explainatory messages on skipped packages 2013-07-12 02:03:09 +02:00
77cfdacce8 automaint: new tool for automatic (cron based) maintainance 2013-07-12 01:55:29 +02:00
1815ade013 Release 0.9.7 2013-07-11 11:39:14 +02:00
374848a5a0 autoport: use rpm to eval specdir if autospec doesn't return it 2013-07-11 11:24:58 +02:00
c35c462647 autodist-upstream-updates: case insensitive search for pkgs in manualver db 2013-07-11 11:15:30 +02:00
ea17d50b69 autodist: config files updates 2013-07-11 11:12:51 +02:00
ef98426c64 autodist: added --user option to notify invoking user via webbuild social messages
- implement older packages autorebuild in batch mode
2013-07-11 11:07:15 +02:00
cbe63c0c85 webbuild: improvement in RPM manager and lots of other changes and fixes 2013-07-11 11:03:09 +02:00
ee91237d64 webbuild-cgi: minor fix on variable check 2013-06-05 18:52:41 +02:00
0febe8f777 webbuild: local webbuild page support for RPM manager 2013-06-05 18:51:00 +02:00
fd294840b1 autodist: sync to latest cron and /etc/autodist configuration 2013-06-05 18:35:07 +02:00
aeec210b02 webbuild: added RPM manager 2013-06-05 18:31:55 +02:00
24f394ce84 autodist,webbuild: support for different update return codes in automatic updates logging 2013-06-05 14:03:56 +02:00
becb15708b webbuild: source files upload support 2013-06-04 02:46:14 +02:00
0e2960e708 webbuild.html: center cointainer and simplify code for heading image and message 2013-06-03 14:09:15 +02:00
92a3d43064 webbuild.js: improved 'Start from URL' filename parsing 2013-06-03 13:57:58 +02:00
16b2ff1ce9 webbuild-cgi: debugging comments removed to clean previous commit 2013-06-03 13:49:37 +02:00
07e9b8a75d webbuild: move show autodist logs section from right sidebar to central area below editor controls ..
- add environment information in some social_log messages
- improve automatic checks and output log in patches add function
2013-06-03 13:46:04 +02:00
56923432c9 webbuild: improve patch management and minor bash code changes 2013-06-01 00:30:05 +02:00
74876ce852 autodist: don't update package version when --rebuild is passed 2013-05-30 13:19:38 +02:00
272860e5fe autoport: just call 'autospec -a4 --rebuild ..' in REBUILD_MILESTONE mode 2013-05-26 13:57:34 +02:00
c0f51ea3ac autoport: restore reworked code for selecting milestone rebuild packages 2013-05-25 22:33:43 +02:00
dc7de5b07c autoport: force rebuild (don't update) in rebuild mode 2013-05-25 22:22:17 +02:00
641029e7ec webbuild: use sudo wrapper to sort list of log files to take the most recent 2013-05-23 15:44:13 +02:00
9cfdccccc0 webbuild: support automatic local environments when none is set in configuration 2013-05-23 13:02:22 +02:00
19233fce7d webbuild.js: support for "Start from URL" related fields autocompletion 2013-05-23 12:06:28 +02:00
dd369356c5 webbuild: support for getting repository list from configuration 2013-05-22 12:09:19 +02:00
0315d1a69d autospec: syntax fix for previous --nosrpm check 2013-05-22 10:36:21 +02:00
8751a555bc webbuild-functions: fixes to previous change 2013-05-22 00:31:57 +02:00
d7fa8c819b webbuild-functions: (re)implement log dir special case for autodist user in chroot environment 2013-05-22 00:21:18 +02:00
d99d231b47 autodist: avoid calling autospec send with --nosrpm --norpm (for autoport) 2013-05-22 00:02:14 +02:00
8fa299b2f2 webbuild-functions: filter web server REMOTE_* variables in cgi_getvars function for security 2013-05-21 16:40:40 +02:00
e0f9129ac5 webbuilnd interface: added progress icon for process box 2013-05-21 16:18:30 +02:00
2b8d183d22 webbuild: support for admin user and access from localhost; support enter key in user and password input 2013-05-21 16:12:02 +02:00
4ff95a4a86 Release 0.9.6 2013-05-21 12:39:01 +02:00
47661108aa autodist: also filter '@' characters when matching job names 2013-05-21 12:23:05 +02:00
a52cecc4c5 webbuild cgi: clean all denied requests 2013-05-21 12:05:33 +02:00
035e78eba8 webbuild interface: small fixes for portability 2013-05-21 11:57:52 +02:00
f9a0a4f5bd Makefile: create state dirs in /var/webbuild 2013-05-21 11:54:37 +02:00
45749c8a4a autodist-upstream-updates: fixes on packages match filters 2013-05-21 01:40:12 +02:00
53163c856a autodist: sync with current cron files with little changes 2013-05-21 01:39:06 +02:00
a218041054 autodist: sync to current distdb.* and unstage.* for all archs 2013-05-21 01:36:32 +02:00
7029416146 webbuild interface: don't send user=null if user cookie is not set 2013-05-21 01:25:35 +02:00
61710ad694 webbuild: also manage user for authentication 2013-05-21 01:18:05 +02:00
b84e90b7db webbuild interface: add cookie support to maintain user session 2013-05-21 00:30:35 +02:00
3927887baf webbuild: add webbuild icon for interface 2013-05-21 00:26:32 +02:00
740eb19d7c webbuild: update webbuild.css 2013-05-21 00:18:39 +02:00
46a9b5cf33 webbuild: add ok and fail icons 2013-05-21 00:15:17 +02:00
c23ffef2a9 webbuild cgi: silence standard error in some tac and grep commands to avoid filling webserver error log 2013-05-20 18:55:13 +02:00
9367503886 webbuild: remove unused code around AS_HOST variable 2013-05-20 18:30:28 +02:00
466141bd3e webbuild: start with most fields disabled for "Start for url:" function 2013-05-20 18:27:13 +02:00
3a7772cb70 webbuild: early addition of web-server side interface 2013-05-20 18:22:38 +02:00
c1617df152 webbuild: support for suggesting specfile name and version when creating a new package
- also remove .spec from spec edit dropdown
2013-05-19 16:54:31 +02:00
91ad537c95 autoport: support for new autospec needport variable in sources-* files 2013-05-19 16:50:59 +02:00
52ea72fb98 webbuild-functions-private: same as below (input boxes auto-resizing) 2013-05-04 15:46:24 +02:00
2d68892ef4 webbuild-cgi: implement auto-resizing of some input boxes 2013-05-04 15:44:57 +02:00
0deefe9b43 autodist-upstream-updates: support for blacklist db 2013-05-04 15:44:08 +02:00
1471140bd4 autoport-chroot: allow to specify a chroot command instead of running default shell from command line 2013-05-04 15:41:57 +02:00
d7f48ae5af autodist/autoport: improve logging support for multiple packages targets; fix some checks with delayed repositories 2013-05-04 15:40:10 +02:00
8576dc1d8c webbuild: some small bugfixes 2013-04-22 12:33:50 +02:00
2674eed1f2 autodist-upstream-updates: get archlinux packages list from mirror directory listings 2013-04-22 12:30:00 +02:00
ac6f81462a autoport-chroot: set a shell prompt containing chroot name 2013-04-22 12:28:47 +02:00
06d4c75c90 autoport: send webbuild messages also when not in batch mode 2013-04-22 12:27:28 +02:00
88ab767d1b autodist: added jobs support for %continue_on_error and some other fixes 2013-04-22 12:26:12 +02:00
abe0683b5f autoport-chroot cron: rework loop to avoid calling more times smart and other things not required 2013-04-22 12:24:34 +02:00
9778194a65 autodist-upstream-updates: support for archlinux 2013-04-22 11:57:31 +02:00
2036752464 autodist config: replace old reference to 'webbuild.cgi' with 'webbuild' 2013-02-03 23:44:41 +01:00
ec6b60b45d Release 0.9.5 2013-02-02 16:37:38 +01:00
54379b55d4 autodist-cgi: support buildlogdir for 'autodist' user in chroot mode 2013-02-02 14:55:06 +01:00
ccf4cda924 webbuild: support for special 'autodist' user path in chroot mode 2013-02-02 14:22:14 +01:00
f43a210165 Makefile: fix after cron file renaming 2013-02-02 14:20:22 +01:00
5aa631ff10 config: updated configuration for distdb.*, legacy and unstaged packages 2013-02-02 14:10:10 +01:00
c1285c09cf autodist-upstream-updates: skip unstable updates 2013-02-02 14:05:36 +01:00
8235cba011 webbuild-function, autodist-cgi: also fix buildlogdir for autodist user in chroot mode 2013-01-21 02:37:04 +01:00
0a7f28e6e3 webbuild-function: support for autodist user special case in chroot mode 2013-01-19 21:06:45 +01:00
1df35a2641 autodist-update cron: fix x86_64 check 2013-01-19 20:37:31 +01:00
e0ee0726c8 60-autodist-update: start using autoport sysconfig configuration for update cron also
- file renamed from 60-autodist-autobuild
2013-01-19 17:46:30 +01:00
625c2b3ed2 webbuild: update to current production version providing some fixes and new features 2013-01-19 16:24:26 +01:00
a0314b874b autodist-cgi: various fixes 2013-01-19 16:22:21 +01:00
95c366a940 autodist: sync to current /etc/autodist files 2013-01-19 16:18:12 +01:00
ec39f8f7cb autodist-upstream-updates: use package repository from distromatic files in html output 2013-01-19 16:15:23 +01:00
6d278e3a20 autodist: sync with current production changes:
- fix support for multiple words arg passed to autospec (--changelog)
- yet some logs path and cleaning fixes
- temporary workaround: hardcoded skipping of java-*, apache-*, jakarta-*, compiz* packages (TODO: make this configurable)
2013-01-19 16:12:37 +01:00
24afa0b07b autodist-upstream-updates: fixed command line options for showing not up-to-date only packages 2012-12-02 00:03:56 +01:00
03a198fec4 webbuild: small fixes and code organization 2012-12-01 23:36:43 +01:00
432f79fa29 autoport: use $DATADIR instead of /var/autoport to also work in user mode 2012-12-01 23:33:14 +01:00
4b8773011b autodist-upstream-updates: added -u option to only output packages that are not up-to-date 2012-12-01 23:31:16 +01:00
0168057f06 Makefile: install cron file added in previous commit 2012-12-01 23:29:06 +01:00
84d27d1f44 Added 60-autodist-autobuild hourly cron script 2012-12-01 17:20:54 +01:00
6cf3e9f99f Added script autodust-upstream-updates with daily cron script 2012-12-01 17:18:36 +01:00
878663f2f0 autodist: sync configuration files with current status 2012-11-20 00:10:29 +01:00
25f1c4bb8c autoport cron: silent a couple of debugging messages 2012-11-20 00:08:05 +01:00
87a184e585 autodist cgi: lots of changes following webbuild development 2012-11-20 00:04:33 +01:00
2f6984ed3b autoport: added rebuild with changelog support throgh new -u option 2012-11-20 00:00:51 +01:00
aabe20a9ad autodist: reduce progress logging lines in autobuild mode and some other small fixes 2012-11-19 23:58:03 +01:00
9f98345aad webbuild: added another ton of changes; added webbuild-functions-private external include 2012-11-19 23:52:30 +01:00
d3705b31c7 autoport: generate an operation state file for better parsing by autodist cgi 2012-10-18 00:57:43 +02:00
76032ddcb4 autodist-tool: makepatch: support for patch type autodetection 2012-10-18 00:55:22 +02:00
12b3759777 autodist: create an operation state file for better parsing from cgi; return the number of faild operations as exit code 2012-10-18 00:52:41 +02:00
0e1067c930 webbuild: sync with current running sources (tons of changes again) 2012-10-18 00:49:13 +02:00
12d8eafdc4 webbuild: added server side javascript includes and css styles 2012-09-21 13:03:27 +02:00
0601482f54 webbuild: sync with current alpha development with lots of changes and improvements 2012-09-21 12:57:19 +02:00
4021d4f7a1 distdb.i586: updated 2012-09-21 12:55:55 +02:00
9a8b1355f7 autoport cron: split autoport cron script into two files to parallelize native and chroot port jobs 2012-09-21 12:53:08 +02:00
1514f95b2b autodist cgi: other logfile names and display fixes 2012-09-21 12:51:11 +02:00
1f088616ad autodist: added --list-pkg option and fix for jobs starting with a number (54321) 2012-09-21 12:48:14 +02:00
eebf7f263d autoport cron: fix some log paths with the ones used by current autodist/autoport 2012-09-10 17:51:11 +02:00
ffff0b1c10 webbuild: lots of not better detailed changes; added webbuild-functions import script in /usr/share/autodist 2012-09-10 17:48:21 +02:00
e66061e4c3 distdb: moved kernel jobs from distdb to distdb.i586 2012-09-10 17:43:44 +02:00
298ad4d73c autodist,autoport: support for sending status to webbuild social log 2012-09-10 17:41:15 +02:00
71fec6c77a webbuild-sudo: fix getting specfile version 2012-09-06 18:56:32 +02:00
dcff130bdf webbuild-cgi: support for public social box and other fixes and improvements 2012-09-06 18:55:33 +02:00
5170d2815a autodist-cgi: move icecream builds outside the repositories loop 2012-09-06 18:54:25 +02:00
455ca50f06 autodist: added option --list-jobs for webdist to know all available jobs 2012-09-06 18:52:58 +02:00
0d02eac831 autoport: log naming using timestamp, fix detection of install requirements
- name logfiles using timestamp (TODO: a logfile cleaner)
- if both -np and -r were given send to PORT_REPOSITORY instead of pkg_repository
- fix detection of install requirements
2012-09-06 18:10:35 +02:00
dd53d60b85 webbuild: added maintainer mode; URI-encode package names to fix packages with '+' characters; other fixes 2012-09-04 13:05:57 +02:00
c1ed68dd78 autodist-cgi: complete support for multiple defined repositories in AUTOPORT_REPOSITORIES[] 2012-09-04 13:04:11 +02:00
17c9e4d33a Sync with current autodist configuration and cron files on server 2012-09-02 13:24:26 +02:00
a518dbe02a autodist-cgi: add packages links to webbuild page 2012-09-02 13:21:18 +02:00
b36a8a552e webbuild: add backend-side files 2012-09-02 13:18:52 +02:00
b9803712a2 Release 0.9.4 2012-08-16 12:19:51 +02:00
b3e82e19b4 update-specfile: sync to current 2012-08-16 12:13:07 +02:00
e6f4f990e4 Makefile: install legacy file and apply new cron files names 2012-08-16 12:10:13 +02:00
13c5359c92 cron files: distribution agnostic cron files rename 2012-08-16 12:05:18 +02:00
b37324962c autoport: replace AUTOPORT_CGI_SECONDARY with AUTOPORT_CGI_HOST in default configuration template 2012-08-16 11:58:40 +02:00
79e63cd2a3 autodist-tool: remove forgotten debugging code 2012-08-16 11:51:02 +02:00
f842044af6 autodist: configuration update for all archs 2012-08-16 11:49:11 +02:00
1e2ba88e57 autodist: improved management of skipped packages, delayed repository and other small fixes 2012-08-16 11:41:10 +02:00
61a6f72850 autodist-cgi: support for multiple packages jobs with link available for each operation performed (prepare,update,build,install) 2012-08-16 11:38:14 +02:00
cd1132a916 autodist-cgi: implement support for multiple secondary hosts; use AS_HOST=# (0 for root host)
autodist-cgi: implement distributed builds monitoring page using icecream-monitor script
2012-08-01 11:48:43 +02:00
a36d759531 autoport cron: check for autoport pid, not autodist 2012-07-29 10:58:07 +02:00
2ee18817c4 autodist-cgi: add available log files table for build target in SHOWLOG and implement security checks on passed urls 2012-07-29 10:56:54 +02:00
00adf496ba autospec-conf: remove -C option rejected by curl 7.27.0; also remove '--limit-rate 400k -Y 1' 2012-07-29 10:53:20 +02:00
a5f3beda83 distdb: rename xorg_drv_video target to xorg_drv_video_all to allow autoupgrading single package 2012-07-11 22:38:55 +02:00
0be3a1fc97 autodist cgi: lots of improvements in interface output and other fixes 2012-07-11 22:36:11 +02:00
005fe6a6f5 autodist cgi: another fix for showlog on secondary host 2012-07-11 20:28:46 +02:00
25cc256ba5 autoport hourly cron: fix to use new log file naming 2012-07-09 18:51:34 +02:00
7f92f0fd95 cleanold daily cron: clean old files in all autoport configured environments 2012-07-09 18:49:52 +02:00
4a281ed9dc autodist-cgi: print location of ok log file in output log
autodist: sync with current minor changes
2012-07-09 18:48:36 +02:00
761ae3b3fb distdb updates for i586 2012-06-10 19:09:38 +02:00
179121211e autoport-cgi: more basic enhancements
autodist,autoport: better loggin location and internal formatting for parsing
2012-06-09 16:35:51 +02:00
c9da095026 autoport cron: remove some empty lines added to log file 2012-05-26 13:29:20 +02:00
6e2a4ded8c autodist-cgi: add support for local autodist update and some parsing improvements 2012-05-26 13:28:28 +02:00
ada79d6f76 autoport: add '^' log prefix also for staging packages 2012-05-24 17:24:33 +02:00
dbaaa43f7f Release 0.9.3 2012-05-24 16:47:53 +02:00
e6556e1063 autodist cgi: rename from autoport-cgi and fix installation 2012-05-24 16:47:14 +02:00
a4ccca0e26 unstage.arm: updated 2012-05-24 16:41:22 +02:00
11951519dc autoport sysconfig: add AUTOPORT_CGI_SECONDARY in default configuration templated 2012-05-24 16:37:45 +02:00
d2b7713cff autoport, autoport cron: provide a prefix to log lines for parsing by autoport-cgi 2012-05-24 16:35:34 +02:00
2a89f70381 autoport-cgi: add initial cgi script for realtime log information through web server 2012-05-24 16:29:41 +02:00
ba9a55182e autoport: - fix error detecting pkg_milestone introduced with previous optimizations
- don't list up to date packages in batch mode unless -v (verbose) is specified
2012-05-15 16:28:01 +02:00
c624adf788 Release 0.9.2 2012-05-14 13:48:41 +02:00
b5f570cc0b autoport cron: reworked for better logfile management; disable service restarts in chroot mode 2012-05-12 13:43:19 +02:00
c49d56bd9e autoport: optimize get_pkg_buildinfo() calls for speed avoiding unnecessary sourcing of input files 2012-05-10 13:42:05 +02:00
465e63d0ef autoport: don't build missing deps in MILESTONE_REBUILD mode 2012-05-10 10:37:10 +02:00
c97abad872 autoport cron: manage AUTOPORT_CHROOT_USER[] and AUTOPORT_DISABLE[] new variables 2012-05-10 10:35:14 +02:00
2cee9628ea autoport-chroot: added new user tool to make entering autoport chroot environment easier 2012-05-10 10:30:38 +02:00
662 changed files with 128876 additions and 1865 deletions

107
Makefile
View File

@ -1,33 +1,37 @@
# Makefile for autodist
# Copyright (C) 2006-2009 by Silvan Calarco <silvan.calarco@mambasoft.it>
# Copyright (C) 2006-2021 by Silvan Calarco <silvan.calarco@mambasoft.it>
#
PACKAGE = autodist
include VERSION
prefix = /usr
exec_prefix = ${prefix}
sysconfdir = /etc
sbindir = ${exec_prefix}/sbin
bindir = ${exec_prefix}/bin
datadir = ${prefix}/share
initrddir = ${sysconfdir}/rc.d/init.d
mandir = ${prefix}/usr/share/man
sysconfigdir= ${sysconfdir}/sysconfig
configdir = ${sysconfdir}/autodist
localstatedir= /var
piddir= ${localstatedir}/run/autodist
prefix := /usr
exec_prefix := ${prefix}
sysconfdir := /etc
sbindir := ${exec_prefix}/sbin
bindir := ${exec_prefix}/bin
datadir := ${prefix}/share
unitdir := ${prefix}/lib/systemd/system
libexecdir := ${prefix}/libexec
mandir := ${prefix}/usr/share/man
sysconfigdir := ${sysconfdir}/sysconfig
configdir := ${sysconfdir}/autodist
localstatedir := /var
piddir := /run/autodist
cgidir := ${localstatedir}/www/cgi-bin
htmldir := ${localstatedir}/www/html
srcdir = .
DESTDIR =
INSTALL = /usr/bin/install
INSTALL_PROGRAM = ${INSTALL} -m 755
INSTALL_DATA = ${INSTALL} -m 644
INSTALL_DIR = ${INSTALL} -d -m 755
INSTALL_SCRIPT = ${INSTALL_PROGRAM}
INSTALL := /usr/bin/install
INSTALL_PROGRAM := ${INSTALL} -m 755
INSTALL_DATA := ${INSTALL} -m 644
INSTALL_DIR := ${INSTALL} -d -m 755
INSTALL_SCRIPT := ${INSTALL_PROGRAM}
pck_datadir = $(localstatedir)/$(PACKAGE)
pck_datadir = $(datadir)/$(PACKAGE)
pck_statedir = $(localstatedir)/$(PACKAGE)
pck_logdir = $(localstatedir)/$(PACKAGE)/log
distdir = $(PACKAGE)-$(VERSION)
@ -43,47 +47,72 @@ install-dirs:
@$(INSTALL_DIR) $(DESTDIR)$(sysconfdir)/cron.hourly
@$(INSTALL_DIR) $(DESTDIR)$(sysconfdir)/cron.daily
@$(INSTALL_DIR) $(DESTDIR)$(sysconfdir)/sysconfig
@$(INSTALL_DIR) $(DESTDIR)$(sysconfdir)/logrotate.d
@$(INSTALL_DIR) $(DESTDIR)$(bindir)
@$(INSTALL_DIR) $(DESTDIR)$(sbindir)
@$(INSTALL_DIR) $(DESTDIR)$(cgidir)
@$(INSTALL_DIR) $(DESTDIR)$(htmldir)
@$(INSTALL_DIR) $(DESTDIR)$(unitdir)
@$(INSTALL_DIR) $(DESTDIR)$(pck_datadir)
@$(INSTALL_DIR) $(DESTDIR)$(pck_datadir)/template/autoupdate/spec-patches-build/old
@$(INSTALL_DIR) $(DESTDIR)$(pck_datadir)/template/autoupdate/spec-patches-update/old
@$(INSTALL_DIR) $(DESTDIR)$(pck_statedir)
@$(INSTALL_DIR) $(DESTDIR)$(pck_statedir)/template/autoupdate/spec-patches-build/old
@$(INSTALL_DIR) $(DESTDIR)$(pck_statedir)/template/autoupdate/spec-patches-update/old
@$(INSTALL_DIR) $(DESTDIR)$(pck_logdir)/prepare/{ok,failed}
@$(INSTALL_DIR) $(DESTDIR)$(pck_logdir)/update/{ok,failed}
@$(INSTALL_DIR) $(DESTDIR)$(pck_logdir)/build/{ok,failed}
@$(INSTALL_DIR) $(DESTDIR)$(pck_logdir)/install/{ok,failed}
@$(INSTALL_DIR) $(DESTDIR)$(pck_logdir)/send/{ok,failed}
@$(INSTALL_DIR) $(DESTDIR)$(pck_datadir)/RPM/{SPECS,SRPMS,BUILD,SOURCES,RPMS/{noarch,i586,ppc,x86_64,arm}}
@$(INSTALL_DIR) $(DESTDIR)$(piddir)
@$(INSTALL_DIR) $(DESTDIR)$(pck_statedir)/RPM/{SPECS,SRPMS,BUILD,SOURCES,RPMS/{noarch,i586,x86_64,arm,aarch64}}
@$(INSTALL_DIR) $(DESTDIR)$(libexecdir)
@$(INSTALL_DIR) $(DESTDIR)$(localstatedir)/webbuild/{cache,home,notes,tmp,users,uploads}
@$(INSTALL_DIR) $(DESTDIR)$(prefix)/lib/tmpfiles.d/
install-programs:
@$(INSTALL_SCRIPT) autodist $(DESTDIR)$(bindir)/autodist
@$(INSTALL_SCRIPT) autodist-cleanold $(DESTDIR)$(bindir)/autodist-cleanold
@$(INSTALL_SCRIPT) autodist-git $(DESTDIR)$(bindir)/autodist-git
@$(INSTALL_SCRIPT) autodist-inspect $(DESTDIR)$(bindir)/autodist-inspect
@$(INSTALL_SCRIPT) autodist-launcher $(DESTDIR)$(bindir)/autodist-launcher
@$(INSTALL_SCRIPT) autodist-repository $(DESTDIR)$(bindir)/autodist-repository
@$(INSTALL_SCRIPT) autodist-tool $(DESTDIR)$(bindir)/autodist-tool
@$(INSTALL_SCRIPT) autodist-upstream-updates $(DESTDIR)$(bindir)/autodist-upstream-updates
@$(INSTALL_SCRIPT) autoport $(DESTDIR)$(bindir)/autoport
@$(INSTALL_SCRIPT) autoport-chroot $(DESTDIR)$(bindir)/autoport-chroot
@$(INSTALL_SCRIPT) autoport-fix-environment $(DESTDIR)$(bindir)/autoport-fix-environment
@$(INSTALL_SCRIPT) autoport-launcher $(DESTDIR)$(bindir)/autoport-launcher
@$(INSTALL_SCRIPT) automaint $(DESTDIR)$(bindir)/automaint
@$(INSTALL_SCRIPT) etc/autodist/scripts/* $(DESTDIR)$(configdir)/scripts/
@$(INSTALL_SCRIPT) autodist-cgi $(DESTDIR)$(cgidir)/autodist
@$(INSTALL_SCRIPT) webbuild/webbuild-cgi $(DESTDIR)$(cgidir)/webbuild
@$(INSTALL_SCRIPT) webbuild/webbuild-sudo $(DESTDIR)$(libexecdir)/webbuild-sudo
@$(INSTALL_SCRIPT) webbuild/webbuild-checkpassword $(DESTDIR)$(libexecdir)/webbuild-checkpassword
@$(INSTALL_SCRIPT) webbuild/webbuild-functions $(DESTDIR)$(pck_datadir)/webbuild-functions
@$(INSTALL_SCRIPT) webbuild/webbuild-functions-private $(DESTDIR)$(pck_datadir)/webbuild-functions-private
@$(INSTALL_SCRIPT) telegram/openmamba_bot.py $(DESTDIR)$(pck_datadir)/openmamba_bot.py
@$(INSTALL_SCRIPT) telegram/requirements.txt $(DESTDIR)$(pck_datadir)/requirements.txt
@$(INSTALL_SCRIPT) repology-openmamba.py $(DESTDIR)$(pck_datadir)/repology-openmamba.py
@cp -a webbuild/html/* $(DESTDIR)$(htmldir)
install-data:
@$(INSTALL_DATA) etc/autodist/config $(DESTDIR)$(configdir)/config
@$(INSTALL_DATA) etc/autodist/distdb $(DESTDIR)$(configdir)/distdb
@$(INSTALL_DATA) etc/autodist/distdb.i586 $(DESTDIR)$(configdir)/distdb.i586
@$(INSTALL_DATA) etc/autodist/distdb.arm $(DESTDIR)$(configdir)/distdb.arm
@$(INSTALL_DATA) etc/autodist/distdb.x86_64 $(DESTDIR)$(configdir)/distdb.x86_64
@$(INSTALL_DATA) etc/autodist/distdb.ppc $(DESTDIR)$(configdir)/distdb.ppc
@$(INSTALL_DATA) etc/autodist/unstage $(DESTDIR)$(configdir)/unstage
@$(INSTALL_DATA) etc/autodist/unstage.i586 $(DESTDIR)$(configdir)/unstage.i586
@$(INSTALL_DATA) etc/autodist/unstage.arm $(DESTDIR)$(configdir)/unstage.arm
@$(INSTALL_DATA) etc/autodist/unstage.x86_64 $(DESTDIR)$(configdir)/unstage.x86_64
@$(INSTALL_DATA) etc/autodist/unstage.ppc $(DESTDIR)$(configdir)/unstage.ppc
@$(INSTALL_DATA) etc/autodist/distdb.d/*.db $(DESTDIR)$(configdir)/distdb.d/
@$(INSTALL_DATA) etc/autodist/config-git $(DESTDIR)$(configdir)/config-git
@$(INSTALL_DATA) etc/autodist/blacklist $(DESTDIR)$(configdir)/blacklist
@$(INSTALL_DATA) etc/autodist/distdb.d/* $(DESTDIR)$(configdir)/distdb.d/
@$(INSTALL_DATA) etc/sudoers.d/autoport $(DESTDIR)$(sysconfdir)/sudoers.d/autoport
@$(INSTALL_DATA) webbuild/webbuild-sudoers $(DESTDIR)$(sysconfdir)/sudoers.d/webbuild
@$(INSTALL_DATA) webbuild/webbuild-admin $(DESTDIR)$(localstatedir)/webbuild/users/admin.conf
@$(INSTALL_SCRIPT) etc/sysconfig/autoport $(DESTDIR)$(sysconfdir)/sysconfig/autoport
@$(INSTALL_SCRIPT) etc/cron.hourly/65-openmamba-autobuild-autoport $(DESTDIR)$(sysconfdir)/cron.hourly/
@$(INSTALL_SCRIPT) etc/cron.daily/40-openmamba-autodist-cleanold $(DESTDIR)$(sysconfdir)/cron.daily/
@$(INSTALL_DATA) autospec-conf $(DESTDIR)$(pck_datadir)/.autospec
@touch $(DESTDIR)$(pck_datadir)/template/autoupdate/auto.success
@touch $(DESTDIR)$(pck_datadir)/template/autoupdate/auto.skip
@$(INSTALL_SCRIPT) etc/cron.hourly/60-autodist-update $(DESTDIR)$(sysconfdir)/cron.hourly/
@$(INSTALL_SCRIPT) etc/cron.hourly/65-autoport $(DESTDIR)$(sysconfdir)/cron.hourly/
@$(INSTALL_SCRIPT) etc/cron.daily/45-autodist-git-sync $(DESTDIR)$(sysconfdir)/cron.daily/
@$(INSTALL_SCRIPT) etc/logrotate.d/webbuild $(DESTDIR)$(sysconfdir)/logrotate.d/webbuild
@$(INSTALL_DATA) autospec-conf $(DESTDIR)$(pck_statedir)/.autospec
@$(INSTALL_DATA) autodist-bashrc $(DESTDIR)$(pck_statedir)/.bashrc
@$(INSTALL_DATA) autodist-bash_profile $(DESTDIR)$(pck_statedir)/.bash_profile
@$(INSTALL_DATA) autodist-tmpfilesd $(DESTDIR)$(prefix)/lib/tmpfiles.d/autodist.conf
@$(INSTALL_DATA) telegram/openmambabot.service $(DESTDIR)$(unitdir)/openmambabot.service
@touch $(DESTDIR)$(pck_statedir)/template/autoupdate/auto.success
@touch $(DESTDIR)$(pck_statedir)/template/autoupdate/auto.skip
install: \
install-dirs \

View File

@ -1 +1 @@
VERSION = 0.9.1
VERSION = 1.5.4

718
autodist

File diff suppressed because it is too large Load Diff

14
autodist-bash_profile Normal file
View File

@ -0,0 +1,14 @@
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
if [ -d $HOME/bin ]; then
PATH=$PATH:$HOME/bin
fi
export PATH
unset USERNAME

8
autodist-bashrc Normal file
View File

@ -0,0 +1,8 @@
# .bashrc
# User specific aliases and functions
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi

380
autodist-cgi Executable file
View File

@ -0,0 +1,380 @@
#!/bin/bash
. /etc/sysconfig/autoport
. /usr/share/autodist/webbuild-functions
NUM=`echo "$QUERY_STRING" | sed -n 's/^.*NUM=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
HOST=`echo "$QUERY_STRING" | sed -n 's/^.*HOST=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
REP=`echo "$QUERY_STRING" | sed -n 's/^.*REP=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
AS_HOST=`echo "$QUERY_STRING" | sed -n 's/^.*AS_HOST=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
SHOWLOG=`echo "$QUERY_STRING" | sed -n 's/^.*SHOWLOG=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
SHOWINDEX=`echo "$QUERY_STRING" | sed -n 's/^.*SHOWINDEX=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
LINES=`echo "$QUERY_STRING" | sed -n 's/^.*LINES=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
FORMAT=`echo "$QUERY_STRING" | sed -n 's/^.*FORMAT=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
FULL=`echo "$QUERY_STRING" | sed -n 's/^.*FULL=\([^&]*\).*$/\1/p' | sed "s/%20/ /g"`
function resolve_logname() {
local l=$1
local jobname=$2
unset SUBJOBNAME OPERATIONNAME OPERATIONSTATUS
SUBJOBNAME=`echo $l | sed "s|.*/${jobname}_\(.*\)\..*|\1|"`
[ "${SUBJOBNAME:0:1}" = "_" ] && SUBJOBNAME=$l
[ "$SUBJOBNAME" = "$l" ] && SUBJOBNAME=`echo $l | sed "s|.*/\(.*\)\..*|\1|"`
SUBJOBNAME=${SUBJOBNAME/__*}
[ "${BUILDOPERATION[$b]}" ] && \
OPERATIONNAME=${BUILDOPERATION[$b]} || OPERATIONNAME=`echo $l | sed "s|\(.*\)/.*/.*|\1|"`
[ "${BUILDOPERATIONSTATUS[$b]}" ] && \
OPERATIONSTATUS=${BUILDOPERATIONSTATUS[$b]} || OPERATIONSTATUS=`echo $l | sed "s|.*/\(.*\)/.*|\1|"`
}
[ ! "$FORMAT" ] && FORMAT=html
[ "$LINES" ] || LINES=5
[ "$HOST" ] || HOST=0
[ "$AS_HOST" ] || AS_HOST=0
[ "$AS_HOST" -a "$HOST" != "0" ] && HOST_ADD="&HOST=$HOST"
if [ "$AS_HOST" = "0" -a "$FORMAT" = "xml" ]; then
echo -e "Content-type: text/xml\nPragma: no-cache\n"
echo -n "<autodist><output><![CDATA["
RELOADTIME=3600000
else
echo -e "Content-type: text/html; charset=UTF-8\n"
fi
if [ "$SHOWINDEX" ]; then
echo "Host $AS_HOST:"
for i in `seq 0 ${#AUTOPORT_ARCH[*]}`; do
[ "${AUTOPORT_ARCH[$i]}" ] || continue
[ "${AUTOPORT_DISABLE[$i]}" -a "${AUTOPORT_DISABLE[$i]}" != "0" ] && continue
RNUM=-1
for r in ${AUTOPORT_REPOSITORIES[$i]}; do
RNUM=`expr $RNUM + 1`
if [ "${AUTOPORT_UPDATE[$i]}" ]; then
echo "<a href=\"?NUM=$i&REP=$RNUM$HOST_ADD\">$r(${AUTOPORT_ARCH[$i]})</a>&nbsp;"
elif [ "${AUTOPORT_CHROOT[$i]}" ]; then
echo "<a href=\"?NUM=$i&REP=$RNUM$HOST_ADD\">$r(${AUTOPORT_ARCH[$i]})</a>&nbsp;"
elif [ "${AUTOPORT_NATIVE[$i]}" ]; then
echo "<a href=\"?NUM=$i&REP=$RNUM$HOST_ADD\">$r(${AUTOPORT_ARCH[$i]})</a>&nbsp;"
elif [ "${AUTOPORT_CROSS[$i]}" ]; then
echo "<a href=\"?NUM=$i&REP=$RNUM$HOST_ADD\">$r(${AUTOPORT_CROSS[$i]};${AUTOPORT_ARCH[$i]})</a>&nbsp;"
fi
done
done
echo "<br>"
exit 0
elif [ "$AS_HOST" = "0" ]; then
echo "Show: [<a href=\"?NUM=\">All hosts</a>] [<a href=\"?SHOWLOG=monitor\">Build hosts monitor</a>]<br>"
for h in `seq 0 ${#AUTOPORT_CGI_HOST[*]}`; do
curl --connect-timeout 20 "${AUTOPORT_CGI_HOST[$h]}?AS_HOST=$h&SHOWINDEX=1" 2>/dev/null
done
echo "<hr>"
fi
[ ! "$SHOWLOG" -a "$HOST" = "$AS_HOST" ] && echo "<h2>Host: `hostname -s` (`uname -m`, kernel `uname -r`)</h2>"
if [ "$SHOWLOG" -a "$HOST" != "$AS_HOST" ]; then
curl "${AUTOPORT_CGI_HOST[$HOST]}?AS_HOST=$HOST&SHOWLOG=$SHOWLOG&NUM=$NUM&REP=$REP&LOG=$LOG&FULL=$FULL" 2>/dev/null
else
for i in `seq 0 ${#AUTOPORT_ARCH[*]}`; do
if [ "$SHOWLOG" = "monitor" ]; then
echo "<h2>Build hosts monitor</h2>"
icecream-monitor $ICECREAM_MONITOR_HOST listcs | \
while read line; do
[ "${line:0:8}" = "200 done" ] && printon=
if [ "$printon" ]; then
set -- $line
case $2 in
\(*) echo "<b>$line</b><br>" ;;
*) echo "$line<br>" ;;
esac
fi
[ "${line:0:6}" = "listcs" ] && printon=1
done
echo "<br>"
RELOADTIME=15000
break
fi
RNUM=-1
for r in ${AUTOPORT_REPOSITORIES[$i]}; do
[ "${AUTOPORT_ARCH[$i]}" ] || continue
[ "${AUTOPORT_DISABLE[$i]}" -a "${AUTOPORT_DISABLE[$i]}" != "0" ] && continue
RNUM=`expr $RNUM + 1`
LOGDIR=`environment_logdir $i`
AUTOPORTLOGDIR=`environment_autoport_logdir $i`
ENVROOTDIR=`environment_rootdir $i`
if [ "${AUTOPORT_UPDATE[$i]}" ]; then
LOGFILE="$LOGDIR/autodist.log"
LASTLOGFILE="$LOGDIR/autodist-last.log"
STATEFILE="$LOGDIR/autoupdate-current"
LASTSTATEFILE="$LOGDIR/autoupdate-last"
elif [ "${AUTOPORT_CHROOT[$i]}" ]; then
LOGFILE="/var/autodist/log/autoport-chroot-$r-${AUTOPORT_CHROOT[$i]}.log"
LASTLOGFILE="/var/autodist/log/autoport-chroot-$r-${AUTOPORT_CHROOT[$i]}-last.log"
AUTODISTLOGFILE="$AUTOPORTLOGDIR/${AUTOPORT_ARCH[$i]}/$r-current.log"
AUTODISTSTATEFILE="$AUTOPORTLOGDIR/autoport-$r-current"
elif [ "${AUTOPORT_NATIVE[$i]}" ]; then
LOGFILE="/var/autodist/log/autoport-native-$r-${AUTOPORT_ARCH[$i]}.log"
LASTLOGFILE="/var/autodist/log/autoport-native-$r-${AUTOPORT_ARCH[$i]}-last.log"
AUTODISTLOGFILE="$AUTOPORTLOGDIR/${AUTOPORT_ARCH[$i]}/$r-current.log"
AUTODISTSTATEFILE="$AUTOPORTLOGDIR/autoport-$r-current"
elif [ "${AUTOPORT_CROSS[$i]}" ]; then
LOGFILE="$LOGDIR/autoport-cross-$r-${AUTOPORT_CROSS[$i]}.log"
LASTLOGFILE="$LOGDIR/autoport-cross-$r-${AUTOPORT_CROSS[$i]}-last.log"
else
continue
fi
if [ "$SHOWLOG" ]; then
if [ "$HOST" = "$AS_HOST" -a "$NUM" = "$i" -a "$REP" = "$RNUM" ]; then
echo -n "<p><h2>$SHOWLOG log in "
if [ "${AUTOPORT_UPDATE[$i]}" ]; then
echo -n "update"
elif [ "${AUTOPORT_CHROOT[$i]}" ]; then
echo -n "${AUTOPORT_CHROOT[i]} chroot"
elif [ "${AUTOPORT_NATIVE[$i]}" ]; then
echo -n "native"
elif [ "${AUTOPORT_CROSS[$i]}" ]; then
echo -n "cross"
fi
echo " environment for ${AUTOPORT_ARCH[$i]}"
[ "${SHOWLOG}" = "current" -o "${SHOWLOG}" = "last" -a ! "${AUTOPORT_UPDATE[$i]}" ] && echo -n " ($r)"
echo -n ":</h2>"
cat << _EOF
<div class="downloadbox" align="center">
<div class="output outputbox">
_EOF
echo -n "<pre><code>"
if [ "$SHOWLOG" = "current" ]; then
RELOADTIME=3600000
cat $LOGFILE | parse_build_output
elif [ "$SHOWLOG" = "last" ]; then
cat $LASTLOGFILE | parse_build_output
LASTLOGDETAILS=`tail $LASTLOGFILE | grep "See .* for details" | sed "s|.*See \(.*\) for details.*|\1|"`
cat $ENVROOTDIR/$LASTLOGDETAILS | parse_build_output
else
# Security check
[ "${SHOWLOG/\/\.}" != "${SHOWLOG}" ] && continue
BUILDLOGDIR="$LOGDIR"
if [ "${SHOWLOG/\/ok\/}" != "${SHOWLOG}" -o "${SHOWLOG/\failed\/}" != "${SHOWLOG}" ]; then
SHOWLOGPKG=${SHOWLOG/*\/}
[ "${SHOWLOGPKG}" ] || continue
echo "<table style=\"color:black;width:auto;\"><tr><td colspan=3>Last ${SHOWLOGPKG} logs:</td>"
for t in prepare update build install send; do
echo -n "<tr><td>$t:</td><td>"
[ -e ${BUILDLOGDIR}${t}/ok/${SHOWLOGPKG} ] && echo -n "<td><a style=\"color:green;text-decoration:none\" target=_autodist href=\"?NUM=$i&REP=$RNUM$HOST_ADD&SHOWLOG=${t}/ok/${SHOWLOGPKG}\">OK</a></td>" || echo "<td></td>"
[ -e ${BUILDLOGDIR}${t}/failed/${SHOWLOGPKG} ] && echo -n "<td><a style=\"color:green;text-decoration:none\" target=_autodist href=\"?NUM=$i&REP=$RNUM$HOST_ADD&SHOWLOG=${t}/failed/${SHOWLOGPKG}\">FAILED</a></td>" || echo "<td></td>"
echo "</tr>"
done
echo "</table>"
fi
if [ -r ${BUILDLOGDIR}${SHOWLOG} ]; then
LOGFILESIZE=`stat -c %s ${BUILDLOGDIR}${SHOWLOG}`
LOGDATE=`stat -c %y ${BUILDLOGDIR}${SHOWLOG}`
echo -n "<b>${SHOWLOG} ($LOGDATE; $LOGFILESIZE):</b>"
if [ $LOGFILESIZE -lt 2097152 -o "$FULL" != "" ]; then
cat ${BUILDLOGDIR}${SHOWLOG} | parse_build_output
else
head -c 1048576 ${BUILDLOGDIR}${SHOWLOG} | parse_build_output
echo "<br><font style=\"background-color:yellow;color:black\">&lt;------ CUT (long file) ------&gt;</font>"
tail -c 1048576 ${BUILDLOGDIR}${SHOWLOG} | parse_build_output
fi
fi
fi
echo -n "</pre></code>"
echo -n "</div></div>"
# break
fi
[ "${AUTOPORT_UPDATE[$i]}" ] && break
elif [ ! "$SHOWLOG" ]; then
RELOADTIME=600000
[[ "$NUM" && "$NUM" != "$i" ]] && continue
[[ "$HOST" = "$AS_HOST" ]] || continue
if [ "${AUTOPORT_UPDATE[$i]}" ]; then
echo "<b>* <a target=_autodist href=\"?NUM=$i&REP=$RNUM&HOST=$AS_HOST\">$r</a>(${AUTOPORT_ARCH[$i]}) (type:autodist update)"
echo " [ <a target=_autodist href=\"?SHOWLOG=current&NUM=$i&REP=$RNUM$HOST_ADD\">log</a> <a target=_autodist href=\"?SHOWLOG=last&NUM=$i&REP=$RNUM$HOST_ADD\">last</a> ]</b>"
fi
if [ "${AUTOPORT_CHROOT[$i]}" ]; then
echo "<b>* <a target=_autodist href=\"?NUM=$i&REP=$RNUM&HOST=$AS_HOST\">$r</a>(${AUTOPORT_ARCH[$i]}) (type:chroot autoport</a> chroot:${AUTOPORT_CHROOT[$i]})"
echo " [ <a target=_autodist href=\"?SHOWLOG=current&NUM=$i&REP=$RNUM$HOST_ADD\">log</a> <a target=_autodist href=\"?SHOWLOG=last&NUM=$i&REP=$RNUM$HOST_ADD\">last</a> ]</b>"
fi
if [ "${AUTOPORT_NATIVE[$i]}" ]; then
echo "<b>* <a target=_autodist href=\"?NUM=$i&REP=$RNUM&HOST=$AS_HOST\">$r</a>(${AUTOPORT_ARCH[$i]}) (type:native autoport)"
echo " [ <a target=_autodist href=\"?SHOWLOG=current&NUM=$i&REP=$RNUM$HOST_ADD\">log</a> <a target=_autodist href=\"?SHOWLOG=last&NUM=$i&REP=$RNUM$HOST_ADD\">last</a> ]</b>"
fi
if [ "${AUTOPORT_CROSS[$i]}" ]; then
echo "<b>* <a target=_autodist href=\"?NUM=$i&REP=$RNUM&HOST=$AS_HOST\">cross-platform</a> autoport (arch:${AUTOPORT_CROSS[$i]})</b>"
echo " [ <a target=_autodist href=\"?SHOWLOG=current&NUM=$i&REP=$RNUM$HOST_ADD\">last</a> ]</b>"
fi
cat << _EOF
<div class="downloadbox" align="center">
<div align="left" class="showlogbox">
_EOF
echo -n "<pre style='margin:1px;word-wrap:normal;white-space:pre;'>"
unset BUILDNOWIDX BUILDLOG BUILDNOW BUILDNOWSTATUS SCHEDULED STARTTIME AUTODIST_PID ENDTIME
if [ "${AUTOPORT_UPDATE[$i]}" ]; then
BUILDNOWIDX=0
STARTTIME=`head $LOGFILE | grep "%% Autodist started" | sed "s|.* @ ||"`
AUTODIST_PID=`head $LOGFILE | grep "%% Autodist started" | sed "s|.*PID \([0-9]*\) .*|\1|"`
SCHEDULED=`head $LOGFILE | grep "%% autoupdate jobs:" | sed "s|.*autoupdate jobs: ||"`
ENDTIME=`tail $LOGFILE | grep "%% All jobs done @" | sed "s|.*@ ||"`
while read line; do
set -- $line
for c in `seq 0 ${#BUILDNOW[*]}`; do
if [ "${BUILDNOW[c]}" = "$1" ]; then
BUILDNOWIDX=$c
break
else
BUILDNOWIDX=$c
fi
done
BUILDNOW[$BUILDNOWIDX]="$1"
[ "$4" ] && BUILDLOG[$BUILDNOWIDX]="${BUILDLOG[$BUILDNOWIDX]} `echo $4 | sed "s|.*autodist/log/||"`"
# BUILDLOG[$BUILDNOWIDX]="${BUILDLOG[$BUILDNOWIDX]} $2/$3/$1.i586"
BUILDNOWSTATUS[$BUILDNOWIDX]=$3
BUILDNOWIDX=`expr $BUILDNOWIDX + 1`
done < $STATEFILE
else
STARTTIME=`head $LOGFILE | grep "^+ .*start at " | sed "s|.*start at ||"`
# AUTODIST_PID=`head $LOGFILE | grep "%% Autodist started" | sed "s|.*PID \([0-9]*\) .*|\1|"`
SCHEDULED=`head -n 40 $LOGFILE | grep -m 1 "^> .*Scheduled jobs: " | sed "s|.*Scheduled jobs: ||"`
ENDTIME=`tail $LOGFILE | grep "^- .*end at " | sed "s|.*end at ||"`
if [ -e "$AUTODISTSTATEFILE" ]; then
while read line; do
set -- $line
for c in `seq 0 ${#BUILDNOW[*]}`; do
if [ "${BUILDNOW[c]}" = "$1" ]; then
BUILDNOWIDX=$c
break
else
BUILDNOWIDX=$c
fi
done
BUILDNOW[$BUILDNOWIDX]="$1"
if [ "$4" ]; then
BUILDLOG[$BUILDNOWIDX]="${BUILDLOG[$BUILDNOWIDX]} `echo $4 | sed "s|.*/log/||"`"
else
if [ "$2" = "port" ]; then
CURRLOGFILE=build/$3/$1.${AUTOPORT_ARCH[$i]}
else
CURRLOGFILE=$2/$3/$1.${AUTOPORT_ARCH[$i]}
fi
BUILDLOG[$BUILDNOWIDX]="${BUILDLOG[$BUILDNOWIDX]} $CURRLOGFILE"
fi
# BUILDLOG[$BUILDNOWIDX]="${BUILDLOG[$BUILDNOWIDX]} $2/$3/$1.i586"
BUILDNOWSTATUS[$BUILDNOWIDX]=$3
BUILDNOWIDX=`expr $BUILDNOWIDX + 1`
done < $AUTODISTSTATEFILE
for p in `dirname $LOGFILE`/current.*; do
CURRENT_FILE=`basename $p`
AUTODIST_PID=${p/*.}
grep "autodist" /proc/$AUTODIST_PID/status &>/dev/null && break
AUTODIST_PID=
done
fi
fi
[ "$STARTTIME" ] && echo "<b>Start:</b> $STARTTIME"
[ "$SCHEDULED" ] && echo "<b>Scheduled jobs:</b> $SCHEDULED"
LASTJOBNAME=
for b in `seq 0 ${#BUILDNOW[*]}`; do
# set -- ${BUILDNOW[$b]}
JOBNAME=${BUILDNOW[$b]}
[ "$JOBNAME" ] || continue
if [ "$JOBNAME" != "$LASTJOBNAME" ]; then
[ "$LASTJOBNAME" -a "$JOBNAME" ] && echo
if [ "${BUILDLOG[$b]}" ]; then
resolve_logname ${BUILDLOG[$b]/* } $JOBNAME
if [ "${OPERATIONSTATUS}" = "ok" ]; then
WEBBUILD_APPEND="&LOGSTATUSOK=true"
else
WEBBUILD_APPEND="&LOGSTATUSOK=false"
fi
echo -n "<a target=_webbuild href=\"$AUTOPORT_WEBBUILD_HOST?REQUEST=autobuildedit&ENVIRONMENT=$i&PACKAGE=$JOBNAME&LOGTYPE=$OPERATIONNAME${WEBBUILD_APPEND}\"><b>$JOBNAME</b></a>: "
else
echo -n "<a target=_webbuild href=\"$AUTOPORT_WEBBUILD_HOST?ENVIRONMENT=$i&PACKAGE=$JOBNAME\"><b>$JOBNAME</b></a>: "
fi
fi
rowcnt=0
if [ "${BUILDLOG[$b]}" ]; then
for l in ${BUILDLOG[$b]}; do
resolve_logname $l $JOBNAME
# if [ $rowcnt -ge 4 ]; then
# echo
# rowcnt=0
# fi
case $OPERATIONNAME-$OPERATIONSTATUS in
build-ok|send-ok|install-ok|retryinstall-ok)
echo -n "<a target=_autodist href=\"?SHOWLOG=$l&NUM=$i&REP=$RNUM$HOST_ADD\">$OPERATIONNAME:$OPERATIONSTATUS</a>"
;;
update-failed|autoupdate-failed)
if [ "${BUILDNOWSTATUS[$b]}" = "4" ]; then
echo -n "<a target=_autodist href=\"?SHOWLOG=$l&NUM=$i&REP=$RNUM$HOST_ADD\"><font color=green>$OPERATIONNAME:up-to-date</font></a>"
elif [ "${BUILDNOWSTATUS[$b]}" = "3" ]; then
echo -n "<a target=_autodist href=\"?SHOWLOG=$l&NUM=$i&REP=$RNUM$HOST_ADD\"><font color=darkgoldenrod>$OPERATIONNAME:unknown</font></a>"
elif [ "${BUILDNOWSTATUS[$b]}" = "2" ]; then
echo -n "<a target=_autodist href=\"?SHOWLOG=$l&NUM=$i&REP=$RNUM$HOST_ADD\"><font color=darkgoldenrod>$OPERATIONNAME:newer</font></a>"
else
echo -n "<a target=_autodist href=\"?SHOWLOG=$l&NUM=$i&REP=$RNUM$HOST_ADD\"><font color=red>$OPERATIONNAME:$OPERATIONSTATUS</font></a>"
fi
;;
*-ok) echo -n "<a target=_autodist href=\"?SHOWLOG=$l&NUM=$i&REP=$RNUM$HOST_ADD\"><font color=black>$OPERATIONNAME:$OPERATIONSTATUS</font></a>"
;;
*)
echo -n "<a target=_autodist href=\"?SHOWLOG=$l&NUM=$i&REP=$RNUM$HOST_ADD\"><font color=red>$OPERATIONNAME:$OPERATIONSTATUS</font></a>"
;;
esac
# [ "$SUBJOBNAME" != "$JOBNAME" ] && echo -en "(<a href=\"$AUTOPORT_WEBBUILD_HOST?ENVIRONMENT=$i&PACKAGE=$SUBJOBNAME\" target=\"webbuild\">$SUBJOBNAME</a>)"
echo -n " "
rowcnt=`expr $rowcnt + 1`
done
fi
if [[ $b -eq $BUILDNOWIDX-1 && ! "$ENDTIME" ]]; then
echo -n "<font color=green>${BUILDOPERATION[$b]}(in progress...)</font>"
fi
LASTJOBNAME=$JOBNAME
done
[ "$LASTJOBNAME" ] && echo
if [ "$ENDTIME" ]; then
echo "<b>End:</b> $ENDTIME"
elif [ "$AUTODIST_PID" ]; then
echo "<b>End: <a target=_autodist href=\"?SHOWLOG=current.$AUTODIST_PID&NUM=$i&REP=$RNUM$HOST_ADD\">in progress</a></b>"
fi
echo
# grep -v "^=" $LOGFILE | tail -n "$LINES" | sed "s|.*\r||"
# echo
echo "</pre></div></div>"
fi
done
done
# only root host (0) calls other hosts
if [ "$AS_HOST" = "0" -a ! "$SHOWLOG" ]; then
for h in `seq 1 ${#AUTOPORT_CGI_HOST[*]}`; do
WBHOSTURL=`echo ${AUTOPORT_CGI_HOST[$h]} | sed "s|^\(http[s]*://[^/]*\).*$|\1|"`
if [ "$WBHOSTURL" ]; then
curl -m1 -s -I ${WBHOSTURL} >/dev/null || continue
if [ "$NUM" -a "$HOST" = "$h" ]; then
curl "${AUTOPORT_CGI_HOST[$h]}?AS_HOST=$h&LINES=$LINES&NUM=$NUM&REP=$RNUM&HOST=$HOST" 2>/dev/null
elif [ ! "$NUM" ]; then
curl "${AUTOPORT_CGI_HOST[$h]}?AS_HOST=$h&LINES=$LINES" 2>/dev/null
fi
fi
done
fi
fi
if [ "$AS_HOST" = "0" ]; then
echo "<p><i>Generated by autodist CGI interface. Last update: `date`</i>"
if [ "$FORMAT" = "xml" ]; then
echo -n "]]></output>"
[ "$RELOADTIME" ] && echo -n "<reloadtime>$RELOADTIME</reloadtime>"
echo "</autodist>"
fi
fi

63
autodist-cleanold Executable file
View File

@ -0,0 +1,63 @@
#!/bin/bash
[ -e /etc/autodist/config ] && . /etc/autodist/config
[ -e /etc/sysconfig/autoport ] && . /etc/sysconfig/autoport
[ "${RPMS_CTIME_OLD}" -a "${SRPMS_CTIME_OLD}" -a "${SOURCES_CTIME_OLD}" \
-a "${BUILD_CTIME_OLD}" -a "${TMP_CTIME_OLD}" ] || {
echo "autodist-cleanold: ERROR: *_CTIME_OLD variables need to be set in config; cleaning skipped."
exit 0
}
function clean() {
dir=$1
[ "$VERBOSE" ] && echo "Cleaning from base directory $dir..."
[ -e $dir/ ] && find $dir/ -mindepth 1 -maxdepth 1 -name "pipe\:\[*" -exec rm -f {} \;
[ -e $dir/RPM/SPECS/ ] && find $dir/RPM/SPECS/ -mindepth 1 -maxdepth 1 -type f -not -name "*.spec*" -exec rm -f {} \;
for arch in ${AUTODIST_ARCHS[*]}; do
[ -e $dir/RPM/RPMS/$arch/ ] && find $dir/RPM/RPMS/$arch/ -mindepth 1 -maxdepth 1 -type f -mtime ${RPMS_CTIME_OLD} -exec rm -f {} \;
done
[ -e $dir/RPM/RPMS/noarch/ ] && find $dir/RPM/RPMS/noarch/ -mindepth 1 -maxdepth 1 -type f -mtime ${RPMS_CTIME_OLD} -exec rm -f {} \;
if [ -e $dir/RPM/BUILD/ ]; then
find $dir/RPM/BUILD/ -mindepth 1 -maxdepth 1 -type d -ctime ${BUILD_CTIME_OLD} -exec rm -rf {} \;
# delete older package duplicates
find $dir/RPM/BUILD/ -maxdepth 1 | grep -V SPECPARTS | sort -V | \
while read curr; do
if [ "${curr/-[0-9._]*}" = "${last/-[0-9._]*}" -a "${last}" ]; then
rm -rf $last
fi
last=$curr;
done
fi
[ -e $dir/RPM/SOURCES/ ] && {
find $dir/RPM/SOURCES/ -mindepth 1 -maxdepth 1 -type f -ctime ${SOURCES_CTIME_OLD} -a ! -name "*.patch" -exec rm -rf {} \;
find $dir/RPM/SOURCES/ -mindepth 1 -maxdepth 1 -type f -ctime ${SOURCES_ARCHIVES_CTIME_OLD} -a -name "*.tar.xz" -exec rm -rf {} \;
find $dir/RPM/SOURCES/ -mindepth 1 -maxdepth 1 -type f -ctime ${SOURCES_ARCHIVES_CTIME_OLD} -a -name "*.tar.bz2" -exec rm -rf {} \;
find $dir/RPM/SOURCES/ -mindepth 1 -maxdepth 1 -type f -ctime ${SOURCES_ARCHIVES_CTIME_OLD} -a -name "*.tar.gz" -exec rm -rf {} \;
find $dir/RPM/SOURCES/ -mindepth 1 -maxdepth 1 -type f -ctime ${SOURCES_PATCH_CTIME_OLD} -a -name "*.patch" -exec rm -rf {} \;
}
[ -e $dir/RPM/SRPMS/ ] && find $dir/RPM/SRPMS/ -mindepth 1 -maxdepth 1 -type f -mtime ${SRPMS_CTIME_OLD} -exec rm -f {} \;
}
for i in `seq 0 ${#AUTOPORT_ARCH[*]}`; do
if [ "${AUTOPORT_CHROOT[$i]}" ]; then
a=${AUTOPORT_CHROOT[$i]}
clean /var/autoport/$a/usr/src
[ -e /var/autoport/$a/var/autodist/RPM/RPMS/ ] && \
clean /var/autoport/$a/var/autodist
[ -e /var/autoport/$a/var/tmp/autodist ] && \
find /var/autoport/$a/var/tmp/autodist/ -mindepth 1 -maxdepth 1 -type f -ctime ${TMP_CTIME_OLD} -exec rm -rf {} \;
find /var/autoport/$a/tmp/ -mindepth 1 -maxdepth 1 -type f -ctime ${TMP_CTIME_OLD} -exec rm -rf {} \;
autoport-chroot $a ccache -C
elif [ "${AUTOPORT_UPDATE[$i]}" ]; then
clean /var/autodist
find /var/autodist-tmp/ -mindepth 1 -maxdepth 1 -ctime ${TMP_CTIME_OLD} -exec rm -rf {} \;
sudo -u autodist ccache -C
sudo -u autodist yarn cache clean
elif [ "${AUTOPORT_NATIVE[$i]}" -a "${AUTOPORT_CHROOT_USER[$i]}" ]; then
WORKINGHOME=`getent passwd ${AUTOPORT_CHROOT_USER[$i]} | cut -d: -f6`
if [ -e $WORKINGHOME ]; then
clean $WORKINGHOME
fi
find /var/autodist-tmp/ -mindepth 1 -maxdepth 1 -ctime ${TMP_CTIME_OLD} -exec rm -rf {} \;
fi
done

365
autodist-git Executable file
View File

@ -0,0 +1,365 @@
#!/usr/bin/python3
import argparse
import glob
import os
import re
import rpm
import subprocess
import tempfile
from shutil import copyfile
from pyrpm.spec import Spec, replace_macros
from gitea import *
from git import Repo
from functools import cmp_to_key
from configobj import ConfigObj
cfg = ConfigObj(infile='/etc/autodist/config-git')
gitea = Gitea(cfg["GITEA_URL"], cfg["GITEA_TOKEN"])
org = Organization.request(gitea, cfg["GITEA_ORGANIZATION"])
# argparse options
options = None
def comparePkgInfo(item1, item2):
return rpm.labelCompare(
(str(item1['e']), item1['v'], item1['r']),
(str(item2['e']), item2['v'], item2['r']))
def giteaGetRepoTags(repo_name):
try:
path = f'/repos/{cfg["GITEA_ORGANIZATION"]}/{repo_name}/tags'
return gitea.requests_get(path)
except NotFoundException:
return None
def giteaGetRepository(repo_name):
try:
path = f'/repos/{cfg["GITEA_ORGANIZATION"]}/{repo_name}'
result = gitea.requests_get(path)
return Repository.parse_response(gitea, result)
except NotFoundException:
return None
def findOrCreateRepo(pkg_name, pkg_description=None, create=True):
# Replace '+' for repository name as it is not allowed
repo_name = pkg_name.replace('+','Plus')
# Get gitea repository instance
gitea_repo = giteaGetRepository(repo_name)
if gitea_repo is not None:
return gitea_repo
# Return None if requested to not create
if not create:
return None
# Repository does not exist -> create
org.create_repo(
repoName=repo_name,
description=pkg_description,
private=False,
autoInit=True,
gitignores=None,
# license=spec.license,
# readme=spec.description,
issue_labels=None,
default_branch="main",
)
gitea_repo = giteaGetRepository(repo_name)
return gitea_repo
def commitReleaseFromDir(pkg_info, gitea_repo, repo, temp_dir):
global options
src_dir = pkg_info["src"]
if src_dir.endswith(".src.rpm"):
# src is a SRPM, use autospec to extract in a temporary folder
#print(f'Extracting {pkg_info["name"]} release {pkg_info["v"]}-{pkg_info["r"]} from {pkg_info["src"]}...')
src_temp_dir = tempfile.TemporaryDirectory()
src_dir = src_temp_dir.name
subprocess.run(["autospec", "-x", pkg_info["src"], f'--destdir={src_dir}'],
stdout=subprocess.PIPE)
# Delete binary source archives
for pattern in [
'*.zip','*.tar.bz2','*.tar.xz','*.tar.gz','*.tgz','*.txz','*.iso',
'*.run','*.dll','*.bin','*.jar','*.msi']:
for filename in glob.glob(f'{src_dir}/{pattern}'):
os.remove(filename)
# Parse spec file
spec = Spec.from_file(f'{src_dir}/{pkg_info["name"]}.spec')
#specfiletemp_dir = tempfile.TemporaryDirectory()
#spec = Specfile(f'{src_dir}/{pkg_info["name"]}.spec',
# sourcedir=specfiletemp_dir.name)
# Get used information from specfile
commit_text = ""
header_split = []
commit_user = cfg["COMMITTER_USER"]
commit_email = cfg["COMMITTER_EMAIL"]
for c in spec.changelog.split('\n'):
if c == "":
break
if c[0:2] == "* ":
header_split = c.split(" ")
# Get committer name end email from changelog
commit_user = " ".join(header_split[5:len(header_split)-2])
commit_email = header_split[-2][1:-1]
else:
if commit_text != "":
commit_text += "\n"
if c[0:2] == "- ":
commit_text += c[2:]
else:
commit_text += c
commit_text = f'{commit_text} [release {header_split[-1]};' + \
f'{header_split[1]} {header_split[2]} {header_split[3]} {header_split[4]}]'
# Remove commented sections following spec description
spec_description = ""
if spec.description is not None:
for line in spec.description.split("\n"):
if line.startswith("#"):
break
if spec_description != "":
spec_description += '\n'
spec_description += line
spec_description = replace_macros(spec_description, spec)
# Set/update gitea repository description and website url
spec_url = replace_macros(spec.url, spec)
spec_summary = replace_macros(spec.summary, spec)
if gitea_repo.description != spec_summary or gitea_repo.website != spec_url:
gitea_repo.description = spec_summary
gitea_repo.website = spec_url
gitea_repo.commit()
# Check if tag already exists
new_tag = f'{pkg_info["v"]}-{pkg_info["r"]}'.replace('~','+')
if new_tag in repo.tags:
if options.verbose:
print(f'Skipping {pkg_info["name"]} release '
f'{pkg_info["e"]}:{pkg_info["v"]}-{pkg_info["r"]}: tag {new_tag} already exists')
return
# Create/update README.md
with open(f'{temp_dir.name}/README.md', "w") as readme_file:
readme_file.write(f"# {pkg_info['name']}\n\n{spec_description}")
repo.index.add(['README.md'])
# Update files
dir_list = os.listdir(src_dir)
for dir_file in dir_list:
copyfile(f'{src_dir}/{dir_file}',
f'{temp_dir.name}/{dir_file}')
# Add/modify files
repo.index.add([dir_file])
# Remove deleted files
temp_dir_list = os.listdir(temp_dir.name)
for temp_dir_file in temp_dir_list:
if temp_dir_file == ".git" or temp_dir_file == "README.md":
continue
if not temp_dir_file in dir_list:
repo.index.remove([temp_dir_file], working_tree = True)
# Set committer user and email
repo.config_writer().set_value("user", "name", commit_user).release()
repo.config_writer().set_value("user", "email", commit_email).release()
# Commit
print(f'Committing {pkg_info["name"]} release {new_tag}...')
repo.index.commit(commit_text)
#origin = repo.remote(name='origin')
#origin.push()
# Create and commit tag
repo.create_tag(new_tag, message=f'Release {new_tag}')
#origin.push(new_tag)
def findAndCommitPackageReleases(pkgname, pkgvr):
global options
print(f'Processing package {pkgname} on {cfg["GITEA_URL"]}...')
pkgs_info = []
# Find from archive dir
pkgnamere = pkgname.replace('+','\+')
dirs = [f for f in os.listdir(f'{cfg["ARCHIVE_DIR"]}/{pkgname[0:1]}') if re.match(f'{pkgnamere}-[^-]*-[^-]*$', f)]
for dir in dirs:
pkg_dir = f'{cfg["ARCHIVE_DIR"]}/{pkgname[0:1]}/{dir}'
spec = Spec.from_file(f'{pkg_dir}/{pkgname}.spec')
parts = re.split(f'{pkgnamere}-([^-]*)-([^-]*)$', dir)
epoch = 0 if spec.epoch is None else int(spec.epoch)
version = parts[1]
release = parts[2]
pkgs_info.append(
{'name': pkgname, 'e': epoch, 'v': version, 'r': release, 'src': pkg_dir})
# Find from OLD_DIR
dirs = [f for f in os.listdir(f'{cfg["OLD_DIR"]}') if re.match(f'{pkgnamere}_[0-9]*.[0-9]*$', f)]
for dir in dirs:
srpms_list = glob.glob(f'{cfg["OLD_DIR"]}/{dir}/{pkgname}-*.src.rpm')
for srpm in srpms_list:
parts = re.split('.*-([^-]*)-([^-]*).src.rpm$', srpm)
epoch = subprocess.run(['rpm', '-q', '--queryformat=%{epoch}', '-p', srpm],
stdout=subprocess.PIPE).stdout.decode('utf-8')
# result is "(none)" if no Epoch is set
if len(epoch) > 2:
epoch = "0"
version = parts[1]
release = parts[2]
pkgs_info.append(
{'name': pkgname, 'e': epoch, 'v': version, 'r': release, 'src': srpm})
# Find from SRPMS_DIR
srpms_list = [f for f in os.listdir(cfg["SRPMS_DIR"]) if re.match(f'{pkgnamere}-[^-]*-[^-]*$', f)]
for srpm in srpms_list:
src_path = f'{cfg["SRPMS_DIR"]}/{srpm}'
parts = re.split('.*-([^-]*)-([^-]*).src.rpm$', srpm)
epoch = subprocess.run(['rpm', '-q', '--queryformat=%{epoch}', '-p', src_path],
stdout=subprocess.PIPE).stdout.decode('utf-8')
# result is "(none)" if no Epoch is set
if len(epoch) > 2:
epoch = "0"
version = parts[1]
release = parts[2]
pkgs_info.append(
{'name': pkgname, 'e': epoch, 'v': version, 'r': release, 'src': src_path })
# Sort releases
pkgs_info.sort(key=cmp_to_key(comparePkgInfo))
# Find or create and get repository instance
gitea_repo = findOrCreateRepo(pkgname)
# Clone repository to temporary folder
repo_url = f'{cfg["GITEA_SSH_URL"]}{gitea_repo.name}.git'
temp_dir = tempfile.TemporaryDirectory()
repo = Repo.clone_from(repo_url, temp_dir.name)
# Set to push annotated tags with commits
repo.config_writer().set_value('push', 'followTags', 'true').release()
new_commits = False
for pkg_info in pkgs_info:
vr = f'{pkg_info["v"]}-{pkg_info["r"]}'
if pkgvr is not None and pkgvr != vr:
continue
# Check if tag already exists
new_tag = f'{vr}'.replace('~','+')
if new_tag in repo.tags:
if options.verbose:
print(f'Skipping {pkgname} release '
f'{pkg_info["e"]}:{vr}: tag {new_tag} already exists')
continue
#for line in sys.stdin:
# line = line.rstrip()
# break
#exit(1)
#pkg_dir = f'{cfg["ARCHIVE_DIR"]}/{pkgname[0:1]}/{pkgname}-{vr}'
commitReleaseFromDir(pkg_info, gitea_repo, repo, temp_dir)
new_commits = True
if new_commits:
print(f"Pushing commits and tags for {pkgname}...")
origin = repo.remote(name='origin')
origin.push()
else:
print(f"No new commits for {pkgname}.")
temp_dir.cleanup()
def main():
global options
parser = argparse.ArgumentParser(prog='autodist-git',
description='RPM repository sync and management with git service.',
epilog="Copyright (c) 2023-2024 by Silvan Calarco <silvan.calarco@mambasoft.it> - GPL v3 License")
subparsers = parser.add_subparsers(help='sub-command help', dest='mode')
parser.add_argument('-v', '--verbose', help="verbose output", action='store_true')
parser_syncpkg = subparsers.add_parser('syncpkg', help="sync a specified package")
parser_syncpkg.add_argument('pkgname', help="name of package")
parser_syncpkg.add_argument('pkgver', help="version of package", nargs='?')
parser_syncpkg.add_argument('-d', '--delete', action='store_true', help="delete and recreate existing repository",
required=False)
parser_syncrepo = subparsers.add_parser('syncrepo', help="sync base repository with git server")
parser_syncrepo.add_argument('--from', dest='frompkg', help="from package name", required=False)
parser_syncrepo.add_argument('--to', dest='topkg', help="to package name", required=False)
parser_syncrepo.add_argument('-d', '--delete', action='store_true', help="delete and recreate existing repositories",
required=False)
try:
options = parser.parse_args()
except:
exit(1)
if options.mode == 'syncpkg':
if options.delete:
if options.pkgver is not None:
print("ERROR: specifying pkgver is not allowed with -d option")
exit(1)
repo_name = options.pkgname.replace('+','Plus')
gitea_repo = giteaGetRepository(repo_name)
if gitea_repo is not None:
print(f'Deleting repository for {options.pkgname}...')
gitea_repo.delete()
findAndCommitPackageReleases(options.pkgname, options.pkgver)
elif options.mode == 'syncrepo':
dir_list = sorted(filter(os.path.isfile, glob.glob(f'{cfg["SRPMS_DIR"]}/*.src.rpm')))
for dir_file in dir_list:
parts = re.split('.*/([^/]*)-([^-]*)-([^-]*).src.rpm$', dir_file)
pkg_name = parts[1]
if options.topkg is not None and pkg_name > options.topkg:
break
if options.frompkg is not None and pkg_name < options.frompkg:
continue
pkg_item = { 'e': 0, 'v': parts[2].replace('~','+'), 'r': parts[3]}
pkg_vr = f'{parts[2]}-{parts[3]}'
# Replace '+' for repository name as it is not allowed
repo_name = pkg_name.replace('+','Plus')
if options.delete:
gitea_repo = giteaGetRepository(repo_name)
if gitea_repo is not None:
print(f'Deleting repository for {pkg_name}...')
gitea_repo.delete()
repo_tags = giteaGetRepoTags(repo_name)
found_equal = False
found_newer = False
found_older = False
if repo_tags is None:
found_newer = True
else:
for repo_tag in repo_tags:
parts = re.split(f'([^-]*)-([^-]*)$', repo_tag["name"])
tag_item = { 'e':0, 'v': parts[1], 'r': parts[2]}
compare = comparePkgInfo(pkg_item, tag_item)
if compare == 0:
found_equal = True
elif compare > 0:
found_older = True
elif compare < 0:
found_newer = True
if not found_equal:
if repo_tags is not None:
print(f'{pkg_name} ({pkg_vr}): needs update')
findAndCommitPackageReleases(pkg_name, None)
if found_newer:
if options.verbose:
print(f'{pkg_name} ({pkg_vr}): found_equal={found_equal} found_newer={found_newer} found_older={found_older}')
else:
parser.print_help()
main()

35
autodist-inspect Executable file
View File

@ -0,0 +1,35 @@
#!/bin/bash
[ -e /etc/autodist/config ] || {
echo "ERROR: missing configuration file /etc/autodist/config."
exit 1
}
. /etc/autodist/config
shopt -s nocaseglob
checkpkg=$1
if [ ! "$checkpkg" ]; then
echo "Usage:
$0 query"
exit 1
fi
[ "$LOCAL_REPS_BASE_DIR" -a -e "$LOCAL_REPS_BASE_DIR" ] || {
echo "ERROR: LOCAL_REPS_BASE_DIR needs to be defined and local repositories to exists."
exit 1
}
echo "=== distromatic sources: ==="
head -n2 ${LOCAL_REPS_BASE_DIR}/distromatic/base/sources
grep -i $checkpkg ${LOCAL_REPS_BASE_DIR}/distromatic/base/sources
#tail -n+2 ${PREFIX}/distromatic/base/deps-* | grep -i $checkpkg
echo -e "\n=== distdb: ==="
grep -i $checkpkg ${LOCAL_REPS_BASE_DIR}/base/distdb
echo -e "\n=== legacy: ==="
grep -i $checkpkg ${LOCAL_REPS_BASE_DIR}/base/legacy
for repo in base devel-makedist devel-autodist devel-misc devel-contrib devel-future; do
echo -e "\n=== ${repo}: ==="
ls ${LOCAL_REPS_BASE_DIR}/${repo}/SRPMS.base/*$checkpkg* 2>/dev/null
ls ${LOCAL_REPS_BASE_DIR}/${repo}/RPMS.*/*$checkpkg* 2>/dev/null
done

77
autodist-launcher Executable file
View File

@ -0,0 +1,77 @@
#!/bin/bash
#
# autodist launcher
# (c) 2021 by Silvan Calarco <silvan.calarco@mambasoft.it>
#
. /etc/autodist/config
. /etc/sysconfig/autoport
# Disable icecc
export PATH=/usr/bin:$PATH
i=$1
[ "$i" ] || {
echo "Usage: autodist-launcher autodist_conf"
exit 1
}
PIDFILE=/run/autodist/autodist-launcher-${i}.pid
[ -e $PIDFILE ] && {
PIDCHECK=`cat $PIDFILE`
[ "$PIDCHECK" -a -e /proc/$PIDCHECK ] && {
echo "autodist-launcher for configuration $i already running; exiting."
exit 0
}
}
echo $$ > $PIDFILE
trap "rm -f $PIDFILE; exit 1" SIGQUIT SIGINT SIGKILL SIGTERM
HOUR=`date +%H`
[ "`uname -m`" = "x86_64" ] && HOST_IS_X86_64=1
AUTODIST_PIDFILE=/run/autodist/autodist.pid
LOGFILE=/var/autodist/log/autodist.log
LASTLOGFILE=/var/autodist/log/autodist-last.log
if [ -e $AUTODIST_PIDFILE ]; then
PIDCHECK=`cat $AUTODIST_PIDFILE`
if [ "$PIDCHECK" -a -e /proc/$PIDCHECK ]; then
echo "autodist already running; exiting."
exit 0
fi
fi
for r in ${AUTOPORT_REPOSITORIES[$i]}; do
[ "${AUTOPORT_ARCH[$i]}" ] || continue
[ "${AUTOPORT_DISABLE[$i]}" -a "${AUTOPORT_DISABLE[$i]}" != "0" ] && continue
if [ "$HOST_IS_X86_64" -a "${AUTOPORT_ARCH[$i]}" != "x86_64" ]; then
CMD_PREFIX=linux32
else
CMD_PREFIX=
fi
# TODO: parametrize DISTROMATIC_REPOSITORY and following log files
DISTROMATIC_REPOSITORY=devel-future
REPLOGFILE=$LOCAL_REPS_BASE_DIR/$r/autodist.log
REPLASTLOGFILE=$LOCAL_REPS_BASE_DIR/$r/autodist-last.log
if [ "${AUTOPORT_UPDATE[$i]}" ]; then
if [ ! "$AUTOPORT_UPDATE_NO_DISTROMATIC" ]; then
distromatic -q -t $DISTROMATIC_REPOSITORY --gensrcpkglist > $LOCAL_REPS_BASE_DIR/$DISTROMATIC_REPOSITORY/srcpkglist 2>/dev/null
fi
#autodist-upstream-updates -q -h -u -r $DISTROMATIC_REPOSITORY -o $r \
# > $LOCAL_REPS_BASE_DIR/distromatic/$r/_popular.html
autodist-upstream-updates -q -u -r $DISTROMATIC_REPOSITORY -o $r
[ -e $LOGFILE ] && mv $LOGFILE $LASTLOGFILE
su -l autodist -c "$CMD_PREFIX autodist -a --server $r" > $LOGFILE
[ -e $REPLOGFILE ] && mv $REPLOGFILE $REPLASTLOGFILE
cp $LOGFILE $REPLOGFILE
fi
done
rm -f ${PIDFILE}

1120
autodist-repository Executable file

File diff suppressed because it is too large Load Diff

1
autodist-tmpfilesd Normal file
View File

@ -0,0 +1 @@
d /run/autodist 775 autodist packager

View File

@ -1,7 +1,7 @@
#!/bin/bash
#
# autodist-tool
# Copyright (c) 2008-2010 by Silvan Calarco <silvan.calarco@mambasoft.it>
# Copyright (c) 2008-2014 by Silvan Calarco <silvan.calarco@mambasoft.it>
#
. /etc/autodist/config
me=(${0##*/} $VERSION "Tue Oct 28 2008")
@ -14,7 +14,6 @@ SOURCESDIR=$AUTOUPDATEDIR/sources/
SRCPKGLIST=/var/ftp/pub/openmamba/$AUTODIST_REPOSITORY/srcpkglist
SUCCESSLISTDIR=$AUTOUPDATEDIR
SKIPPEDLISTDIR=$AUTOUPDATEDIR
DISTDBFILE=/etc/autodist/distdb
#eval `autospec -q --eval="srpms_dir"`
#eval `autospec -q --eval="rpms_dir"`
@ -30,10 +29,10 @@ ${me[0]} ${me[1]}
echo "
"$"Usage"":
$me makepatch package [build|update|remove]
$me schedule job_regexp
$me unschedule job_regexp
$me skip job_regexp
$me makepatch package [auto|build|update|remove]
$me schedule job_regexp..
$me unschedule job_regexp..
$me skip job_regexp..
"
}
@ -83,10 +82,29 @@ if [ "$COMMAND" = "makepatch" ]; then
rm -f $AUTOUPDATEDIR/spec-patches-build/$JOB.spec.patch
echo
exit 0
elif [ "$OPERATION" = "auto" ]; then
if [ -e $spec_dir/.$JOB.spec.autodist.prebuild -a ! -e $AUTOUPDATEDIR/spec-patches-update/$JOB.spec.patch ]; then
OPERATION=build
elif [ -e $spec_dir/.$JOB.spec.autodist.preupdate -a ! -e $AUTOUPDATEDIR/spec-patches-build/$JOB.spec.patch ]; then
OPERATION=update
else
echo "Error: unable to autodetect patch type."
exit 1
fi
fi
echo diff $spec_dir/.$JOB.spec.autodist.pre$OPERATION $spec_dir/$JOB.spec > \
$AUTOUPDATEDIR/spec-patches-$OPERATION/$JOB.spec.patch
if [ ! -e $spec_dir/.$JOB.spec.autodist.pre$OPERATION ]; then
echo "Error: pre$OPERATION specfile missing; make sure you prepare and update the package using autodist."
exit 1
fi
if [ "$OPERATION" = "build" -a -e $AUTOUPDATEDIR/spec-patches-update/$JOB.spec.patch ]; then
echo "Error: trying to make a build patch when an update patch already exists! Remove or create a update patch instead."
exit 1
elif [ "$OPERATION" = "update" -a -e $AUTOUPDATEDIR/spec-patches-build/$JOB.spec.patch ]; then
echo "Error: trying to make an update patch when a build patch already exists! Remove or create a build patch instead."
exit 1
fi
diff $spec_dir/.$JOB.spec.autodist.pre$OPERATION $spec_dir/$JOB.spec > \
$AUTOUPDATEDIR/spec-patches-$OPERATION/$JOB.spec.patch
@ -114,7 +132,7 @@ elif [ "$COMMAND" = "schedule" ]; then
# while read line; do
# set -- $line
# if [ "`echo \" $1 \" | grep \" $JOB \"`" ]; then
if [ "`grep \"^$JOB \" $SRCPKGLIST`" -o "`grep \"^$JOB=(\" $DISTDBFILE`" ]; then
if [ "`grep \"^$JOB \" $SRCPKGLIST`" -o "`autodist --list-jobs | grep ^$JOB$`" ]; then
echo "Job $JOB scheduled for automatic update or rebuild"
sed -i "/^$JOB .*/d" $AUTOUPDATEDIR/manual.in
echo "$JOB $JOBVER 0" >> $AUTOUPDATEDIR/manual.in || exit 1
@ -146,7 +164,7 @@ elif [ "$COMMAND" = "skip" ]; then
if [ "$SKIPPEDLINE" ]; then
sed -i "/^$PKGNAME /d" $SKIPPEDLISTDIR/*.skip
fi
if [ "`grep \"^$JOB \" $SRCPKGLIST`" -o "`grep \"^$JOB=(\" $DISTDBFILE`" ]; then
if [ "`grep \"^$JOB \" $SRCPKGLIST`" -o "`autodist --list-jobs | grep ^$JOB$`" ]; then
echo "$JOB $DATE_NOW 101" >> $SKIPPEDLISTDIR/auto.skip
echo "Job $JOB skipped from automatic builds"
else

380
autodist-upstream-updates Executable file
View File

@ -0,0 +1,380 @@
#!/bin/bash
#
# autodist upstream updates - find upstream packages updates from different internet resources
# Copyright (c) 2004-2023 by Silvan Calarco <silvan.calarco@mambasoft.it>
#
#[ -r /etc/sysconfig/openmamba-central ] || {
# echo "Error: this program must be run as root; aborting." >&2
# exit 1
#}
. /etc/autodist/config
DISTROMATIC_PREFIX=/distribution/distromatic.html?
DISTROMATIC_REPOSITORY=base
DISTDB=/etc/autodist/distdb
BLACKLISTDB=/etc/autodist/blacklist
DISTDBDIR=/etc/autodist/distdb.d
XORG_RELEASE=current
[ -r $DISTDB ] && {
. $DISTDB
[ -d $DISTDBDIR ] && \
for f in `ls $DISTDBDIR/*.db`; do
. $f
done
}
function usage()
{
echo "openmamba-upstream-updates - finds upstream packages updates from different internet resources"
echo
echo "Usage:"
echo "openmamba-upstream-updates [-h|-m][-r repository][-o output_repository]"
echo
echo " -h: generate distromatic HTML output"
echo " -m: report missing packages only"
echo " -s: skip fetching and parsing upstream updates"
echo " -u: output not up-to-date packages only"
echo " -q: produces quite output"
echo " -r repository: specify the distromatic base (default: base)"
echo " -o repository: specify the repository for output data (default: same as base repository)"
echo
}
get_job_vector() {
local JNAME=$1
local JNAME_ESCAPED=`echo $JNAME | tr - _ | tr . _ | tr @ _`
# resolve JOB_NAME from distdb
local jobtmpfile=`mktemp`
# hack to get an array variable named as $j assigned to the JOB array
echo "echo \${$JNAME_ESCAPED[*]}" > $jobtmpfile
JOB=(`. $jobtmpfile`)
rm -f $jobtmpfile
if [ ${#JOB[*]} -eq 0 ]; then
# create a default job with given JOB_NAME
JOB=($JNAME "" "")
elif [ ${#JOB[*]} -eq 1 ]; then
# no variables defined, add an empty job
JOB=(${JOB[*]} "" "")
fi
JOB_PKGS=(${JOB[0]//,/ })
JOB_VARNAMES=(${JOB[1]//,/ })
}
function version_compare()
{
local A B
A=$1
B=$2
if [[ ${1} =~ ^[0-9]+$ && ${2} =~ ^[0-9]+$ ]]; then
if [ $((10#${A/[a-zA-Z_]*})) -gt $((10#${B/[a-zA-Z_]*})) ]; then
return 1
elif [ $((10#${A/[a-zA-Z_]*})) -lt $((10#${B/[a-zA-Z_]*})) ]; then
return 2
fi
else
if [[ ${1} =~ ^[0-9]+$ || "$A" > "$B" ]]; then
return 1
elif [[ "$A" < "$B" ]]; then
return 2
fi
fi
return 0
}
function version_find_bigger()
{
local VER1 VER2 FPOS CUTVER1 CUTVER2
VER1=$1
VER2=$2
FPOS=1
while true; do
CUTVER1=`echo $VER1. | cut -d. -f $FPOS`
CUTVER2=`echo $VER2. | cut -d. -f $FPOS`
if [ "$CUTVER1" -a ! "$CUTVER2" ]; then
return 1
elif [ "$CUTVER2" -a ! "$CUTVER1" ]; then
return 2
elif [ ! "$CUTVER1" -a "$CUTVER2" ]; then
return 0
else
version_compare $CUTVER1 $CUTVER2
case $? in
1) return 1 ;;
2) return 2 ;;
esac
fi
FPOS=`expr $FPOS + 1`
done
return 0
}
while [ "$1" ]; do
case $1 in
-h) distromatic_html=1 ;;
-m) if [ "$distromatic_html" ]; then
echo "Error: options -h and -m cannot be used together."
usage
exit 1
else
missing_only=1
fi ;;
-s) skip_parsing=1 ;;
-u) needupdate_only=1 ;;
-r) [ "$2" ] || {
echo "Error: option -r requires repository name as parameter"
usage
exit 1
}
DISTROMATIC_REPOSITORY=$2
shift
;;
-o) [ "$2" ] || {
echo "Error: option -o requires repository name as parameter"
usage
exit 1
}
OUTPUT_REPOSITORY=$2
shift
;;
-q) quiet=1 ;;
*) echo "Error: invalid option $1."; usage; exit 1 ;;
esac
shift
done
[ "$OUTPUT_REPOSITORY" ] || OUTPUT_REPOSITORY=$DISTROMATIC_REPOSITORY
CACHE_DIR=${LOCAL_REPS_BASE_DIR}/$OUTPUT_REPOSITORY/autoupdate/
PKGLIST_FILE=${LOCAL_REPS_BASE_DIR}/$DISTROMATIC_REPOSITORY/srcpkglist
BUILDS_FILE=${LOCAL_REPS_BASE_DIR}/distromatic/$DISTROMATIC_REPOSITORY/builds-i586
BUILDLIST_FILE=$CACHE_DIR/upstream-updates.in
CONFIG_DIR=$CACHE_DIR
UPDATES_DB=$CACHE_DIR/upstream-updates
ALIASES_DB=$CACHE_DIR/aliases
MANUALVER_DB=$CACHE_DIR/manualver
BLACKLIST_DB_PREFIX=$CACHE_DIR/blacklist.
[ -s $PKGLIST_FILE ] || {
echo "Error: file $PKGLIST_FILE is missing or empty; aborting." >&2
exit 1
}
[ -r $ALIASES_DB ] || {
echo "Error: file $ALIASES_DB cannot be read; aborting." >&2
exit 1
}
parse_arch_linux() {
# parse Arch Linux package list
[ "$quiet" ] || echo -n "Parsing Arch Linux packages list..." >&2
#for page in `seq 1 45`; do
for rep in core community extra; do
# SOURCEURL="https://www.archlinux.org/packages/?page=$page&sort=-last_update&q=&arch=i686&maintainer=&flagged="
SOURCEURL="http://lug.mtu.edu/archlinux/$rep/os/x86_64/"
curl -L -s "$SOURCEURL" | \
grep ".pkg." | grep -v ".sig\"" | \
while read line; do
line=`echo $line | sed "s|.*href=\"\([^\"]*\)\">.*|\1|"`
pkg=`echo $line | sed "s|\(.*\)-[^-]*-[^-]*-[^-]*|\1|"`
ver=`echo $line | sed "s|.*-\([^-]*\)-[^-]*-[^-]*|\1|;s|.*%3a||i;s|%2b.*||i"`
alias=`grep "^$pkg " $ALIASES_DB`
# Skip blackisted
if [ -e ${BLACKLIST_DB_PREFIX}arch ]; then
grep -q "^$pkg$" ${BLACKLIST_DB_PREFIX}arch && continue
fi
[ "$alias" ] || alias=`grep "^lib$pkg " $ALIASES_DB`
[ "$alias" ] && pkgalias=${alias/* /} || pkgalias=$pkg
line=`grep -i "^$pkgalias:" $buildstmp || grep -i "^lib$pkgalias:" $buildstmp || grep -i " $pkgalias[^-_A-Za-z0-9]" $buildstmp`
if [ "$line" ]; then
[ "$pkg" != "$pkgalias" ] && alias=$pkgalias || alias=
[ "$pkg" -a "$ver" ] && {
echo "$pkg $ver $SOURCEURL ${alias}" >> $tmpfile
}
fi
done
done
rm -f $buildstmp
}
parse_xorg() {
# parse X.org stable packages list
[ "$quiet" ] || echo "Parsing X.org release ftp directory..." >&2
SOURCEURL="ftp://ftp.x.org/pub/$XORG_RELEASE/src/everything/"
curl -L -s $SOURCEURL -l | sed "s|\.tar\..*||" | sort -u |
while read line; do
if [ "$line" ]; then
ver=`echo $line | sed "s|.*-||"`
pkg="${line/-$ver}"
if [ -e ${BLACKLIST_DB_PREFIX}xorg ]; then
grep -q "^$pkg$" ${BLACKLIST_DB_PREFIX}xorg && continue
fi
alias=`grep "^$pkg " $ALIASES_DB`
if [ ! "$alias" -a "${pkg:0:5}" == "xf86-" ]; then
alias="$pkg xorg-drv-${pkg/xf86-}"
else
[ "$alias" ] || alias=`grep "^lib$pkg " $ALIASES_DB`
fi
[ "$pkg" -a "$ver" ] && echo "$pkg $ver $SOURCEURL ${alias/* /}" >> $tmpfile
fi
done
}
parse_gnome() {
# parse Gnome stable packages list
[ "$quiet" ] || echo "Parsing GNOME stable versions file..." >&2
for f in versions-stable versions-stable-extras; do
SOURCEURL="https://people.gnome.org/~vuntz/tmp/versions/$f"
curl -s -L $SOURCEURL | grep -v "^#" |
while read line; do
if [ "$line" ]; then
IFS=":"
set -- $line
pkg="$2"
if [ -e ${BLACKLIST_DB_PREFIX}gnome ]; then
grep -q "^$pkg$" ${BLACKLIST_DB_PREFIX}gnome && continue
fi
ver="$3"
alias=`grep "^$pkg " $ALIASES_DB`
[ "$alias" ] || alias=`grep "^lib$pkg " $ALIASES_DB`
if [ "$pkg" -a "$ver" ]; then
ver1=$(echo $ver | cut -d. -f1)
ver2=$(echo $ver | cut -d. -f2)
if [ "$ver2" -a $(($ver2 % 2)) -ne 0 ]; then
# skip unstable versions with odd numbers
continue
else
echo "$pkg $ver $SOURCEURL ${alias/* /}" >> $tmpfile
fi
fi
fi
done
done
}
parse_distromatic() {
# parse distrowatch.com packages list
[ "$quiet" ] || echo "Parsing Distrowatch packages list..." >&2
SOURCEURL="https://distrowatch.com/packages.php"
lynx -width 300 -dump $SOURCEURL |
while read line; do
[ "`echo $line | grep "Package Version Note"`" ] && start_print=1
[ "`echo $line | grep "____________________"`" ] && unset start_print
[ "$start_print" ] && {
set -- $line
pkg="${1/\[*\]/}"
ver="${2/\[*\]/}"
alias=`grep "^$pkg " $ALIASES_DB`
[ "$pkg" != "chromium" ] && \
echo "$pkg $ver $SOURCEURL ${alias/* /}" >> $tmpfile
}
done
}
if [ ! "$skip_parsing" ]; then
#tmpfile=`mktemp -q -t autodist-upstream-updates.XXXXXXXX`
buildstmp=`mktemp -q -t autodist-upstream-updates.XXXXXXXX`
tail -n+2 $BUILDS_FILE > $buildstmp
#parse_arch_linux
#parse_xorg
#parse_gnome
#parse_distromatic
/usr/share/autodist/repology-openmamba.py > $UPDATES_DB.tmp
if [ $? -eq 0 ]; then
#cat $tmpfile | sort -uf > $UPDATES_DB.tmp
#rm -f $tmpfile
> $UPDATES_DB
unset lastpkg
while read pkg ver upsource alias; do
# skip updates to unstable versions
unset found_beta
for b in alpha beta rc "~"; do
[ "${ver/$b}" != "${ver}" ] && found_beta=1
done
[ "$found_beta" ] && continue
if [ "$pkg" = "$lastpkg" ]; then
# echo "Warning: duplicate found: $pkg lastver: $lastver ver: $ver" >&2
version_find_bigger $lastver $ver
vercmp=$?
if [ $vercmp -eq 2 ]; then
sed -i "/^$lastpkg $lastver /d" $UPDATES_DB
echo "$pkg $ver $upsource $alias" >> $UPDATES_DB
fi
else
echo "$pkg $ver $upsource $alias" >> $UPDATES_DB
fi
lastpkg=$pkg
lastver=$ver
done < $UPDATES_DB.tmp
fi
rm -f $UPDATES_DB.tmp
fi
> $UPDATES_DB.missing
> $BUILDLIST_FILE
while read pkg ver upsource alias; do
grep "^$pkg$" $BLACKLISTDB >/dev/null && continue
unset pkgline
unset found_manual
unset found_alias
pkgline=`grep -i "^$pkg " $MANUALVER_DB` && found_manual=1
if [ ! "$found_manual" ]; then
if [ "$alias" ]; then
get_job_vector $alias
lastjob=${#JOB_PKGS[*]}
pkgline=`grep "^${JOB_PKGS[$lastjob-1]} " $PKGLIST_FILE` && found_alias=1
else
get_job_vector $pkg
lastjob=${#JOB_PKGS[*]}
pkgline=`grep "^${JOB_PKGS[$lastjob-1]} " $PKGLIST_FILE`
[ "$pkgline" ] || {
get_job_vector lib${pkg}
lastjob=${#JOB_PKGS[*]}
pkgline=`grep "^${JOB_PKGS[$lastjob-1]} " $PKGLIST_FILE` && {
found_alias=1
alias=lib${pkg}
}
}
fi
fi
if [ "$pkgline" -a ! "$missing_only" ]; then
set -- $pkgline
pkgname=$1
pkgver=$2
pkgrep=$4
version_find_bigger $pkgver ${ver/-/.}
vercmp=$?
#echo "$pkgname - version_find_bigger $pkgver ${ver/-/.} result=$vercmp"
[ "${vercmp}" != "2" -a "$needupdate_only" ] && continue
[ "$found_manual" ] && pkgname=$3
[ "$found_alias" -o "$found_manual" ] && nameadd="$pkg" || unset nameadd
unset veradd
[ ${vercmp} = 2 ] && veradd="<a href=\"$upsource\"><font color=red>$ver</font></a>"
[ ${vercmp} = 1 ] && veradd="$ver"
[ "$veradd" -o "$nameadd" ] && {
[ "$veradd" -a "$nameadd" ] && \
verappend="($nameadd;$veradd)" ||
verappend="(${nameadd}${veradd})"
} || unset verappend
if [ "$distromatic_html" = "1" ]; then
echo "<a href=\"${DISTROMATIC_PREFIX}tag=${pkgrep}&pkg=${JOB_PKGS[0]}.source\">${JOB_PKGS[0]} $pkgver</a> $verappend<br>"
else
echo "$pkg $pkgver ($ver)"
fi
[ $vercmp = 2 ] && {
if [ "$found_alias" ]; then
echo "$alias +$ver 0 $upsource" >> $BUILDLIST_FILE
else
echo "$pkg +$ver 0 $upsource" >> $BUILDLIST_FILE
fi
}
elif [ ! "$pkgline" ]; then
echo "$pkg ($ver) $upsource" >> $UPDATES_DB.missing
fi
done < $UPDATES_DB

291
automaint Executable file
View File

@ -0,0 +1,291 @@
#!/bin/bash
# automaint -- batch automatic maintainance tool of the autodist suite
# Copyright (C) 2013-2021 by Silvan Calarco <silvan.calarco@mambasoft.it>
#
# Released under the terms of the GNU GPL release 3 license
#
VERSION=0.9.7
# First in vector is base arch
. /etc/autodist/config
me=(${0##*/} $VERSION "Sat Mar 20 2011")
function usage() {
echo "\
${me[0]} ${me[1]}
"$"Copyright (C) 2013-2021 Silvan Calarco <silvan.calarco@mambasoft.it>""
"$"Released under the terms of the GNU GPL v3 license"
echo "
"$"Batch automatic maintainance tool of the autodist suite.""
"$"Usage"":
$me [-s repository -d repository ] [-p repository] [-h] [-v]
-d repository "$"Main destination repository
-p repository "$"Port repository
-s repository "$"Automatic/Staging builds source repository
-h "$"Show this help and exit
-t "$"Test mode (no change will be made)
-v "$"Verbose output
"
}
# for webbuild message
function cgi_encodevar() {
local string="${1}"
local strlen=${#string}
local encoded=""
for (( pos=0 ; pos<strlen ; pos++ )); do
c=${string:$pos:1}
case "$c" in
[-_.~a-zA-Z0-9] ) o="${c}" ;;
* ) printf -v o '%%%02x' "'$c"
esac
encoded+="${o}"
done
echo "${encoded}" # You can either set a return variable (FASTER)
# REPLY="${encoded}" #+or echo the result (EASIER)... or both... :p
}
# get_pkg_buildinfo - uses distromatic generated build file for
# getting information on the repository
#
# $1: distromatic files base url for repository
# $2: architecture
# $3: pkg name
function get_pkg_buildinfo() {
local pkg i a local_arch local_distromatic
[ $1 ] && local_distromatic=$1 || exit 1
[ $2 ] && local_arch=$2 || exit 1
[ $3 ] && pkg=$3
if [ ! "$pkg" ]; then
[ -e $local_distromatic/builds-${local_arch}.sh ] && . $local_distromatic/builds-${local_arch}.sh
return 0
fi
pkg_archs=();
for a in ${archs[*]}; do
[ "$a" = "${local_arch}" ] && continue
pkg_header=();
DISTROMATIC_BUILD_FILE=$local_distromatic/builds-$a.sh
[ -e $DISTROMATIC_BUILD_FILE ] && . $DISTROMATIC_BUILD_FILE
[ ${pkg_header[0]} ] && pkg_archs=(${pkg_archs[*]} $a)
done
pkg_header=();
pkg_builds=();
pkg_obsoletes=();
pkg_list=();
DISTROMATIC_BUILD_FILE=$local_distromatic/builds-${local_arch}.sh
[ -e $DISTROMATIC_BUILD_FILE ] && . $DISTROMATIC_BUILD_FILE
[ ${pkg_header[0]} ] && pkg_archs=(${pkg_archs[*]} ${local_arch})
# {
# echo "Error: missing distromatic generated file $DISTROMATIC_BUILD_FILE; aborting."
# return;
# }
# . $DISTROMATIC_BUILD_FILE
for i in ${pkg_list[*]}; do
if [ "$i" == "${pkg_header[0]}" ]; then
pkg_name=${pkg_header[0]};
# Note: pkg_arch reported in builds file is just last arch source was
# built for, so we use repository arch instead
pkg_arch=${pkg_header[1]};
[ "$pkg_arch" = "noarch" ] || pkg_arch=${local_arch}
pkg_version=${pkg_header[2]};
pkg_release=${pkg_header[3]};
pkg_group=${pkg_header[4]};
pkg_license=${pkg_header[5]};
pkg_size=${pkg_header[6]};
pkg_buildtime=${pkg_header[7]};
pkg_altrep=${pkg_header[8]};
pkg_repository=${pkg_header[9]};
return 0
fi
done
unset pkg_name pkg_arch pkg_version pkg_release \
pkg_group pkg_license pkg_size pkg_buildtime pkg_altrep pkg_repository
return 1
}
[ $# -gt 0 ] || { usage ; exit 1; }
for ((i=1; i<=$#; i++)); do
case ${!i} in
-s) shift
SOURCE_REPOSITORY="${!i}"
;;
-d) shift
DEST_REPOSITORY="${!i}"
;;
-p) shift
PORT_REPOSITORY="${!i}"
;;
-t) TESTMODE=1
;;
-v) VERBOSE=1
;;
-h|--help)
usage
exit 0
;;
esac
done
[ "$SOURCE_REPOSITORY" -a "$DEST_REPOSITORY" ] || { usage; exit 1; }
[ "$SOURCE_REPOSITORY" = "$DEST_REPOSITORY" ] && {
echo "ERROR: source and destination repository cannot be the same; aborting."
exit 1
}
[ "$TESTMODE" ] && echo "** TEST MODE enabled: no changes will be made **"
for a in `seq 1 ${#AUTODIST_ARCHS[*]}`; do
. $LOCAL_REPS_BASE_DIR/distromatic/$SOURCE_REPOSITORY/builds-${AUTODIST_ARCHS[$a-1]}.sh
pkglist[$a-1]="${pkg_list[*]}"
warningslist[$a-1]="${warnings_list[*]}"
needportlist[$a-1]="${needport_list[*]}"
done
tmpfile=`mktemp -q -t $me.XXXXXXXX` || {
echo "ERROR: cannot create temporary files." >&2
exit 1
}
for a in `seq 1 ${#AUTODIST_ARCHS[*]}`; do
echo -n "${pkglist[$a-1]} " >> $tmpfile
done
allpkgs="`cat $tmpfile | xargs -n 1 | sort -u | xargs`"
rm -f $tmpfile
for p in ${allpkgs}; do
pkgcontinue=
needsport=
for w in ${warningslist[*]}; do
[ "$p" = "$w" ] && { pkgcontinue=1; break; }
done
[ "$pkgcontinue" ] && continue
for a in `seq 1 ${#AUTODIST_ARCHS[*]}`; do
# Get pkg info from port repository
get_pkg_buildinfo $LOCAL_REPS_BASE_DIR/distromatic/$PORT_REPOSITORY ${AUTODIST_ARCHS[$a-1]} $p
# If not found get info from main repository
if [ ! "$pkg_name" ]; then
get_pkg_buildinfo $LOCAL_REPS_BASE_DIR/distromatic/$DEST_REPOSITORY ${AUTODIST_ARCHS[$a-1]} $p
fi
if [ "$pkg_name" ]; then
old_pkg_version=$pkg_version
old_pkg_release=$pkg_release
old_pkg_repository=$pkg_repository
break
fi
done
[ "$pkg_name" ] || {
[ "$VERBOSE" ] && echo "$p: not present in $DEST_REPOSITORY; skipping."
continue
}
[ "$VERBOSE" ] && echo "$p: old release in $DEST_REPOSITORY is $old_pkg_version-$old_pkg_release"
for o in ${needportlist[*]}; do
[ "$p" = "$o" ] && { needsport=1; break; }
done
#[ "$needsport" ] && continue
[ "$needsport" -a ! "$PORT_REPOSITORY" ] && continue
for a in `seq 1 ${#AUTODIST_ARCHS[*]}`; do
get_pkg_buildinfo $LOCAL_REPS_BASE_DIR/distromatic/$SOURCE_REPOSITORY ${AUTODIST_ARCHS[$a-1]} $p
[ "$pkg_name" ] && break
done
[ "$pkg_name" ] || {
[ "$VERBOSE" ] && echo "$p: not present in $SOURCE_REPOSITORY; skipping."
continue
}
[ "$VERBOSE" ] && echo "$p: new release in $SOURCE_REPOSITORY is $pkg_version-$pkg_release"
if [ "$pkg_version" = "$old_pkg_version" ]; then
if [ "$pkg_release" = "$old_pkg_release" ]; then
echo "$p: same release as upstream; skipping."
continue
fi
update_type="release"
else
OIFS=$IFS
IFS='.'
read -ra SVER <<< "$old_pkg_version"
read -ra VER <<< "$pkg_version"
IFS=$OIFS
dotdiff=`expr ${#VER[*]} - ${#SVER[*]}`
for i in `seq 1 ${#SVER[*]}`; do
[ "${SVER[i-1]}" != "${VER[i-1]}" ] && break
done
if [ "$i" = "${#SVER[*]}" -a $dotdiff -eq 0 ]; then
# e.g. SVER=0.11.3 -> VER=0.11.4
if [[ 64#${VER[i-1]} -gt 64#89 && 64#${SVER[i-1]} -lt 64#80 ]]; then
[ "$VERBOSE" ] && echo "$p: dubious beta upgrade from ${SVER[i-1]} to ${VER[i-1]}; skipping."
continue
fi
update_type="minor"
#elif [ $dotdiff -lt 0 ]; then
# [ "$VERBOSE" ] && echo "$p: newer version has less dots than older ${#VER[*]} < ${#SVER[*]}; skipping."
# continue
#elif [ "$i" != "${#SVER[*]}" ]; then
# # e.g. SVER=0.11 -> VER=1.0
# [ "$VERBOSE" ] && echo "$p: not a minor version update at position $i/${#SVER[*]}: ${SVER[i-1]} != ${VER[i-1]}; skipping."
# continue
elif [ "${SVER[i-1]}" = "${VER[i-1]}" -a $dotdiff -ge 1 ]; then
# e.g. SVER=0.11.2 -> VER=0.11.2.3
update_type="minor"
elif [[ 64#${VER[i-1]} -gt 64#89 && 64#${SVER[i-1]} -lt 64#80 ]]; then
[ "$VERBOSE" ] && echo "$p: dubious beta upgrade from ${SVER[i-1]} to ${VER[i-1]}; skipping."
continue
elif [[ 64#${VER[i-1]} -gt 64#${SVER[i-1]} && $i -gt 1 ]]; then
# e.g. SVER=1.0.2 -> VER=1.0.3.dev1234
update_type="minor"
#else
# [ "$VERBOSE" ] && echo "$p: major version update ${SVER[i-1]} vs ${VER[i-1]}; skipping"
# continue
fi
fi
#if [ ! "${needsport}" ]; then
if [ "$old_pkg_repository" == "$PORT_REPOSITORY" -o "$old_pkg_repository" == "$DEST_REPOSITORY" ]; then
echo "$p: importing from $SOURCE_REPOSITORY to $PORT_REPOSITORY ($pkg_version-$pkg_release -> $old_pkg_version-$old_pkg_release)"
if [ ! "$TESTMODE" ]; then
autodist-repository import $SOURCE_REPOSITORY $p -d $PORT_REPOSITORY -y >/dev/null
if [ $? -eq 0 -a "$WEBBUILD_URL" -a "$WEBBUILD_USER" ]; then
curl -s "$WEBBUILD_URL?REQUEST=message&USER=$WEBBUILD_USER&SECRET=${WEBBUILD_SECRET}&USER_EMAIL=$WEBBUILD_EMAIL&\
MESSAGE=`cgi_encodevar \"imported <b>$p</b> from <b>$SOURCE_REPOSITORY</b> to <b>$PORT_REPOSITORY</b> for porting\"`" >/dev/null
fi
fi
fi
#fi
#elif [ "$old_pkg_repository" == "$DEST_REPOSITORY" ]; then
# echo "$p: importing from $SOURCE_REPOSITORY to $DEST_REPOSITORY ($pkg_version-$pkg_release -> $old_pkg_version-$old_pkg_release; update type: $update_type)"
# if [ ! "$TESTMODE" ]; then
# autodist-repository import $SOURCE_REPOSITORY $p -d $DEST_REPOSITORY -y >/dev/null
# if [ $? -eq 0 -a "$WEBBUILD_URL" -a "$WEBBUILD_USER" ]; then
# curl -s "$WEBBUILD_URL?REQUEST=message&USER=$WEBBUILD_USER&SECRET=${WEBBUILD_SECRET}&USER_EMAIL=$WEBBUILD_EMAIL&\
#MESSAGE=`cgi_encodevar \"imported <b>$p</b> from <b>$SOURCE_REPOSITORY</b> to <b>$DEST_REPOSITORY</b>\"`" >/dev/null
# fi
# fi
# else
# echo "$p: upstream package repository $pkg_repository does not match with $DEST_REPOSITORY; skipping."
# fi
done
exit 0

526
autoport
View File

@ -1,13 +1,13 @@
#!/bin/bash
# autoport -- batch cross-build tool based on autodist
# Copyright (C) 2011-2012 by Silvan Calarco <silvan.calarco@mambasoft.it>
# Copyright (C) 2011-2024 by Silvan Calarco <silvan.calarco@mambasoft.it>
#
# Released under the terms of the GNU GPL release 3 license
#
VERSION=0.9.1
BASE_ARCH=i586
BASE_REPOSITORY=devel
PORT_REPOSITORY=devel
VERSION=1.5.4
BASE_REPOSITORY=base
PORT_REPOSITORY=base
. /etc/autodist/config
@ -16,13 +16,13 @@ me=(${0##*/} $VERSION "Sat Mar 20 2011")
function usage() {
echo "\
${me[0]} ${me[1]}
"$"Copyright (C) 2011-2012 Silvan Calarco <silvan.calarco@mambasoft.it>""
"$"Copyright (C) 2011-2023 Silvan Calarco <silvan.calarco@mambasoft.it>""
"$"Released under the terms of the GNU GPL v3 license"
echo "
"$"Batch port and cross-build tool based on autodist.""
"$"Usage"":
$me [-a][-f][-x arch1[,arch2],..][-r repository][-d release_repository]{--fix|job ...}
$me [-a][-f][-x arch1[,arch2],..][-r repository][-d release_repository][-s \"script_args\"]{--fix|job ...}
-a "$"Automatic mode (use cache)
-b "$"Batch port all packages in port repository to sync with base repository
@ -32,10 +32,14 @@ ${me[0]} ${me[1]}
-nr "$"Don't recurse build
--fix "$"Fix .la files for cross linking and exit
-r "$"Work on given repository (default: $PORT_REPOSITORY)
-d "$"Release packages to given repository (default: $PORT_REPOSITORY)
-x "$"Operate in cross build mode
-d "$"Release packages to given repository (default: work repository)
-h "$"Show this help and exit
-s \"script_args\" "$"Send script_args as arguments for autodist update-specfile script
-u changelog "$"Rebuild packages with given changelog
-ud "$"Rebuild dependent packages that need rebuild
-v "$"More verbose output
-x "$"Operate in cross build mode
--user user "$"Pass calling user name for Webbuild social messages
arch "$"Target architecture
job "$"Job specification for autodist""
@ -43,6 +47,63 @@ ${me[0]} ${me[1]}
}
function autoport_log() {
local pkg=$1
local operation=$2
local result=$3
local loggrep=`grep "?= See" $4 | sed "s|?= See ||"`
local logfiles=""
for f in $loggrep; do
logfiles="$logfiles $f"
done
[ "$pkg" -a "$operation" -a "$result" -a "$BATCH_MODE" ] || return
echo "$pkg $operation $result $logfiles" >> $DATADIR/autoport-$PORT_REPOSITORY-current
}
# for webbuild message
function cgi_encodevar() {
local string="${1}"
local strlen=${#string}
local encoded=""
for (( pos=0 ; pos<strlen ; pos++ )); do
c=${string:$pos:1}
case "$c" in
[-_.~a-zA-Z0-9] ) o="${c}" ;;
* ) printf -v o '%%%02x' "'$c"
esac
encoded+="${o}"
done
echo "${encoded}" # You can either set a return variable (FASTER)
# REPLY="${encoded}" #+or echo the result (EASIER)... or both... :p
}
function get_pkg_srcinfo() {
local pkg local_distromatic pkg_line
unset src_name src_version src_buildtime src_repository src_epoch src_release
[ $1 ] && local_distromatic=$1 || exit 1
[ $2 ] && pkg=$2 || return 1
[ -e $local_distromatic/srcpkglist ] || return 2
pkg_line=`grep "^$pkg " $local_distromatic/srcpkglist`
[ "$pkg_line" ] || return 3
set -- $pkg_line
src_name=$1
src_version=$2
src_buildtime=$3
src_repository=$4
src_epoch=$5
src_release=$6
src_milestone=`echo $src_release | sed "s|[0-9.]*\(.*\)|\1|"`
}
# get_pkg_buildinfo - uses distromatic generated build file for
# getting information on the repository
#
@ -63,7 +124,8 @@ function get_pkg_buildinfo() {
fi
pkg_archs=();
for a in ${archs[*]}; do
for a in ${AUTODIST_ARCHS[*]}; do
[ "$a" = "${local_arch}" ] && continue
pkg_header=();
DISTROMATIC_BUILD_FILE=$local_distromatic/builds-$a.sh
[ -e $DISTROMATIC_BUILD_FILE ] && . $DISTROMATIC_BUILD_FILE
@ -77,6 +139,7 @@ function get_pkg_buildinfo() {
DISTROMATIC_BUILD_FILE=$local_distromatic/builds-${local_arch}.sh
[ -e $DISTROMATIC_BUILD_FILE ] && . $DISTROMATIC_BUILD_FILE
[ ${pkg_header[0]} ] && pkg_archs=(${pkg_archs[*]} ${local_arch})
# {
# echo "Error: missing distromatic generated file $DISTROMATIC_BUILD_FILE; aborting."
@ -84,8 +147,7 @@ function get_pkg_buildinfo() {
# }
# . $DISTROMATIC_BUILD_FILE
for i in ${pkg_list[*]}; do
if [ "$i" == "${pkg_header[0]}" ]; then
if [ "${pkg_header[0]}" ]; then
pkg_name=${pkg_header[0]};
# Note: pkg_arch reported in builds file is just last arch source was
# built for, so we use repository arch instead
@ -99,10 +161,9 @@ function get_pkg_buildinfo() {
pkg_buildtime=${pkg_header[7]};
pkg_altrep=${pkg_header[8]};
pkg_repository=${pkg_header[9]};
pkg_epoch=${pkg_header[10]};
return 0
fi
done
unset pkg_name pkg_arch pkg_version pkg_release \
pkg_group pkg_license pkg_size pkg_buildtime pkg_altrep pkg_repository
@ -123,7 +184,7 @@ _EOF
function find_source_by_provide() {
local pkg=`echo $2 | sed "s|(|\\\\\[|g;s|)|\\\\\]|g;s|:|_|g"`
grep "^$pkg:" $DATADIR/$1/sources-$BASE_ARCH | \
grep "^$pkg:" $DATADIR/$1/sources-* | \
awk '{ $1=""; print $0 }' | \
sed "s|[[:space:]]_| |g"
}
@ -138,21 +199,28 @@ function find_requirements() {
local OUTFILE=$1
if [ "`grep " is needed by " $OUTFILE`" ]; then
grep " is needed by " $OUTFILE | awk '{ print $1 }' | sort -u > $tf1
grep " is needed by " $OUTFILE | awk '{ print $1 }' | tr -d \' > $tf1
elif [ "`grep " matches no packages" $OUTFILE`" ]; then
grep " matches no packages" $OUTFILE | awk '{ print $2 }' | tr -d \' | sort -u > $tf1
grep " matches no packages" $OUTFILE | awk '{ print $2 }' | tr -d \' | sed "s|@.*||" > $tf1
elif [ "`grep " no package provides " $OUTFILE`" ]; then
grep " no package provides " $OUTFILE | sed "s|.* no package provides ||" | sort -u > $tf1
grep " no package provides " $OUTFILE | sed "s|.* no package provides ||" > $tf1
fi
[ `stat -c %s $tf1` -gt 0 ] && {
echo -n " | missing requirements: "
> $tf
cat $tf1 | while read line; do
REQ=`find_source_by_provide $PORT_REPOSITORY $line`
[ "$REQ" ] && \
echo "${REQ}" >> $tf || \
sort -u $tf1 | while read line; do
REQ=`find_source_by_provide $PORT_REPOSITORY ${line}`
if [ "$REQ" ]; then
get_pkg_buildinfo $DATADIR/$PORT_REPOSITORY $TARGET_ARCH $REQ
if [ "$pkg_name" ]; then
echo -n "$line(notrebuilding) "
else
echo "${REQ}" >> $tf
fi
else
echo -n "$line(unresolved) "
fi
done
> $tf1
cat $tf | sort -u 2>/dev/null | while read line; do
@ -170,9 +238,43 @@ function find_requirements() {
return 0
}
fetch_repfiles() {
local u
f=${DATADIR}/${PORT_REPOSITORY}/srcpkglist
if [ ! -e ${f} -o "`find ${f} -mmin +60 2>/dev/null`" ]; then
[ "$VERBOSE_MODE" = "1" ] && echo "Fetching ${REPS_BASE_URL}/$PORT_REPOSITORY/srcpkglist"
curl -f -L -s ${REPS_BASE_URL}/$PORT_REPOSITORY/srcpkglist -o ${f} ||
echo "Warning: unable to fetch ${REPS_BASE_URL}/$PORT_REPOSITORY/srcpkglist"
fi
for a in ${AUTODIST_ARCHS[*]}; do
f=${DATADIR}/${PORT_REPOSITORY}/sources-${a}
if [ ! -e ${f} -o "`find ${f} -mmin +60 2>/dev/null`" ]; then
[ "$VERBOSE_MODE" = "1" ] && echo "Fetching $PORT_REPOSITORY_DISTROMATIC_URL/sources-${a}"
curl -f -L -s $PORT_REPOSITORY_DISTROMATIC_URL/sources-${a} -o ${f} ||
echo "Warning: unable to fetch $PORT_REPOSITORY_DISTROMATIC_URL/sources-${a}"
fi
f=${DATADIR}/${PORT_REPOSITORY}/builds-${a}.sh
if [ ! -e ${f} -o "`find ${f} -mmin +60 2>/dev/null`" ]; then
[ "$VERBOSE_MODE" = "1" ] && echo "Fetching $PORT_REPOSITORY_DISTROMATIC_URL/builds-${a}.sh"
curl -f -L -s $PORT_REPOSITORY_DISTROMATIC_URL/builds-${a}.sh -o ${f} ||
echo "Warning: unable to fetch $PORT_REPOSITORY_DISTROMATIC_URL/builds-${a}.sh"
fi
done
for u in ${AUTOPORT_UNSTAGE_ARCHS}; do
[ "$u" = "$TARGET_ARCH" ] && {
rm -f $DATADIR/$PORT_REPOSITORY/unstage.$TARGET_ARCH
return
}
done
[ "$VERBOSE_MODE" = "1" ] && echo "Fetching ${REPS_BASE_URL}/${PORT_REPOSITORY/-*}/unstage.$TARGET_ARCH"
curl -f -L -s ${REPS_BASE_URL}/${PORT_REPOSITORY/-*}/unstage.$TARGET_ARCH -o $DATADIR/$PORT_REPOSITORY/unstage.$TARGET_ARCH ||
echo "Warning: unable to fetch ${REPS_BASE_URL}/${PORT_REPOSITORY/-*}/unstage.$TARGET_ARCH"
}
[ $# -gt 0 ] || { usage ; exit 1; }
BUILD_ARCH=`uname -i`
[ "$BUILD_ARCH" ] || BUILD_ARCH=`uname -m`
case $BUILD_ARCH in
i386|i486|i686) BUILD_ARCH=i586 ;;
@ -189,6 +291,17 @@ for ((i=1; i<=$#; i++)); do
-b) BATCH_MODE=1 ;;
-f) FORCE_MODE=1 ;;
-v) VERBOSE_MODE=1 ;;
-u) REBUILD_MODE=1
shift
REBUILD_CHANGELOG="${!i}"
[ "$REBUILD_CHANGELOG" ] || {
echo "ERROR: changelog not given as -u option parameter; aborting."
exit 1
}
;;
-ud) REBUILD_DEPENDANT_MODE=1
DONT_RECURSE=1
;;
-npa) DONT_PREPARE_ANY=1
DONT_PREPARE=1 ;;
-np) DONT_PREPARE=1 ;;
@ -197,6 +310,9 @@ for ((i=1; i<=$#; i++)); do
-r) shift
PORT_REPOSITORY="${!i}"
;;
-s) shift
SCRIPT_ARGS="${!i}"
;;
-d) shift
DEST_REPOSITORY="${!i}"
;;
@ -204,6 +320,13 @@ for ((i=1; i<=$#; i++)); do
TARGET_ARCHS="`echo ${!i} | tr , ' '`"
CROSS_MODE=1
;;
--user) let i+=1
[ "${!i}" ] || {
echo "Error: --user parameter not given, aborting."
exit 1
}
WEBBUILD_USER_CMDLINE="${!i}"
;;
-h|--help)
usage
exit 0
@ -215,14 +338,21 @@ done
[ "$DEST_REPOSITORY" ] || DEST_REPOSITORY=$PORT_REPOSITORY
if [ "$BATCH_MODE" ]; then
PIDFILE="/run/autodist/autoport-${BUILD_ARCH}-${PORT_REPOSITORY}.pid"
[ -e $PIDFILE ] && {
PIDCHECK=`cat $PIDFILE`
[ "$PIDCHECK" -a -e /proc/$PIDCHECK -a ! "$DISABLE_PID_CHECK" ] && {
echo "Error: autoport -b already running with PID=$PIDCHECK.Aborting."
exit 1
}
}
echo $$ > $PIDFILE
trap "rm -f $PIDFILE; exit 1" SIGQUIT SIGINT SIGKILL SIGTERM
fi
for TARGET_ARCH in ${TARGET_ARCHS}; do
[ "$BASE_ARCH" = "$TARGET_ARCH" -a "$PORT_REPOSITRY" = "$DEST_REPOSITORY" ] && {
echo "Error: base and target arch ($BASE_ARCH) are the same as well as port and release repositories ($PORT_REPOSITORY); skipping."
continue
}
archs=($BASE_ARCH $TARGET_ARCH)
JOBS_SKIPPED=()
JOBS_CANTPREPARE=()
JOBS_CANTINSTALL=()
@ -236,83 +366,106 @@ for TARGET_ARCH in ${TARGET_ARCHS}; do
BASE_REPOSITORY_DISTROMATIC_URL=${DISTROMATIC_BASE_URL}$BASE_REPOSITORY
PORT_REPOSITORY_DISTROMATIC_URL=${DISTROMATIC_BASE_URL}$PORT_REPOSITORY
[ "$AUTO_MODE" -a -e $DATAARCHDIR/last ] && . $DATAARCHDIR/last
JOB=(${JOB_CMDLINE[*]} ${JOB_MISSINGREQ[*]} ${JOB_FAILED[*]})
[ "$FIX_MODE" -o "$BATCH_MODE" -o "${JOB[*]}" ] || { usage ; exit 1; }
[ -d $DATAARCHDIR ] || mkdir -p $DATAARCHDIR
[ -d $DATADIR/$BASE_REPOSITORY ] || mkdir -p $DATADIR/$BASE_REPOSITORY
[ -d $DATADIR/$PORT_REPOSITORY ] || mkdir -p $DATADIR/$PORT_REPOSITORY
logfile=$DATAARCHDIR/log
[ -e $logfile ] && mv -f $logfile $DATAARCHDIR/loglast
logdate=`date +"%F@%T"`
logfile=$DATAARCHDIR/$logdate.log
[ -e $DATAARCHDIR/$PORT_REPOSITORY-current.log ] && mv $DATAARCHDIR/$PORT_REPOSITORY-current.log $DATAARCHDIR/$PORT_REPOSITORY-last.log
> $logfile
ln -sf $logdate.log $DATAARCHDIR/$PORT_REPOSITORY-current.log
BUILD_PLATFORM=`rpm --target $TARGET_ARCH --eval %{_build}`
BUILD_CPU=`echo $BUILD_PLATFORM | cut -d- -f1`
TARGET_PLATFORM=`rpm --target $TARGET_ARCH --eval %{_target_platform}`
TARGET_CPU=`echo $TARGET_PLATFORM | cut -d- -f1`
eval `autospec --eval spec_dir | tail -n1`
if [ "$spec_dir" ]; then
SPECDIR=$spec_dir
else
SPECDIR=`rpm --eval %{_specdir}`
fi
echo "Build platform is $BUILD_PLATFORM"
echo "Target platform is $TARGET_PLATFORM"
echo "Port repository is $PORT_REPOSITORY"
echo "Release repository is $DEST_REPOSITORY"
curl -s $PORT_REPOSITORY_DISTROMATIC_URL/sources-$BASE_ARCH -o $DATADIR/$PORT_REPOSITORY/sources-$BASE_ARCH ||
echo "Warning: unable to fetch $PORT_REPOSITORY_DISTROMATIC_URL/sources-$BASE_ARCH"
curl -s $PORT_REPOSITORY_DISTROMATIC_URL/sources-$TARGET_CPU -o $DATADIR/$PORT_REPOSITORY/sources-$TARGET_CPU ||
echo "Warning: unable to fetch $PORT_REPOSITORY_DISTROMATIC_URL/sources-$TARGET_CPU"
curl -s $PORT_REPOSITORY_DISTROMATIC_URL/builds-$BASE_ARCH.sh -o $DATADIR/$PORT_REPOSITORY/builds-$BASE_ARCH.sh ||
echo "Error: unable to fetch $PORT_REPOSITORY_DISTROMATIC_URL/builds-$BASE_ARCH.sh"
curl -s $PORT_REPOSITORY_DISTROMATIC_URL/builds-$TARGET_ARCH.sh -o $DATADIR/$PORT_REPOSITORY/builds-$TARGET_ARCH.sh ||
echo "Error: unable to fetch $PORT_REPOSITORY_DISTROMATIC_URL/builds-$TARGET_ARCH.sh"
fetch_repfiles
[ "$AUTO_MODE" -a -e $DATAARCHDIR/last ] && . $DATAARCHDIR/last
if [ "$REBUILD_DEPENDANT_MODE" ]; then
for j in ${JOB_CMDLINE[*]}; do
get_pkg_buildinfo $DATADIR/$PORT_REPOSITORY $TARGET_ARCH $j
port_pkg_list=${pkg_needrebuild[*]}
port_pkg_builds=" ${pkg_builds[*]} "
port_pkg_epoch=$pkg_epoch
port_pkg_version=$pkg_version
port_pkg_release=$pkg_release
currrebuild=
currjobscriptargs=
JOBNUM=0
for p in ${port_pkg_list}; do
if [ "${p/@*}" != "$currrebuild" ]; then
[ $JOBNUM -gt 0 ] && JOB_SCRIPTARGS[$JOBNUM-1]="$currjobscriptargs"
currjobscriptargs=
currrebuild=${p/@*}
get_pkg_buildinfo $DATADIR/$PORT_REPOSITORY $TARGET_ARCH $currrebuild
for ignore_pkg in ${AUTOPORT_IGNORE_LIST}; do
[ "${currrebuild}" == "${ignore_pkg}" ] && continue
done
JOB=(${JOB[*]} $currrebuild)
let JOBNUM+=1
fi
currprovider=${p/*@}
if [ "${currprovider/-devel}" == "$currprovider" ]; then
currprovider=${currprovider}-devel
fi
add_epoch=""
[ "${port_pkg_epoch}" ] && add_epoch="${port_pkg_epoch}:"
currjobscriptargs="$currjobscriptargs --buildreq ${currprovider} >= ${add_epoch}${port_pkg_version}-${port_pkg_release} "
done
[ "$currjobscriptargs" ] && JOB_SCRIPTARGS[$JOBNUM-1]="$currjobscriptargs"
echo "Package dependant from $j to rebuild: ${JOB[*]}"
done
else
JOB=(${JOB_CMDLINE[*]} ${JOB_MISSINGREQ[*]} ${JOB_FAILED[*]})
fi
[ "$FIX_MODE" -o "$BATCH_MODE" -o "${JOB[*]}" ] || { echo "Nothing to do."; exit 0; }
if [ "$BATCH_MODE" ]; then
[ "${JOB[*]}" ] && {
echo "Error: no jobs allowed in batch mode; aborting."
exit 1
}
curl -s $BASE_REPOSITORY_DISTROMATIC_URL/builds-$BASE_ARCH.sh -o $DATADIR/$BASE_REPOSITORY/builds-$BASE_ARCH.sh ||
echo "Error: unable to fetch $BASE_REPOSITORY_DISTROMATIC_URL/builds-$BASE_ARCH.sh"
curl -s $BASE_REPOSITORY_DISTROMATIC_URL/builds-$TARGET_ARCH.sh -o $DATADIR/$BASE_REPOSITORY/builds-$TARGET_ARCH.sh ||
echo "Error: unable to fetch $BASE_REPOSITORY_DISTROMATIC_URL/builds-$TARGET_ARCH.sh"
get_pkg_buildinfo $DATADIR/$PORT_REPOSITORY $BASE_ARCH
# old files cleanup
rm -f $DATADIR/$BASE_REPOSITORY/builds-*.sh
get_pkg_buildinfo $DATADIR/$PORT_REPOSITORY $TARGET_ARCH
port_pkg_list=${pkg_list[*]}
if [ "$REBUILD_MILESTONE" ]; then
for p in ${port_pkg_list}; do
get_pkg_buildinfo $DATADIR/$PORT_REPOSITORY $TARGET_ARCH $p || get_pkg_buildinfo $DATADIR/$BASE_REPOSITORY $TARGET_ARCH $p
if [ "$pkg_name" ]; then
base_pkg_ver=$pkg_version
get_pkg_buildinfo $DATADIR/$PORT_REPOSITORY $BASE_ARCH $p
[ "$pkg_name" ] || {
echo "Error: internal error, should never be here; aborting."
exit 1
}
port_pkg_ver=$pkg_version
port_pkg_rel=$pkg_release
get_pkg_buildinfo $DATADIR/$PORT_REPOSITORY $TARGET_ARCH $p
if [ "$pkg_name" ]; then
pkg_milestone=`echo $pkg_release | sed "s|[0-9.]*\(.*\)|\1|"`
if [ "$pkg_version" != "$port_pkg_ver" ]; then
echo "Package $pkg_name#${port_pkg_ver}($TARGET_ARCH) differs from $pkg_name#${pkg_version}($BASE_ARCH); port needed."
target_pkg_name=$pkg_name
target_pkg_ver=$pkg_version
target_pkg_rel=$pkg_release
target_pkg_milestone=`echo $target_pkg_rel | sed "s|[0-9.]*\(.*\)|\1|"`
if [ "$target_pkg_milestone" != "$REBUILD_MILESTONE" ]; then
JOB=(${JOB[*]} $p)
elif [ "$pkg_release" != "$port_pkg_rel" ]; then
echo "Package $pkg_name#${port_pkg_ver}-${port_pkg_rel}($TARGET_ARCH) differs from $pkg_name#${pkg_version}-${pkg_release}($BASE_ARCH); port needed."
JOB=(${JOB[*]} $p)
elif [ "$REBUILD_MILESTONE" -a "$pkg_milestone" != "$REBUILD_MILESTONE" ]; then
echo "Package $pkg_name($TARGET_ARCH) was not built for '$REBUILD_MILESTONE' milestone; rebuild needed."
JOB=(${JOB[*]} $p)
else
echo "Package $pkg_name#${port_pkg_ver}($TARGET_ARCH) is up to date."
fi
else
echo "$p#${port_pkg_ver}($BASE_ARCH) is in port repository but $p#${base_pkg_ver}($TARGET_ARCH) is in base repository; port needed."
JOB=(${JOB[*]} $p)
fi
fi
done
echo "Packages to rebuild: ${JOB[*]}"
fi
echo "Packages to port: ${needport_list[*]}"
for p in ${needport_list[*]}; do
JOB=(${JOB[*]} $p)
done
[ -e $DATADIR/autoport-$PORT_REPOSITORY-current ] && \
mv $DATADIR/autoport-$PORT_REPOSITORY-current $DATADIR/autoport-$PORT_REPOSITORY-last
fi
step=0
@ -320,15 +473,20 @@ for TARGET_ARCH in ${TARGET_ARCHS}; do
tmpfile1=`mktemp`
[ -e $DATAARCHDIR/sentjobs ] || > $DATAARCHDIR/sentjobs
find $DATAARCHDIR/sentjobs -cmin 120 && {
find $DATAARCHDIR/sentjobs -cmin 120 >/dev/null && {
> $DATAARCHDIR/sentjobs
}
[ -e $DATAARCHDIR/preparedjobs ] || > $DATAARCHDIR/preparedjobs
find $DATAARCHDIR/preparedjobs -ctime 1 && {
find $DATAARCHDIR/preparedjobs -ctime 1 >/dev/null && {
> $DATAARCHDIR/preparedjobs
}
[ -e $DATAARCHDIR/updatedjobs ] || > $DATAARCHDIR/updatedjobs
find $DATAARCHDIR/updatedjobs -ctime 1 >/dev/null && {
> $DATAARCHDIR/updatedjobs
}
sudo autoport-fix-environment $TARGET_ARCH
[ "$FIX_MODE" ] && exit 0
@ -337,13 +495,14 @@ for TARGET_ARCH in ${TARGET_ARCHS}; do
while [ "${JOB[*]}" ]; do
step=`expr $step + 1`
[ $step -gt 1 ] && fetch_repfiles
[ "$BATCH_MODE" -a $step -gt $AUTOPORT_MAX_STEPS ] && {
echo "Maximum steps count reached for batch mode; exiting. See $logfile for details."
break
}
echo "=========="
echo "Step $step"
echo "Scheduled jobs: ${JOB[*]}"
echo "# Step $step"
echo "> Scheduled jobs: ${JOB[*]}"
echo
JOB_MISSINGREQ_OLD=(${JOB_MISSINGREQ[*]})
JOB_MISSINGREQ=()
@ -352,94 +511,139 @@ for TARGET_ARCH in ${TARGET_ARCHS}; do
JOB_FAILED=()
JOB_CANTINSTALL_OLD=(${JOB_CANTINSTALL[*]})
for JOB_NUM in `seq 1 ${#JOB[*]}`; do
JOB_CURRENT=${JOB[$JOB_NUM-1]}
if [ "`grep "^${JOB_CURRENT}$" /etc/autodist/unstage 2>/dev/null`" -o \
"`grep "^${JOB_CURRENT}$" /etc/autodist/unstage.${TARGET_ARCH} 2>/dev/null`" ]; then
echo -n "$JOB_CURRENT: "
JOB_CURRENT=${JOB[$JOB_NUM-1]/\#*}
if [ "${JOB_CURRENT}" != "${JOB[$JOB_NUM-1]}" ]; then
JOB_CURRENT_VERSION=${JOB[$JOB_NUM-1]/*\#}
else
JOB_CURRENT_VERSION=
fi
if [ ! -s $DATADIR/$PORT_REPOSITORY/unstage.${TARGET_ARCH} -o \
"`grep "^${JOB_CURRENT}$" /etc/autodist/unstage.${TARGET_ARCH} 2>/dev/null`" -o \
"`grep "^${JOB_CURRENT}$" $DATADIR/$PORT_REPOSITORY/unstage.${TARGET_ARCH} 2>/dev/null`" ]; then
echo -n "^ $JOB_CURRENT: "
STAGEOPTS=
else
echo -n "$JOB_CURRENT(staging): "
echo -n "^ $JOB_CURRENT(staging): "
STAGEOPTS="$AUTOPORT_STAGEVARS"
fi
if [ "$CROSS_MODE" -a "${JOB_CURRENT:0:5}" == "perl-" ]; then
echo " (SKIPPED) [unable to cross-build perl modules]"
echo "< (SKIPPED) [unable to cross-build perl modules]"
JOB_SKIPPED=(${JOB_SKIPPED[*]} $JOB_CURRENT)
continue
fi
[ "`grep ^$JOB_CURRENT\$ $DATAARCHDIR/sentjobs`" -a ! "$FORCE_MODE" ] && {
echo " (SKIPPED) [already sent]"
echo "< (SKIPPED) [already sent]"
JOB_SKIPPED=(${JOB_SKIPPED[*]} $JOB_CURRENT)
continue
}
if [ "${JOB_MAYBEINSTALLED_NEW[*]}" = "" -a \
"${JOB_MISSINGREQ_OLD[*]}" != "" -a \
"`echo "( ${JOB_FAILED_OLD[*]} )"| grep " $JOB_CURRENT "`" ]; then
echo " (FAILED) [nothing new since previous attempt]"
echo "< (FAILED) [nothing new since previous attempt]"
JOB_FAILED=(${JOB_FAILED[*]} $JOB_CURRENT)
continue
fi
pkg_release=
pkg_version=
get_pkg_buildinfo $DATADIR/$PORT_REPOSITORY $TARGET_ARCH ${JOB_CURRENT} || \
get_pkg_buildinfo $DATADIR/$PORT_REPOSITORY $BASE_ARCH ${JOB_CURRENT} || \
get_pkg_buildinfo $DATADIR/$BASE_REPOSITORY $TARGET_ARCH ${JOB_CURRENT} || \
get_pkg_buildinfo $DATADIR/$BASE_REPOSITORY $BASE_ARCH ${JOB_CURRENT}
pkg_milestone=`echo $pkg_release | sed "s|[0-9.]*\(.*\)|\1|"`
pkg_numrelease=`echo $pkg_release | sed "s|\([0-9.]*\).*|\1|"`
get_pkg_srcinfo $DATADIR/$PORT_REPOSITORY ${JOB_CURRENT} || {
echo "< (FAILED) [error $? in get_pkg_srcinfo]"
JOB_FAILED=(${JOB_FAILED[*]} $JOB_CURRENT)
continue
}
if [ "$JOB_CURRENT_VERSION" -a \
"$JOB_CURRENT_VERSION" != "$src_version" -a \
"$JOB_CURRENT_VERSION" != "$src_version-$src_release" ]; then
echo "< (FAILED) [wrong version $src_version-$src_release != $JOB_CURRENT_VERSION]"
JOB_FAILED=(${JOB_FAILED[*]} $JOB_CURRENT)
continue
fi
DONT_PREPARE_THIS=
RELEASE_UPDATED=
grep -q ^$JOB_CURRENT\$ $DATAARCHDIR/preparedjobs && RELEASE_UPDATED=1
for p in ${JOB_CMDLINE[*]}; do
[ "$p" = "${JOB_CURRENT}" -o "$DONT_PREPARE_ANY" ] || continue
[ -e ${SPECDIR}/${JOB_CURRENT}.spec ] && DONT_PREPARE_THIS="$DONT_PREPARE"
done
[ ! "$DONT_PREPARE_THIS" -a ! "`grep ^$JOB_CURRENT\$ $DATAARCHDIR/preparedjobs`" ] && {
echo -n "prepare"
[ "$VERBOSE_MODE" ] && echo "
%% COMMAND: LANG=C LC_ALL=C autodist -p ${JOB_CURRENT} --server $PORT_REPOSITORY --repository $PORT_REPOSITORY --severity 2 -- $STAGEOPTS"
LANG=C LC_ALL=C autodist -p ${JOB_CURRENT} --server $PORT_REPOSITORY --repository $PORT_REPOSITORY --severity 2 -- $STAGEOPTS &>>$logfile
[ $? -gt 0 ] && {
RES=`find_source_by_provide $PORT_REPOSITORY $JOB_CURRENT`
for j in ${RES}; do
[ "$j" != "$JOB_CURRENT" ] && RESOLVED_JOB="$RESOLVED_JOB $j"
done
if [ "$RESOLVED_JOB" ]; then
echo "(FAILED) [but scheduling $RESOLVED_JOB]"
JOB_FAILED=(${JOB_FAILED[*]} $RESOLVED_JOB)
if [ ! "$REBUILD_DEPENDANT_MODE" -a "$step" = "1" ]; then
REPOSITORY_STRICT_ADD="--repository-strict"
else
echo "(FAILED) "
REPOSITORY_STRICT_ADD=""
fi
# [ "$VERBOSE_MODE" ] && echo "
#%% COMMAND: LANG=C LC_ALL=C autodist -p ${JOB_CURRENT} --server $PORT_REPOSITORY --repository $PORT_REPOSITORY $REPOSITORY_STRICT_ADD --severity 2 -- $STAGEOPTS"
LANG=C LC_ALL=C autodist -p ${JOB_CURRENT} --server $PORT_REPOSITORY --repository $PORT_REPOSITORY $REPOSITORY_STRICT_ADD --severity 2 -- $STAGEOPTS &>$tmpfile
[ $? -gt 0 ] && {
echo "(FAILED) "
JOB_CANTPREPARE=(${JOB_CANTPREPARE[*]} $JOB_CURRENT)
autoport_log ${JOB_CURRENT} prepare failed $tmpfile
continue
} || {
spec_version=`grep -m1 "^Version:" ${SPECDIR}/${JOB_CURRENT}.spec | awk '{ print $2}'`
spec_release=`grep -m1 "^Release:" ${SPECDIR}/${JOB_CURRENT}.spec | awk '{ print $2}'`
if [ "${spec_version}-${spec_release}" != "$src_version-$src_release" ]; then
echo "< (FAILED) [wrong version ${src_version}-${src_release} != ${spec_version}-${spec_release}]"
JOB_CANTPREPARE=(${JOB_CANTPREPARE[*]} $JOB_CURRENT)
autoport_log ${JOB_CURRENT} prepare failed $tmpfile
continue
fi
echo $JOB_CURRENT >> $DATAARCHDIR/preparedjobs
echo -n "(OK) "
autoport_log ${JOB_CURRENT} prepare ok $tmpfile
}
if [ "$PORT_REPOSITORY" != "$DEST_REPOSITORY" ]; then
if [ "$REBUILD_MODE" = "1" -o "$REBUILD_DEPENDANT_MODE" = "1" ]; then
echo -n "update"
[ "$VERBOSE_MODE" ] && echo "
%% COMMAND: LANG=C LC_ALL=C autodist -u -r ${JOB_CURRENT} --severity 2 -- $STAGEOPTS --changelog \"automatic port from $PORT_REPOSITORY\""
LANG=C LC_ALL=C autodist -u -r ${JOB_CURRENT} --severity 2 -- $STAGEOPTS --changelog \"automatic port from $PORT_REPOSITORY\" &>>$logfile
if [ "$REBUILD_DEPENDANT_MODE" ]; then
SCRIPT_ARGS="${JOB_SCRIPTARGS[$JOB_NUM-1]}"
changelogadd="`echo ${SCRIPT_ARGS} | sed "s|--buildreq|,|g;s| ||g;s|^,||g"`"
REBUILD_CHANGELOG="rebuilt by autoport with build requirements: '${changelogadd}'"
fi
# [ "$VERBOSE_MODE" ] && echo "
#%% COMMAND: LANG=C LC_ALL=C autodist -u --rebuild -r ${JOB_CURRENT} --severity 2 -- $STAGEOPTS --changelog \"$REBUILD_CHANGELOG\" --- \"$SCRIPT_ARGS\""
LANG=C LC_ALL=C autodist -u --rebuild -r ${JOB_CURRENT} --severity 2 -- $STAGEOPTS --changelog \"$REBUILD_CHANGELOG\" --- $SCRIPT_ARGS &>$tmpfile
[ $? -gt 0 ] && {
echo "(FAILED) "
autoport_log ${JOB_CURRENT} update failed $tmpfile
continue
} || {
autoport_log ${JOB_CURRENT} update ok $tmpfile
echo -n "(OK) "
RELEASE_UPDATED=1
echo $JOB_CURRENT >> $DATAARCHDIR/updatedjobs
}
elif [ "$REBUILD_MILESTONE" -a "$pkg_milestone" != "$REBUILD_MILESTONE" ]; then
elif [ "$PORT_REPOSITORY" != "$DEST_REPOSITORY" ]; then
echo -n "update"
[ "$pkg_repository" -a "$pkg_version" -a "$pkg_release" ] || {
# [ "$VERBOSE_MODE" ] && echo "
#%% COMMAND: LANG=C LC_ALL=C autodist -u -r ${JOB_CURRENT} --severity 2 -- $STAGEOPTS --changelog \"automatic port from $PORT_REPOSITORY\""
LANG=C LC_ALL=C autodist -u -r ${JOB_CURRENT} --severity 2 -- $STAGEOPTS --changelog \"automatic port from $PORT_REPOSITORY\" --- $SCRIPT_ARGS &>$tmpfile
cat $tmpfile >> $logfile
[ $? -gt 0 ] && {
echo "(FAILED) "
autoport_log ${JOB_CURRENT} update failed $tmpfile
continue
} || {
autoport_log ${JOB_CURRENT} update ok $tmpfile
echo -n "(OK) "
RELEASE_UPDATED=1
}
elif [ "$REBUILD_MILESTONE" -a "$src_milestone" != "$REBUILD_MILESTONE" ]; then
echo -n "update"
[ "$src_repository" -a "$src_version" -a "$src_release" ] || {
echo "(FAILED) [can't get repository information for this package]"
continue
}
src_release_num=`echo $src_release | sed "s|\([0-9.]*\).*|\1|"`
# [ "$VERBOSE_MODE" ] && echo "
#%% COMMAND: LANG=C LC_ALL=C autospec -u ${JOB_CURRENT} -a4 --changelog \"$REBUILD_MILESTONE milestone rebuild\" $src_version $src_release_num${REBUILD_MILESTONE}"
# FIXME: should be implemented in autodist
LANG=C LC_ALL=C autospec -u ${JOB_CURRENT} -a4 ${pkg_version} ${pkg_numrelease}${REBUILD_MILESTONE} \
--changelog "$REBUILD_MILESTONE milestone rebuild" &>$tmpfile
LANG=C LC_ALL=C autospec -u ${JOB_CURRENT} -a4 --changelog "$REBUILD_MILESTONE milestone rebuild" $src_version $src_release_num${REBUILD_MILESTONE} &>$tmpfile
[ $? -gt 0 ] && {
if [ "$VERBOSE_MODE" ]; then
echo
echo "Failed output:"
echo "=============="
echo "= Failed output:"
echo "================"
cat $tmpfile
echo "=============="
echo "================"
echo
fi
cat $tmpfile >> $logfile
@ -447,28 +651,37 @@ for TARGET_ARCH in ${TARGET_ARCHS}; do
echo "(FAILED)"
JOB_LOG=`grep "^?= See " $tmpfile | awk '{ print $3 }'`
[ "$JOB_LOG" ] || JOB_LOG=$tmpfile
autoport_log ${JOB_CURRENT} update failed $tmpfile
continue
} || {
cat $tmpfile >> $logfile
echo -n "(OK) "
autoport_log ${JOB_CURRENT} update ok $tmpfile
RELEASE_UPDATED=1
}
fi
}
echo -n "port"
[ "$pkg_repository" ] || {
if [ ! "$src_repository" -a "$DONT_PREPARE_THIS" != "1" ]; then
echo "(FAILED) [can't get repository information for this package]"
autoport_log ${JOB_CURRENT} port failed
continue
}
[ "$PORT_REPOSITORY" != "$DEST_REPOSITORY" ] && pkg_repository="$DEST_REPOSITORY"
[ ! "$DONT_PREPARE_THIS" -a "$PORT_REPOSITORY" = "$DEST_REPOSITORY" -a ! "$REBUILD_MILESTONE" ] && NOSRPM_OPTS="--nosrpm" || NOSRPM_OPTS="--force"
LANG=C LC_ALL=C autodist -b -s ${JOB_CURRENT} --arch $TARGET_ARCH --server $pkg_repository --repository $PORT_REPOSITORY --severity 2 $FORCE_FLAG -- $STAGEOPTS $NOSRPM_OPTS &>$tmpfile
fi
SEND_REPOSITORY=$DEST_REPOSITORY
if [ ! "$RELEASE_UPDATED" -a ! "$DONT_PREPARE_THIS" ]; then
SEND_REPOSITORY=$src_repository
fi
[ ! "$DONT_PREPARE_THIS" -a ! "$RELEASE_UPDATED" ] && NOSRPM_OPTS="--nosrpm" || NOSRPM_OPTS="--force"
# [ "$VERBOSE_MODE" ] && echo "
#%% COMMAND: LANG=C LC_ALL=C autodist -b -s ${JOB_CURRENT} --arch $TARGET_ARCH --server $SEND_REPOSITORY --repository $PORT_REPOSITORY --severity 2 $FORCE_FLAG -- $STAGEOPTS $NOSRPM_OPTS"
LANG=C LC_ALL=C autodist -b -s ${JOB_CURRENT} --arch $TARGET_ARCH --server $SEND_REPOSITORY --repository $PORT_REPOSITORY --severity 2 $FORCE_FLAG -- $STAGEOPTS $NOSRPM_OPTS &>$tmpfile
[ $? -gt 0 ] && {
if [ "$VERBOSE_MODE" ]; then
echo
echo "Failed output:"
echo "=============="
echo "= Failed output:"
echo "================"
cat $tmpfile
echo "=============="
echo "================"
echo
fi
cat $tmpfile >> $logfile
@ -476,24 +689,37 @@ for TARGET_ARCH in ${TARGET_ARCHS}; do
echo "(FAILED)"
JOB_LOG=`grep "^?= See " $tmpfile | awk '{ print $3 }'`
[ "$JOB_LOG" ] || JOB_LOG=$tmpfile
find_requirements $JOB_LOG
[ ! "$REBUILD_MILESTONE" ] && find_requirements $JOB_LOG
autoport_log ${JOB_CURRENT} port failed $tmpfile
continue
} || {
cat $tmpfile >> $logfile
JOB_SENT=(${JOB_SENT[*]} $JOB_CURRENT)
echo $JOB_CURRENT >> $DATAARCHDIR/sentjobs
echo -n "(OK) "
autoport_log ${JOB_CURRENT} port ok $tmpfile
if [ "$WEBBUILD_URL" -a "$WEBBUILD_USER" ]; then
if [ "$WEBBUILD_USER_CMDLINE" ]; then
curl -s "$WEBBUILD_URL?REQUEST=message&USER=$WEBBUILD_USER&\
SECRET=`cgi_encodevar ${WEBBUILD_SECRET}`&USER_EMAIL=$WEBBUILD_EMAIL&\
MESSAGE=`cgi_encodevar \"(invoked by $WEBBUILD_USER_CMDLINE) ported <b>$JOB_CURRENT</b> to <b>$TARGET_ARCH</b> and sent it to <b>$SEND_REPOSITORY</b>\"`" >/dev/null
else
curl -s "$WEBBUILD_URL?REQUEST=message&USER=$WEBBUILD_USER&\
SECRET=`cgi_encodevar ${WEBBUILD_SECRET}`&USER_EMAIL=$WEBBUILD_EMAIL&\
MESSAGE=`cgi_encodevar \"ported <b>$JOB_CURRENT</b> to <b>$TARGET_ARCH</b> and sent it to <b>$SEND_REPOSITORY</b>\"`" >/dev/null
fi
fi
}
echo -n "install"
LANG=C LC_ALL=C autodist -i ${JOB_CURRENT} --arch $TARGET_ARCH --force --severity 2 -- $STAGEOPTS &>>$tmpfile
LANG=C LC_ALL=C autodist -i ${JOB_CURRENT} --arch $TARGET_ARCH --force --severity 2 -- $STAGEOPTS &>$tmpfile
# --server $DEST_REPOSITORY --repository $PORT_REPOSITORY
[ $? -gt 0 ] && {
if [ "$VERBOSE_MODE" ]; then
echo
echo "Failed output:"
echo "=============="
echo "= Failed output:"
echo "================"
cat $tmpfile
echo "=============="
echo "================"
echo
fi
cat $tmpfile >> $logfile
@ -506,7 +732,8 @@ for TARGET_ARCH in ${TARGET_ARCHS}; do
JOB_MAYBEINSTALLED_NEW=(${JOB_MAYBEINSTALLED_NEW[*]} $JOB_CURRENT)
JOB_LOG=`grep "^?= See " $tmpfile | awk '{ print $3 }'`
[ "$JOB_LOG" ] || JOB_LOG=$tmpfile
find_requirements $JOB_LOG
[ ! "$REBUILD_MILESTONE" ] && find_requirements $JOB_LOG
autoport_log ${JOB_CURRENT} install failed $tmpfile
continue
} || {
cat $tmpfile >> $logfile
@ -514,6 +741,7 @@ for TARGET_ARCH in ${TARGET_ARCHS}; do
JOB_MAYBEINSTALLED_NEW=(${JOB_MAYBEINSTALLED_NEW[*]} $JOB_CURRENT)
JOB_COMPLETED=(${JOB_COMPLETED[*]} $JOB_CURRENT)
echo -n "(OK)"
autoport_log ${JOB_CURRENT} install ok $tmpfile
}
echo
done
@ -522,8 +750,8 @@ for TARGET_ARCH in ${TARGET_ARCHS}; do
JOB_CANTINSTALL=()
for JOB_NUM in `seq 1 ${#JOB_CANTINSTALL_OLD[*]}`; do
JOB_CURRENT=${JOB_CANTINSTALL_OLD[$JOB_NUM-1]}
if [ "`grep "^${JOB_CURRENT}$" /etc/autodist/unstage 2>/dev/null`" -o \
"`grep "^${JOB_CURRENT}$" /etc/autodist/unstage.${TARGET_ARCH} 2>/dev/null`" ]; then
if [ "`grep "^${JOB_CURRENT}$" /etc/autodist/unstage.${TARGET_ARCH} 2>/dev/null`" -o \
"`grep "^${JOB_CURRENT}$" $DATADIR/$PORT_REPOSITORY/unstage.$TARGET_ARCH 2>/dev/null`" ]; then
echo -n "$JOB_CURRENT: "
STAGEOPTS=
else
@ -536,10 +764,10 @@ for TARGET_ARCH in ${TARGET_ARCHS}; do
[ $? -gt 0 ] && {
if [ "$VERBOSE_MODE" ]; then
echo
echo "Failed output:"
echo "=============="
echo "= Failed output:"
echo "================"
cat $tmpfile
echo "=============="
echo "================"
echo
fi
cat $tmpfile >> $logfile
@ -560,22 +788,23 @@ for TARGET_ARCH in ${TARGET_ARCHS}; do
JOB_MAYBEINSTALLED_NEW=(${JOB_MAYBEINSTALLED_NEW[*]} $JOB_CURRENT)
JOB_COMPLETED=(${JOB_COMPLETED[*]} $JOB_CURRENT)
echo -n "(OK)"
autoport_log ${JOB_CURRENT} retryinstall ok $tmpfile
}
echo
done
fi
echo "Skipped jobs: ${JOB_SKIPPED[*]}"
echo "Unpreparable jobs: ${JOB_CANTPREPARE[*]}"
echo "Missing requirements: ${JOB_MISSINGREQ[*]}"
echo "Completed jobs: ${JOB_COMPLETED[*]}"
echo "Installation error for: ${JOB_CANTINSTALL[*]}"
echo "Failed jobs: ${JOB_FAILED[*]}"
echo "| Skipped jobs: ${JOB_SKIPPED[*]}"
echo "| Unpreparable jobs: ${JOB_CANTPREPARE[*]}"
echo "| Missing requirements: ${JOB_MISSINGREQ[*]}"
echo "| Completed jobs: ${JOB_COMPLETED[*]}"
echo "| Installation error for: ${JOB_CANTINSTALL[*]}"
echo "| Failed jobs: ${JOB_FAILED[*]}"
write_last_file
[ "${JOB[*]}" == "${JOB_FAILED[*]}" -a \
"${JOB_MISSINGREQ[*]}" == "" -a \
"${JOB_CANTINSTALL_OLD[*]}" == "${JOB_CANTINSTALL[*]}" ] && {
echo "Loop detected. Finishing. See $logfile for details."
echo "! Loop detected. Finishing. See $logfile for details."
rm -f $tmpfile $tmpfile1
exit 1
}
@ -584,5 +813,6 @@ for TARGET_ARCH in ${TARGET_ARCHS}; do
done
rm -f $tmpfile $tmpfile1
done
echo "All jobs completed. See $logfile for details."
exit 0
echo "* All jobs completed. See $logfile for details."
[ "$BATCH_MODE" ] && rm -f $PIDFILE
exit ${#JOB_FAILED[*]}

57
autoport-chroot Executable file
View File

@ -0,0 +1,57 @@
#!/bin/bash
#
# autoport-chroot
# (c) 2012-2013 by Silvan Calarco <silvan.calarco@mambasoft.it>
#
. /etc/sysconfig/autoport
CHROOT_TARGET=$1
shift
CHROOT_COMMAND=$@
function usage() {
echo "\
$0
"$"Copyright (C) 2012 Silvan Calarco <silvan.calarco@mambasoft.it>""
"$"Released under the terms of the GNU GPL v3 license"
echo "
"$"Enters autoport chroot environment.""
"$"Usage"":
$me chroot_target [command [args..]]
"
}
[ "$CHROOT_TARGET" ] || {
usage
exit 1
}
[ "`uname -m`" = "x86_64" ] && HOST_IS_X86_64=1
for i in `seq 0 ${#AUTOPORT_ARCH[*]}`; do
[ "${AUTOPORT_CHROOT[$i]}" = "$CHROOT_TARGET" ] || continue
if [ "$HOST_IS_X86_64" -a "${AUTOPORT_ARCH[$i]}" != "x86_64" ]; then
CMD_PREFIX=linux32
else
CMD_PREFIX=
fi
if [ "$CHROOT_COMMAND" ]; then
$CMD_PREFIX /usr/sbin/chroot /var/autoport/${AUTOPORT_CHROOT[$i]} su -l $SU_APPEND ${AUTOPORT_CHROOT_USER[$i]} -c "${CHROOT_COMMAND}"
else
echo "Entering ${AUTOPORT_CHROOT[$i]} autoport chroot environment"
hostname=`hostname`
grep $hostname /var/autoport/${AUTOPORT_CHROOT[$i]}/etc/hosts >/dev/null || {
sed -i "s|\(^127.0.0.1[[:space:]]*\)|\1$hostname |" /var/autoport/${AUTOPORT_CHROOT[$i]}/etc/hosts
}
[ -e /var/autoport/${AUTOPORT_CHROOT[$i]}/etc/profile.d/autoport.sh ] || {
echo "PS1='[\u@${AUTOPORT_CHROOT[$i]} \W]\$ '" > /var/autoport/${AUTOPORT_CHROOT[$i]}/etc/profile.d/autoport.sh
}
$CMD_PREFIX /usr/sbin/chroot /var/autoport/${AUTOPORT_CHROOT[$i]} su -l $SU_APPEND ${AUTOPORT_CHROOT_USER[$i]}
fi
exit 0
done
echo "$CHROOT_TARGET: undefined chroot target"
exit 1

View File

@ -30,7 +30,7 @@ function fix_la_files() {
sed -i "s|libdir='/usr/$TARGET_PLATFORM/${_lib}'|libdir='/usr/${_lib}'|g" /usr/${_lib}/*.la
sed -i "s|libdir='/$TARGET_PLATFORM/${_lib}'|libdir='/usr/${_lib}'|g" /usr/${_lib}/*.la
sed -i "s|/usr/$TARGET_PLATFORM/${_lib}|/usr/${_lib}|g" /usr/${_lib}/*.la
sed -i "s|[:space:]/usr/$TARGET_PLATFORM/${_lib}|[:space:]/usr/${_lib}/lib|g" /usr/${_lib}/*.la
sed -i "s|[[:space:]]/usr/$TARGET_PLATFORM/${_lib}|[[:space:]]/usr/${_lib}/lib|g" /usr/${_lib}/*.la
}
done
}
@ -41,7 +41,7 @@ function fix_la_files_cross() {
sed -i "s|libdir='/usr/${_lib}'|libdir='/usr/$TARGET_PLATFORM/${_lib}'|g" /usr/$TARGET_PLATFORM/${_lib}/*.la
sed -i "s|libdir='/${_lib}'|libdir='/usr/$TARGET_PLATFORM/${_lib}'|g" /usr/$TARGET_PLATFORM/${_lib}/*.la
sed -i "s|/usr/${_lib}|/usr/$TARGET_PLATFORM/${_lib}|g" /usr/$TARGET_PLATFORM/${_lib}/*.la
sed -i "s|[:space:]/lib/${_lib}|[:space:]/usr/$TARGET_PLATFORM/${_lib}/lib|g" /usr/$TARGET_PLATFORM/${_lib}/*.la
sed -i "s|[[:space:]]/lib/${_lib}|[[:space:]]/usr/$TARGET_PLATFORM/${_lib}/lib|g" /usr/$TARGET_PLATFORM/${_lib}/*.la
}
done
}

115
autoport-launcher Executable file
View File

@ -0,0 +1,115 @@
#!/bin/bash
#
# autoport launcher
# (c) 2021-2024 by Silvan Calarco <silvan.calarco@mambasoft.it>
#
#. /etc/sysconfig/openmamba-central
. /etc/sysconfig/autoport
[ "$AUTOPORT_ENABLE" = "1" -o "$AUTOPORT_ENABLE" = "true" ] || exit 0
i=$1
[ "$i" ] || {
echo "Usage: autoport-launcher autoport_conf"
exit 1
}
[ "`uname -m`" = "x86_64" ] && HOST_IS_X86_64=1
autodist-cleanold
[ "${AUTOPORT_DISABLE[$i]}" -a "${AUTOPORT_DISABLE[$i]}" != "0" ] && exit 0
PIDFILE=/run/autodist/autoport-launcher-${i}.pid
[ -e $PIDFILE ] && {
PIDCHECK=`cat $PIDFILE`
[ "$PIDCHECK" -a -e /proc/$PIDCHECK ] && {
echo "autoport-launcher for configuration $i already running; exiting."
exit 0
}
}
echo $$ > $PIDFILE
trap "rm -f $PIDFILE; exit 1" SIGQUIT SIGINT SIGKILL SIGTERM
if [ "$HOST_IS_X86_64" -a "${AUTOPORT_ARCH[$i]}" != "x86_64" ]; then
CMD_PREFIX=linux32
else
CMD_PREFIX=
fi
UPDATE_DONE=
for r in ${AUTOPORT_REPOSITORIES[$i]}; do
if [ "${AUTOPORT_NATIVE[$i]}" ]; then
AUTOPORT_PIDFILE="/run/autodist/autoport-${AUTOPORT_ARCH[$i]}-$r.pid"
LOGFILE="/var/autodist/log/autoport-native-$r-${AUTOPORT_ARCH[$i]}.log"
LASTLOGFILE="/var/autodist/log/autoport-native-$r-${AUTOPORT_ARCH[$i]}-last.log"
elif [ "${AUTOPORT_CHROOT[$i]}" ]; then
AUTOPORT_PIDFILE="/var/autoport/${AUTOPORT_CHROOT[$i]}/run/autodist/autoport-${AUTOPORT_ARCH[$i]}-$r.pid"
LOGFILE="/var/autodist/log/autoport-chroot-$r-${AUTOPORT_CHROOT[$i]}.log"
LASTLOGFILE="/var/autodist/log/autoport-chroot-$r-${AUTOPORT_CHROOT[$i]}-last.log"
elif [ "${AUTOPORT_CROSS[$i]}" ]; then
AUTOPORT_PIDFILE="/run/autoport/autoport-${AUTOPORT_ARCH[$i]}-$r.pid"
LOGFILE="/var/autodist/log/autoport-cross-$r-${AUTOPORT_CROSS[$i]}.log"
LASTLOGFILE="/var/autodist/log/autoport-cross-$r-${AUTOPORT_CROSS[$i]}-last.log"
else
continue
fi
if [ "$UPDATE_DONE" == "" ]; then
if [ "${AUTOPORT_NATIVE[$i]}" ]; then
[[ "`/usr/bin/tty`" != "not a tty" ]] && echo "Updating packages in ${AUTOPORT_ARCH[$i]} native environment"
echo "= Updating packages in ${AUTOPORT_ARCH[$i]} native environment..." >> $LOGFILE
LANG=C dnf refresh >> $LOGFILE
LANG=C dnf update -y >> $LOGFILE
UPDATE_DONE=1
elif [ "${AUTOPORT_CHROOT[$i]}" ]; then
[[ "`/usr/bin/tty`" != "not a tty" ]] && echo "Updating packages in ${AUTOPORT_CHROOT[$i]} chroot environment"
#echo "= Updating packages in ${AUTOPORT_CHROOT[$i]} chroot environment..." >> $LOGFILE
LANG=C /usr/sbin/chroot /var/autoport/${AUTOPORT_CHROOT[$i]} dnf refresh > /dev/null
LANG=C /usr/sbin/chroot /var/autoport/${AUTOPORT_CHROOT[$i]} dnf update -y > /dev/null
#[ "${AUTOPORT_CHROOT_ICECREAM[$i]}" ] && LANG=C /usr/sbin/chroot /var/autoport/${AUTOPORT_CHROOT[$i]} /etc/init.d/icecream start
UPDATE_DONE=1
fi
fi
if [ -e $AUTOPORT_PIDFILE ]; then
PIDCHECK=`cat $AUTOPORT_PIDFILE`
if [ "$PIDCHECK" -a -e /proc/$PIDCHECK ]; then
echo "autoport for configuration $i already running; continuing."
continue
fi
fi
[ -e $LOGFILE ] && mv $LOGFILE $LASTLOGFILE
echo "+ Autoport start at `date`" > $LOGFILE
echo "============================================" >> $LOGFILE
if [ "${AUTOPORT_NATIVE[$i]}" ]; then
echo "= Working on $r(${AUTOPORT_ARCH[$i]}) in native mode" >> $LOGFILE
su -l ${AUTOPORT_CHROOT_USER[$i]} -c "$CMD_PREFIX autoport -b -r $r" >> $LOGFILE
AUTODIST_HOME=`getent passwd ${AUTOPORT_CHROOT_USER[$i]} | cut -d: -f6`
cat $AUTODIST_HOME/.autoport/${AUTOPORT_ARCH[$i]}/$r-current.log >> $LOGFILE
elif [ "${AUTOPORT_CHROOT[$i]}" ]; then
echo "= Working on $r(${AUTOPORT_CHROOT[$i]}) in chroot mode..." >> $LOGFILE
$CMD_PREFIX /usr/sbin/chroot /var/autoport/${AUTOPORT_CHROOT[$i]} su -l ${AUTOPORT_CHROOT_USER[$i]} -c "autoport -b -r $r" >> $LOGFILE
if [ "${AUTOPORT_CHROOT_USER[$i]}" = "autodist" ]; then
cat /var/autoport/${AUTOPORT_CHROOT[$i]}/var/autodist/.autoport/${AUTOPORT_ARCH[$i]}/$r-current.log >> $LOGFILE
else
cat /var/autoport/${AUTOPORT_CHROOT[$i]}/home/${AUTOPORT_CHROOT_USER[$i]}/.autoport/${AUTOPORT_ARCH[$i]}/$r-current.log >> $LOGFILE
fi
elif [ "${AUTOPORT_CROSS[$i]}" ]; then
[[ "`/usr/bin/tty`" != "not a tty" ]] && echo "Working on $r(${AUTOPORT_CROSS[$i]}) in cross-platform mode"
echo "= Working on $r(${AUTOPORT_CROSS[$i]}) in cross-platform mode" >> $LOGFILE
su -l autodist -c "autoport -b -x ${AUTOPORT_CROSS[$i]} -r $r" >> $LOGFILE
cat /var/autodist/.autoport/${AUTOPORT_CROSS[$i]}/$r-current.log >> $LOGFILE
fi
echo "- Autoport end at `date`" >> $LOGFILE
echo "============================================" >> $LOGFILE
done
rm -f ${PIDFILE}

View File

@ -3,10 +3,10 @@
DISTRO="openmamba"
VENDOR="openmamba"
curl_opts_netlink="--connect-timeout 15 --retry 3 --limit-rate 400k -Y 1 -C -s"
curl_opts_netlink="--connect-timeout 15 --retry 3 -s"
packager_fullname="Automatic Build System"
packager_email="autodist@mambasoft.it"
packager_email="autodist@openmamba.org"
ftp_rw_server_num_default=0
colorize=0
@ -20,72 +20,58 @@ source_dir="/var/autodist/RPM/SOURCES"
build_dir="/var/autodist/RPM/BUILD"
tmppath_dir="/var/tmp/autodist"
ftp_alias[0]="devel"
ftpurl_ro_rpms[0]="ftp://ftp.openmamba.org/pub/openmamba/devel/RPMS.@arch@"
ftpurl_ro_srpms[0]="ftp://ftp.openmamba.org/pub/openmamba/devel/SRPMS.base"
ftp_rw_server[0]="ftp://ftp.openmamba.org"
ftp_alias[0]="base"
ftpurl_ro_rpms[0]="https://push.openmamba.org/pub/openmamba/base/RPMS.@arch@"
ftpurl_ro_srpms[0]="https://push.openmamba.org/pub/openmamba/base/SRPMS.base"
ftp_rw_server[0]="https://push.openmamba.org/pub/openmamba/base"
ftp_rw_port[0]=
ftp_rw_passive_mode[0]=on
ftp_rw_user[0]=
ftp_rw_passwd[0]=
ftp_rw_rpms_dir[0]="/RPMS.@arch@"
ftp_rw_srpms_dir[0]="/SRPMS.base"
arch_list[0]="i586 ppc arm x86_64"
arch_noarch_upload[0]="${arch_list[0]}"
arch_list[0]="i586 x86_64 aarch64"
arch_noarch_upload[0]="@arch@"
ftpdir_rw_old[0]="/old"
ftp_alias[1]="devel-games"
ftpurl_ro_rpms[1]="ftp://ftp.openmamba.org/pub/openmamba/devel-games/RPMS.@arch@"
ftpurl_ro_srpms[1]="ftp://ftp.openmamba.org/pub/openmamba/devel-games/SRPMS.base"
ftp_rw_server[1]="ftp://ftp.openmamba.org"
ftp_alias[1]="devel-makedist"
ftpurl_ro_rpms[1]="https://push.openmamba.org/pub/openmamba/devel-makedist/RPMS.@arch@"
ftpurl_ro_srpms[1]="https://push.openmamba.org/pub/openmamba/devel-makedist/SRPMS.base"
ftp_rw_server[1]="https://push.openmamba.org/pub/openmamba/devel-makedist"
ftp_rw_port[1]=
ftp_rw_passive_mode[1]=on
ftp_rw_user[1]=
ftp_rw_passwd[1]=
ftp_rw_rpms_dir[1]="/RPMS.@arch@"
ftp_rw_srpms_dir[1]="/SRPMS.base"
arch_list[1]="i586"
arch_noarch_upload[1]="${arch_list[1]}"
arch_list[1]="i586 x86_64 aarch64"
arch_noarch_upload[1]="@arch@"
ftpdir_rw_old[1]="/old"
ftp_alias[2]="devel-makedist"
ftpurl_ro_rpms[2]="ftp://ftp.openmamba.org/pub/openmamba/devel-makedist/RPMS.@arch@"
ftpurl_ro_srpms[2]="ftp://ftp.openmamba.org/pub/openmamba/devel-makedist/SRPMS.base"
ftp_rw_server[2]="ftp://ftp.openmamba.org"
ftp_alias[2]="devel-misc"
ftpurl_ro_rpms[2]="https://push.openmamba.org/pub/openmamba/devel-misc/RPMS.@arch@"
ftpurl_ro_srpms[2]="https://push.openmamba.org/pub/openmamba/devel-misc/SRPMS.base"
ftp_rw_server[2]="https://push.openmamba.org/pub/openmamba/devel-misc"
ftp_rw_port[2]=
ftp_rw_passive_mode[2]=on
ftp_rw_user[2]=
ftp_rw_passwd[2]=
ftp_rw_rpms_dir[2]="/RPMS.@arch@"
ftp_rw_srpms_dir[2]="/SRPMS.base"
arch_list[2]="i586"
arch_noarch_upload[2]="${arch_list[2]}"
arch_list[2]="i586 x86_64 aarch64"
arch_noarch_upload[2]="@arch@"
ftpdir_rw_old[2]="/old"
ftp_alias[3]="devel-autodist"
ftpurl_ro_rpms[3]="ftp://ftp.openmamba.org/pub/openmamba/devel-autodist/RPMS.@arch@"
ftpurl_ro_srpms[3]="ftp://ftp.openmamba.org/pub/openmamba/devel-autodist/SRPMS.base"
ftp_rw_server[3]="ftp://ftp.openmamba.org"
ftpurl_ro_rpms[3]="https://push.openmamba.org/pub/openmamba/devel-autodist/RPMS.@arch@"
ftpurl_ro_srpms[3]="https://push.openmamba.org/pub/openmamba/devel-autodist/SRPMS.base"
ftp_rw_server[3]="https://push.openmamba.org/pub/openmamba/devel-autodist"
ftp_rw_port[3]=
ftp_rw_passive_mode[3]=on
ftp_rw_user[3]=
ftp_rw_passwd[3]=
ftp_rw_rpms_dir[3]="/RPMS.@arch@"
ftp_rw_srpms_dir[3]="/SRPMS.base"
arch_list[3]="i586"
arch_noarch_upload[3]="${arch_list[3]}"
arch_list[3]="i586 x86_64 aarch64"
arch_noarch_upload[3]="@arch@"
ftpdir_rw_old[3]="/old"
ftp_alias[4]="devel-future"
ftpurl_ro_rpms[4]="ftp://ftp.openmamba.org/pub/openmamba/devel-future/RPMS.@arch@"
ftpurl_ro_srpms[4]="ftp://ftp.openmamba.org/pub/openmamba/devel-future/SRPMS.base"
ftp_rw_server[4]="ftp://ftp.openmamba.org"
ftp_rw_port[4]=
ftp_rw_passive_mode[4]=on
ftp_rw_user[4]=
ftp_rw_passwd[4]=
ftp_rw_rpms_dir[4]="/RPMS.@arch@"
ftp_rw_srpms_dir[4]="/SRPMS.base"
arch_list[4]="i586"
arch_noarch_upload[4]="${arch_list[4]}"
ftpdir_rw_old[4]="/old"

View File

@ -4,17 +4,15 @@ openmamba-sound-theme
desktop-base-openmamba
autodist
kernel27
rpm
apt
rootfiles
soundfont-2rock9
livecd-tools
makedist
makedist-openmamba
postplug
grub-theme-openmamba
kdevelop
lxde
libqt
distromatic
u-boot
openmamba-distro-compat
xorg-apps

View File

@ -1,16 +1,61 @@
# Global configuration file for autodist
#
REPS_BASE_URL=http://www.openmamba.org/pub/openmamba
AUTODIST_ARCHS=(i586 x86_64 arm aarch64)
SITE_BASE_URL=https://openmamba.org
REPS_BASE_URL=https://push.openmamba.org/pub/openmamba
LOCAL_REPS_BASE_DIR=/var/ftp/pub/openmamba
SEND_SERVER=devel-autodist
GNOME_VER=2.32.0
AUTOBUILD_MAXNUM=150
#WEBBUILD_URL=http://localhost/cgi-bin/webbuild
#WEBBUILD_USER=
#WEBBUILD_EMAIL=
#WEBBUILD_SECRET=
WEBBUILD_STATEDIR=/var/webbuild
WEBBUILD_DISTROQUERY_URL="http://www.openmamba.org/cgi-bin/distroquery"
AUTOBUILD_MAXNUM=500
AUTOBUILD_DATEFROM=20060601
AUTOBUILD_SKIP_DAYS=7
AUTOBUILD_SKIP_DAYS=28
AUTOBUILD_SUCCESS_DAYS=3
AUTODIST_REPOSITORY=devel-autodist
AUTODIST_DELAYED_REPOSITORY=devel-future
AUTODIST_REPOSITORIES=(devel devel-games devel-makedist devel-kernel devel-xorg devel-kde4 devel-autodist)
AUTODIST_REPOSITORIES=(base devel-makedist devel-autodist devel-misc)
AUTOPORT_UNSTAGE_ARCHS="i586"
AUTOPORT_STAGEVARS="--define stage1=1"
AUTOPORT_MAX_STEPS=15
AUTOPORT_MAX_STEPS=10
AUTOPORT_IGNORE_LIST=""
#RPMDIR=/usr/src/RPM
AUTODIST_REBUILDOLD_MAX=20
AUTODIST_REBUILDOLD_FROMDATE=20090101
#AUTODIST_GIT_SYNC=1
# Variables used by autodist-cleanold
RPMS_CTIME_OLD="+3"
BUILD_CTIME_OLD="+3"
SOURCES_CTIME_OLD="+7"
SOURCES_ARCHIVES_CTIME_OLD="+7"
SOURCES_PATCH_CTIME_OLD="+365"
SRPMS_CTIME_OLD="+3"
TMP_CTIME_OLD="+2"
#
# Set to disable autodist-repository and use local list
#
WEBBUILD_REPOSITORIES=(base devel-kernel devel-makedist devel-misc devel-autodist devel-future devel-past \
milestone1 milestone1-updates milestone1-games milestone1-1.1 milestone1-makedist \
milestone2 milestone2-games milestone2-updates milestone2-kernel milestone2-kde4 \
milestone2-xorg milestone2-makedist milestone2-java \
milestone1-java milestone1-contrib)
#
# Set to enable autodist-repository (you also need to disable WEBBUILD_REPOSITORIES above)
#
#AUTODIST_REPOSITORIES_LOCAL_REPS=(base devel-kernel devel-makedist devel-misc devel-autodist \
# devel-future devel-past \
# milestone3 milestone3-games milestone3-updates milestone3-makedist \
# milestone2 milestone2-games milestone2-updates milestone2-kernel milestone2-kde4 \
# milestone2-xorg milestone2-makedist milestone2-java milestone2-kernel-next \
# milestone1 milestone1-updates milestone1-games milestone1-1.1 milestone1-makedist)
#AUTODIST_REPOSITORIES_REMOTE_REPS=(devel-contrib \
# milestone1-java milestone1-contrib)
#AUTODIST_REPOSITORIES_TRANSITIONAL_REP=devel-makedist
#AUTODIST_REPOSITORIES_REMOTE_FTPUSER=
#AUTODIST_REPOSITORIES_REMOTE_FTPPASS=
#AUTODIST_REPOSITORIES_REMOTE_FTP=

12
etc/autodist/config-git Normal file
View File

@ -0,0 +1,12 @@
REPO_DIR = "/var/ftp/pub/openmamba/base"
ARCHIVE_DIR = "%(REPO_DIR)s/archive"
OLD_DIR = "%(REPO_DIR)s/old"
SRPMS_DIR = "%(REPO_DIR)s/SRPMS.base"
GITEA_URL = "https://src.openmamba.org"
GITEA_SSH_URL = "ssh://gitea@src.openmamba.org:3326/rpms/"
GITEA_TOKEN = "<replace with a valid token>"
GITEA_ORGANIZATION = "rpms"
COMMITTER_USER = "autodist"
COMMITTER_EMAIL = "autodist@openmamba.org"

View File

@ -1,317 +0,0 @@
# openmamba autodist build jobs database - architecture independent
#
# Copyright (c) 2006-2012 by Silvan Calarco <silvan.calarco@mambasoft.it>
# Released under the terms of the GNU GPL version 3 license
#
kernel=(
kernel
target,KERNEL_TARGET
i586,mamba
i586,mamba-64GB
arm,mamba-arm
x86_64,mamba-x86_64
)
kernel_64GB=(
kernel
target,KERNEL_TARGET
i586,mamba-64GB
)
kernel_x86_64=(
kernel
target,KERNEL_TARGET
x86_64,mamba-x86_64
)
kernel_hannspad=(
kernel-hannspad
target
arm
)
kernel_iconia=(
kernel-iconia
target
arm
)
#ppc,mamba
#x86_64,mamba
kernel_extramodules=(
kernel-extramodules
target,KERNEL_TARGET
i586,mamba
i586,mamba-64GB
)
kernel_packages_old=(
hsfmodem,slmodem,compat-wireless,alsa-driver,ati-driver,lirc,ndiswrapper,NVIDIA,NVIDIA_71xx,NVIDIA_96xx,NVIDIA_173xx,VirtualBox,\
broadcom-sta,atheros-81,drbd,rtl8192se
target,KERNEL_TARGET,KERNEL_VER
i586,mamba,3.0
i586,mamba-64GB,3.0
)
kernel_packages=(
hsfmodem,slmodem,compat-wireless,alsa-driver,ati-driver,lirc,ndiswrapper,NVIDIA,NVIDIA_71xx,NVIDIA_96xx,NVIDIA_173xx,VirtualBox,\
broadcom-sta,stk11xx,cm2020,rtl8192se
target,KERNEL_TARGET,KERNEL_VER
i586,mamba,-
i586,mamba-64GB,-
)
kernel_packages_new=(
hsfmodem,slmodem,compat-wireless,alsa-driver,ati-driver,lirc,ndiswrapper,NVIDIA,NVIDIA_71xx,NVIDIA_96xx,NVIDIA_173xx,VirtualBox,\
broadcom-sta,stk11xx,cm2020
target,KERNEL_TARGET,KERNEL_VER
i586,mamba,3.2
i586,mamba-64GB,3.2
)
#rtl8192se
#ppc,mamba
#x86_64,mamba
NVIDIA_all=(
NVIDIA,NVIDIA_71xx,NVIDIA_96xx,NVIDIA_173xx
target,KERNEL_TARGET,KERNEL_VER
i586,mamba,-
i586,mamba-64GB,-
)
alsa_driver=(
alsa-driver
target,KERNEL_TARGET
i586,mamba
i586,mamba-64GB
)
ati_driver=(
ati-driver
target,KERNEL_TARGET
i586,mamba
i586,mamba-64GB
)
#x86_64,mamba-x86_64
broadcom_sta=(
broadcom-sta
target,KERNEL_TARGET
i586,mamba
i586,mamba-64GB
)
kernel_wireless_backport=(
kernel-wireless-backport
target,KERNEL_TARGET
i586,mamba
i586,mamba-64GB
)
lirc=(
lirc
target,KERNEL_TARGET
i586,mamba
i586,mamba-64GB
)
ndiswrapper=(
ndiswrapper
target,KERNEL_TARGET
i586,mamba
i586,mamba-64GB
)
NVIDIA=(
NVIDIA
target,KERNEL_TARGET
i586,mamba
i586,mamba-64GB
)
VirtualBox=(
VirtualBox
target,KERNEL_TARGET
i586,mamba
i586,mamba-64GB
)
compat_wireless=(
compat-wireless
target,KERNEL_TARGET
i586,mamba
i586,mamba-64GB
)
broadcom_sta=(
broadcom-sta
target,KERNEL_TARGET
i586,mamba
i586,mamba-64GB
)
atheros_81=(
atheros-sta
target,KERNEL_TARGET
i586,mamba
i586,mamba-64GB
)
drbd=(
drbd
target,KERNEL_TARGET
i586,mamba
i586,mamba-64GB
)
xorg_drv_video=(
xorg-drv-video,xorg-drv-video-apm,xorg-drv-video-ark,xorg-drv-video-ast,xorg-drv-video-ati,\
xorg-drv-video-chips,xorg-drv-video-cirrus,xorg-drv-video-dummy,xorg-drv-video-fbdev,\
xorg-drv-video-geode,xorg-drv-video-glint,xorg-drv-video-i128,xorg-drv-video-i740,\
xorg-drv-video-intel,xorg-drv-video-mach64,xorg-drv-video-mga,xorg-drv-video-neomagic,\
xorg-drv-video-newport,xorg-drv-video-nouveau,xorg-drv-video-nv,xorg-drv-video-openchrome,\
xorg-drv-video-r128,xorg-drv-video-radeonhd,xorg-drv-video-rendition,xorg-drv-video-s3,\
xorg-drv-video-s3virge,xorg-drv-video-savage,xorg-drv-video-siliconmotion,xorg-drv-video-sis,\
xorg-drv-video-sisusb,xorg-drv-video-trident,xorg-drv-video-tseng,xorg-drv-video-v4l,\
xorg-drv-video-vesa,xorg-drv-video-vmware,xorg-drv-video-voodoo,xorg-drv-video-xgixp
)
xorg_drv_input=(
xorg-drv-input,xorg-drv-input-acecad,xorg-drv-input-aiptek,xorg-drv-input-elographics,\
xorg-drv-input-evdev,xorg-drv-input-fpit,xorg-drv-input-hyperpen,xorg-drv-input-joystick,\
xorg-drv-input-keyboard,xorg-drv-input-mouse,xorg-drv-input-mutouch,xorg-drv-input-penmount,\
xorg-drv-input-synaptics,xorg-drv-input-tslib,xorg-drv-input-vmmouse,xorg-drv-input-void
)
abiword=(
abiword,abiword-docs
%build_and_install
1
)
compiz=(
compiz,compiz-bcop,compiz-plugins-extra,compiz-plugins-main,libcompizconfig,compizconfig-backend-kconfig4,\
compizconfig-simple-settings-manager,emerald
%build_and_install
1
)
# compiz-bcop,compizconfig-backend-kconfig,compizconfig-settings-manager,compizconfig-backend-gconf
compiz09=(
compiz-core,libcompizconfig,python-compizconfig,compizconfig-backend-kconfig4,compiz-fusion-plugins-main,compiz-fusion-plugins-extra
%build_and_install
1
)
#curl=(
#curl
#%build_and_install
#1
#)
evolution=(
libevolution-data-server,evolution
%build_and_install
1
)
#,evolution-exchange
#ekiga=(
#libpt,libopal,ekiga
#%build_and_install
#1
#)
#gobby=(
#obby,gobby
#%build_and_install
#1
#)
kde3=(
kdelibs,kdebase,kdeadmin,kdeutils,kdenetwork,kdeaccessibility,kdepim,kdegames,kdegraphics,kdemultimedia,kdeaddons,kdenetwork,\
kdesdk,kdetoys,kdebindings,kdewebdev,kdeedu,kdeartwork,kde-i18n
%build_and_install
1
)
kde4=(
kdelibs,kdepimlibs,oxygen-icons,kde-runtime,kde-workspace,kde-wallpapers,kde-baseapps,kdepim4,\
kdepim-runtime,kdeadmin,kdemultimedia,kdenetwork4,kdeartwork,kdegames,kdetoys,kdesdk,marble,\
kdeplasma-addons,kde-l10n,blinken,cantor,gwenview,libkdeedu,libanalitza,kalgebra,kalzium,kamera,\
kanagram,kate,kbruch,kcolorchooser,kdegraphics-strigi-analyzer,kgamma,kgeography,khangman,kig,kiten,\
klettres,kmplot,kolourpaint,konsole,kruler,ksnapshot,kstars,libkdcraw,libkexiv2,libkipi,libksane,\
okular,smokegen,smokeqt,smokekde,svgpart,rocs,kwordquiz,kturtle,ktouch,qtruby,korundum,\
kross-interpreters,perl-Qt4,perl-KDE,kdegraphics-thumbnailers,ksaneplugin,parley,step,\
ark,filelight,kcalc,kcharselect,kdf,kfloppy,kgpg,kremotecontrol,ktimer,kwallet,sweeper
%build_and_install
1
)
#kdeaccessibility4,kdeutils
alsa=(
libalsa,libalsa-plugins,alsa-utils,alsa-driver,alsa-tools
%build_and_install
1
)
apache_tomcat=(
apache-tomcat-dbcp,apache-tomcat
%build_and_install
1
)
netbeans=(
netbeans-platform,netbeans
%build_and_install
1
)
firefox=(
xulrunner,firefox
%build_and_install
1
)
xfce=(
libxfce4util,xfconf,libxfcegui4,libxfce4ui,xfce-utils,xfce4-appfinder,xfce4-panel,xfce4-session,xfdesktop,xfwm4
%build_and_install
1
)
#xfce4-mixer,xfprint,orage,xfwm4-themes,libxfce4menu
FlightGear=(
libSimGear,FlightGear
%build_and_install
1
)
valknut=(
libdc,valknut
%build_and_install
1
)
# use for major release update (e.g. 2.24 -> 2.26)
gnome=(
libgnome,libsoup,libgweather,librsvg,libwnck,libgdl,gnome-desktop,python-gnome-desktop,libeel,gnome-icon-theme,gnome-menus,\
libgnome-panel,anjuta,zenity,metacity,nautilus,brasero,cheese,evince,gconf-editor,gedit,gedit-plugins
%build_and_install
1
)
fwbuilder=(
libfwbuilder,fwbuilder
%build_and_install
1
)
koffice=(
koffice
%build_and_install
1
)
#,koffice-i18n

View File

@ -1,73 +0,0 @@
# openmamba autodist build jobs database
#
# Copyright (c) 2006-2010 by Silvan Calarco <silvan.calarco@mambasoft.it>
# Released under the terms of the GNU GPL version 3 license
#
#
# XTC 1 (Cross Toolchain)
#
# build native binutils (gcc needed, so it's not a stage1 build)
# and cross platform binutils
#
binutils=(
binutils
cross_target_cpu,_target_platform
arm,arm-openmamba-linux-gnueabi
avr,avr
)
glibc=(
glibc
cross_target_cpu,bigendian,softfloat,KERNEL_TARGET,KERNEL_VER,build_doc,build_profile,build_selinux
arm,-,-,mamba-arm,-,0,0,0
)
kernel=(
kernel
target,KERNEL_TARGET
arm,mamba-arm
)
linux_firmware=(
linux-firmware
target,KERNEL_TARGET,KERNEL_VER
arm,mamba-arm,3.2
)
pam=(
pam
bootstrap
1
)
rpm=(
rpm
bootstrap
1
)
klibc=(
klibc
KERNEL_VER
2.6.33mamba-arm
)
emacs=(
emacs
bootstrap
1
)
gcc=(
gcc
cross_target_cpu,_target_platform,disable_java,disable_gjdoc
avr,avr,1,-
arm,arm-openmamba-linux-gnueabi,1,1
)
udev=(
udev
%build_and_install
0
)

View File

@ -1,183 +0,0 @@
# openmamba autodist build jobs database for i586 platform
#
# Copyright (c) 2006-2010 by Silvan Calarco <silvan.calarco@mambasoft.it>
# Released under the terms of the GNU GPL version 3 license
#
#
# XTC 1 (Cross Toolchain)
#
# build native binutils (gcc needed, so it's not a stage1 build)
# and cross platform binutils
#
binutils=(
binutils
cross_target_cpu,_target_platform
i586,i586-openmamba-linux-gnu
arm,arm-openmamba-linux-gnueabi
avr,avr
x86_64,x86_64-openmamba-linux-gnu
ppc,ppc-openmamba-linux-gnu
)
#
# XTC 2
#
# glibc stage1: build headers only
glibc_stage1=(
glibc
cross_target_cpu,stage1,_target_platform,KERNEL_TARGET,KERNEL_VER
i586,1,i586-openmamba-linux-gnu,mamba,-
arm,1,arm-openmamba-linux-gnueabi,mamba-arm,2.6.33
ppc,1,ppc-openmamba-linux-gnu,mamba-ppc,2.6.33
x86_64,1,x86_64-openmamba-linux-gnu,mamba-x86_64,-
)
#
# XTC 3
#
gcc_stage1=(
gcc
cross_target_cpu,stage1,_target_platform
arm,1,arm-openmamba-linux-gnueabi
i586,1,i586-openmamba-linux-gnu
ppc,1,ppc-openmamba-linux-gnu
x86_64,1,x86_64-openmamba-linux-gnu
)
#
# XTC 4
#
glibc_stage2=(
glibc
cross_target_cpu,stage2,bigendian,softfloat,_target_platform,KERNEL_TARGET,KERNEL_VER
arm,1,-,-,arm-openmamba-linux-gnueabi,mamba-arm,2.6.33
i586,1,-,-,i586-openmamba-linux-gnu,mamba,-
ppc,1,-,-,ppc-openmamba-linux-gnu,mamba,-
x86_64,1,-,-,x86_64-openmamba-linux-gnu,mamba-x86_64,-
)
#
# XTC 5
#
gcc=(
gcc
cross_target_cpu,_target_platform,disable_java
i586,i586-openmamba-linux-gnu,-
arm,arm-openmamba-linux-gnueabi,1
x86_64,x86_64-openmamba-linux-gnu,1
ppc,ppc-openmamba-linux-gnu,1
avr,avr,1
)
#
# XTC 6
#
glibc=(
glibc
cross_target_cpu,_target_platform,bigendian,softfloat,KERNEL_TARGET,KERNEL_VER
i586,i586-openmamba-linux-gnu,-,-,mamba,-
x86_64,x86_64-openmamba-linux-gnu,-,-,mamba-x86_64,2.6.33
arm,arm-openmamba-linux-gnueabi,-,-,mamba-arm,-
ppc,ppc-openmamba-linux-gnu,-,-,mamba-ppc,2.6.33
)
# XTC 7
cross_environment=(
cross-environment
cross_target_cpu,autodist_crossonly,_target_platform
avr,1,avr
i586,1,i586-openmamba-linux-gnu
arm,1,arm-openmamba-linux-gnueabi
ppc,1,ppc-openmamba-linux-gnu
x86_64,1,x86_64-openmamba-linux-gnu
)
gcc_cross=(
gcc
cross_target_cpu,_target_platform,disable_java
avr,avr,1
)
pkg_config=(
pkg-config
cross_target_cpu,_target_platform
i586,i586-openmamba-linux-gnu
x86_64,x86_64-openmamba-linux-gnu
arm,arm-openmamba-linux-gnueabi
ppc,ppc-openmamba-linux-gnu
)
gcc_uclibc=(
gcc
cross_target_cpu,_target_platform,bigendian,softfloat,KERNEL_TARGET,KERNEL_VER
arm,arm-linux-uclibc,-,-,mamba-arm,2.6.33
)
dietlibc=(
dietlibc
cross_target_cpu
i586
arm
)
gcc34=(
gcc34
cross_target_cpu
i586
ppc
)
klibc=(
klibc
cross_target_cpu,_target_platform,KERNEL_VER
-,-,-
ppc,ppc-openmamba-linux-gnu,2.6.33mamba-ppc
x86_64,x86_64-openmamba-linux-gnu,2.6.33mamba-x86_64
arm,arm-openmamba-linux-gnueabi,2.6.33mamba-arm
)
glibc_arm=(
glibc
cross_target_cpu,bigendian,softfloat,KERNEL_TARGET,KERNEL_VER
arm,-,-,mamba-arm,-
)
#
# ppc cross toolchain
#
binutils_ppc=(
binutils
cross_target_cpu,_target_platform
ppc,ppc-openmamba-linux-gnu
)
glibc_ppc_stage1=(
glibc
cross_target_cpu,stage1,_target_platform,KERNEL_TARGET,KERNEL_VER
ppc,1,ppc-openmamba-linux-gnu,mamba,-
)
gcc_ppc_stage1=(
gcc
cross_target_cpu,stage1,_target_platform
ppc,1,ppc-openmamba-linux-gnu
)
glibc_ppc_stage2=(
glibc
cross_target_cpu,stage2,bigendian,softfloat,_target_platform,KERNEL_TARGET,KERNEL_VER
ppc,1,-,-,ppc-openmamba-linux-gnu,mamba-ppc,2.6.33
)
gcc_ppc=(
gcc
cross_target_cpu,_target_platform
ppc,ppc-openmamba-linux-gnu
)
glibc_ppc=(
glibc
cross_target_cpu,_target_platform,bigendian,softfloat,KERNEL_TARGET,KERNEL_VER
ppc,ppc-openmamba-linux-gnu,-,-,mamba-ppc,2.6.33
)

View File

@ -1,267 +0,0 @@
# openmamba autodist build jobs database
#
# Copyright (c) 2006-2010 by Silvan Calarco <silvan.calarco@mambasoft.it>
# Released under the terms of the GNU GPL version 3 license
#
# XTC 1 (Cross Toolchain)
cross_environment=(
cross-environment
cross_target_cpu,autodist_crossonly,_target_platform
x86_64,1,x86_64-openmamba-linux-gnu
i586,1,i586-openmamba-linux-gnu
arm,1,arm-openmamba-linux-gnueabi
ppc,1,ppc-openmamba-linux-gnu
)
#
# XTC 2
#
# build native binutils (gcc needed, so it's not a stage1 build)
# and cross platform binutils
#
binutils=(
binutils
cross_target_cpu,_target_platform
x86_64,x86_64-openmamba-linux-gnu
i586,i586-openmamba-linux-gnu
arm,arm-openmamba-linux-gnueabi
ppc,ppc-openmamba-linux-gnu
)
#
# XTC 3
#
# glibc stage1: build headers only
glibc_stage1=(
glibc
cross_target_cpu,stage1,_target_platform,KERNEL_TARGET,KERNEL_VER
x86_64,1,x86_64-openmamba-linux-gnu,mamba-x86_64,-
arm,1,arm-openmamba-linux-gnueabi,mamba-arm,2.6.33
i586,1,i586-openmamba-linux-gnu,mamba,-
ppc,1,ppc-openmamba-linux-gnu,mamba,-
)
#
# XTC 4
#
gcc_stage1=(
gcc
cross_target_cpu,stage1,_target_platform
x86_64,1,x86_64-openmamba-linux-gnu
arm,1,arm-openmamba-linux-gnueabi
i586,1,i586-openmamba-linux-gnu
ppc,1,ppc-openmamba-linux-gnu
)
#
# XTC 5
#
glibc_stage2=(
glibc
cross_target_cpu,stage2,bigendian,softfloat,_target_platform,KERNEL_TARGET,KERNEL_VER
x86_64,1,-,-,x86_64-openmamba-linux-gnu,mamba-x86_64,-
arm,1,-,-,arm-openmamba-linux-gnueabi,mamba-arm,2.6.33
i586,1,-,-,i586-openmamba-linux-gnu,mamba,-
ppc,1,-,-,ppc-openmamba-linux-gnu,mamba,-
)
#
# XTC 6
#
gcc=(
gcc
cross_target_cpu,_target_platform
x86_64,x86_64-openmamba-linux-gnu
arm,arm-openmamba-linux-gnueabi
i586,i586-openmamba-linux-gnu
ppc,ppc-openmamba-linux-gnu
)
#
# XTC 7
#
glibc=(
glibc
cross_target_cpu,_target_platform,bigendian,softfloat,KERNEL_TARGET,KERNEL_VER
ppc,ppc-openmamba-linux-gnu,-,-,mamba-ppc,2.6.33
x86_64,x86_64-openmamba-linux-gnu,-,-,mamba-x86_64,-
i586,i586-openmamba-linux-gnu,-,-,mamba,-
arm,arm-openmamba-linux-gnueabi,-,-,mamba-arm,2.6.33
)
gcc_uclibc=(
gcc
cross_target_cpu,_target_platform,bigendian,softfloat,KERNEL_TARGET,KERNEL_VER
arm,arm-linux-uclibc,-,-,mamba-arm,2.6.33
)
dietlibc=(
dietlibc
cross_target_cpu
ppc
x86_64
i586
arm
)
gcc34=(
gcc34
cross_target_cpu
ppc
x86_64
i586
ppc
)
#klibc=(
#klibc
#cross_target_cpu,_target_platform,KERNEL_VER
#-,-,-
#ppc,ppc-openmamba-linux-gnueabi,2.6.33mamba-ppc
#)
kernel=(
kernel
target,KERNEL_TARGET
ppc,mamba-ppc
)
kernel_new=(
kernel
target,KERNEL_TARGET,KERNEL_VER
ppc,mamba-ppc,2.6.33
)
kernel_extra=(
kernel-extramodules
target,KERNEL_TARGET
ppc,mamba-ppc
)
kernel_packages=(
hsfmodem,compat-wireless,ati-driver,NVIDIA,NVIDIA_71xx,NVIDIA_96xx,NVIDIA_173xx,broadcom-sta
target,KERNEL_TARGET,KERNEL_VER
ppc,mamba-ppc,-
)
# slmodem, alsa-driver, lirc,VirtualBox, ndiswrapper, alsa-driver
kernel_packages_new=(
hsfmodem,compat-wireless,ati-driver,NVIDIA,NVIDIA_71xx,NVIDIA_96xx,NVIDIA_173xx,broadcom-sta
target,KERNEL_TARGET,KERNEL_VER
ppc,mamba-ppc,2.6.33
)
NVIDIA_all=(
NVIDIA,NVIDIA_71xx,NVIDIA_96xx,NVIDIA_173xx
target,KERNEL_TARGET,KERNEL_VER
ppc,mamba-ppc
)
alsa_driver=(
alsa-driver
target,KERNEL_TARGET
ppc,mamba-ppc
)
ati_driver=(
ati-driver
target,KERNEL_TARGET
ppc,mamba-ppc
)
broadcom_sta=(
broadcom-sta
target,KERNEL_TARGET
ppc,mamba-ppc
)
kernel_extramodules=(
kernel-extramodules
target,KERNEL_TARGET
ppc,mamba-ppc
)
kernel_nongpl=(
kernel-nongpl
target,KERNEL_TARGET
ppc,mamba-ppc
)
kernel_wireless_backport=(
kernel-wireless-backport
target,KERNEL_TARGET
ppc,mamba-ppc
)
lirc=(
lirc
target,KERNEL_TARGET
ppc,mamba-ppc
)
ndiswrapper=(
ndiswrapper
target,KERNEL_TARGET
ppc,mamba-ppc
)
NVIDIA=(
NVIDIA
target,KERNEL_TARGET
ppc,mamba-ppc
)
VirtualBox=(
VirtualBox
target,KERNEL_TARGET
ppc,mamba-ppc
)
glibc=(
glibc
cross_target_cpu,bigendian,softfloat,KERNEL_TARGET,KERNEL_VER
ppc,-,-,mamba-ppc,2.6.33
)
gcc=(
gcc
cross_target_cpu
ppc
)
binutils=(
binutils
cross_target_cpu
ppc
)
pam=(
pam
bootstrap
1
)
rpm=(
rpm
bootstrap
1
)
klibc=(
klibc
KERNEL_VER
2.6.33mamba-ppc
)
emacs=(
emacs
bootstrap
1
)
gcc=(
gcc
disable_jack,disable_java,disable_gjdoc
1,1,1
)

View File

@ -1,271 +0,0 @@
# openmamba autodist build jobs database
#
# Copyright (c) 2006-2010 by Silvan Calarco <silvan.calarco@mambasoft.it>
# Released under the terms of the GNU GPL version 3 license
#
# XTC 1 (Cross Toolchain)
cross_environment=(
cross-environment
cross_target_cpu,autodist_crossonly,_target_platform
x86_64,1,x86_64-openmamba-linux-gnu
i586,1,i586-openmamba-linux-gnu
arm,1,arm-openmamba-linux-gnueabi
ppc,1,ppc-openmamba-linux-gnu
)
#
# XTC 2
#
# build native binutils (gcc needed, so it's not a stage1 build)
# and cross platform binutils
#
binutils=(
binutils
cross_target_cpu,_target_platform
x86_64,x86_64-openmamba-linux-gnu
i586,i586-openmamba-linux-gnu
arm,arm-openmamba-linux-gnueabi
ppc,ppc-openmamba-linux-gnu
)
#
# XTC 3
#
# glibc stage1: build headers only
glibc_stage1=(
glibc
cross_target_cpu,stage1,_target_platform,KERNEL_TARGET,KERNEL_VER
x86_64,1,x86_64-openmamba-linux-gnu,mamba-x86_64,-
arm,1,arm-openmamba-linux-gnueabi,mamba-arm,2.6.33
i586,1,i586-openmamba-linux-gnu,mamba,-
ppc,1,ppc-openmamba-linux-gnu,mamba,-
)
#
# XTC 4
#
gcc_stage1=(
gcc
cross_target_cpu,stage1,_target_platform
x86_64,1,x86_64-openmamba-linux-gnu
arm,1,arm-openmamba-linux-gnueabi
i586,1,i586-openmamba-linux-gnu
ppc,1,ppc-openmamba-linux-gnu
)
#
# XTC 5
#
glibc_stage2=(
glibc
cross_target_cpu,stage2,bigendian,softfloat,_target_platform,KERNEL_TARGET,KERNEL_VER
x86_64,1,-,-,x86_64-openmamba-linux-gnu,mamba-x86_64,-
arm,1,-,-,arm-openmamba-linux-gnueabi,mamba-arm,2.6.33
i586,1,-,-,i586-openmamba-linux-gnu,mamba,-
ppc,1,-,-,ppc-openmamba-linux-gnu,mamba,-
)
#
# XTC 6
#
gcc=(
gcc
cross_target_cpu,_target_platform
x86_64,x86_64-openmamba-linux-gnu
arm,arm-openmamba-linux-gnueabi
i586,i586-openmamba-linux-gnu
ppc,ppc-openmamba-linux-gnu
)
#
# XTC 7
#
glibc=(
glibc
cross_target_cpu,_target_platform,bigendian,softfloat,KERNEL_TARGET,KERNEL_VER
x86_64,x86_64-openmamba-linux-gnu,-,-,mamba-x86_64,-
i586,i586-openmamba-linux-gnu,-,-,mamba,-
arm,arm-openmamba-linux-gnueabi,-,-,mamba-arm,2.6.33
)
gcc_uclibc=(
gcc
cross_target_cpu,_target_platform,bigendian,softfloat,KERNEL_TARGET,KERNEL_VER
arm,arm-linux-uclibc,-,-,mamba-arm,2.6.33
)
dietlibc=(
dietlibc
cross_target_cpu
x86_64
i586
arm
)
gcc34=(
gcc34
cross_target_cpu
x86_64
i586
ppc
)
kernel=(
kernel
target,KERNEL_TARGET
x86_64,mamba-x86_64
)
#x86_64,mamba-xen
kernel_extra=(
kernel-extramodules
target,KERNEL_TARGET
x86_64,mamba-x86_64
)
#x86_64,mamba-xen
kernel_packages=(
hsfmodem,compat-wireless,ati-driver,NVIDIA,NVIDIA_71xx,NVIDIA_96xx,NVIDIA_173xx,broadcom-sta
target,KERNEL_TARGET,KERNEL_VER
x86_64,mamba-x86_64,-
)
# slmodem, alsa-driver, lirc,VirtualBox, ndiswrapper, alsa-driver
kernel_packages_new=(
hsfmodem,compat-wireless,ati-driver,NVIDIA,NVIDIA_71xx,NVIDIA_96xx,NVIDIA_173xx,broadcom-sta
target,KERNEL_TARGET,KERNEL_VER
x86_64,mamba-x86_64,2.6.33
)
kernelxen_packages=(
alsa-driver,hsfmodem,compat-wireless,ati-driver,ndiswrapper,broadcom-sta
target,KERNEL_TARGET,KERNEL_VER
x86_64,mamba-xen,-
)
NVIDIA_all=(
NVIDIA,NVIDIA_71xx,NVIDIA_96xx,NVIDIA_173xx
target,KERNEL_TARGET,KERNEL_VER
x86_64,mamba-x86_64
)
#x86_64,mamba-xen
alsa_driver=(
alsa-driver
target,KERNEL_TARGET
x86_64,mamba-x86_64
x86_64,mamba-xen
)
ati_driver=(
ati-driver
target,KERNEL_TARGET
x86_64,mamba-x86_64
x86_64,mamba-xen
)
broadcom_sta=(
broadcom-sta
target,KERNEL_TARGET
x86_64,mamba-x86_64
x86_64,mamba-xen
)
kernel_extramodules=(
kernel-extramodules
target,KERNEL_TARGET
x86_64,mamba-x86_64
x86_64,mamba-xen
)
kernel_nongpl=(
kernel-nongpl
target,KERNEL_TARGET
x86_64,mamba-x86_64
x86_64,mamba-xen
)
kernel_wireless_backport=(
kernel-wireless-backport
target,KERNEL_TARGET
x86_64,mamba-x86_64
x86_64,mamba-xen
)
broadcom_sta=(
broadcom-sta
target,KERNEL_TARGET
x86_64,mamba-x86_64
x86_64,mamba-xen
)
lirc=(
lirc
target,KERNEL_TARGET
x86_64,mamba-x86_64
x86_64,mamba-xen
)
ndiswrapper=(
ndiswrapper
target,KERNEL_TARGET
x86_64,mamba-x86_64
x86_64,mamba-xen
)
NVIDIA=(
NVIDIA
target,KERNEL_TARGET
x86_64,mamba-x86_64
)
#x86_64,mamba-xen
VirtualBox=(
VirtualBox
target,KERNEL_TARGET
x86_64,mamba-x86_64
x86_64,mamba-xen
)
glibc=(
glibc
cross_target_cpu,bigendian,softfloat,KERNEL_TARGET,KERNEL_VER
x86_64,-,-,mamba-x86_64,-
)
gcc=(
gcc
cross_target_cpu
x86_64
)
binutils=(
binutils
cross_target_cpu
x86_64
)
pam=(
pam
bootstrap
1
)
rpm=(
rpm
bootstrap
1
)
emacs=(
emacs
bootstrap
1
)
gcc=(
gcc
cross_target_cpu,_target_platform,disable_jack,disable_gjdoc,disable_java
x86_64,x86_64-openmamba-linux-gnu,1,1,0
)

View File

@ -1,83 +0,0 @@
kdebase
kdewebdev
grub
libsqlite2
libglade1
openssl097
gnupg
kannel
ftp
nrg2iso
ddrescue
db42
gcc34
ftpsync
libglib1
gcc33
libxml
libtool1
openldap22
python24
postgresql7
PyQt
libcares1
libraw13941
net-snmp5
libmtp7
gambas
libgda2
libmusicbrainz2
libpng2
libXaw8
icu38
mysql5
libreadline5
libxcb-xlib
autoconf2.13
python
libflac11
libdc1394_control
automake1.10
libusb0
xorg-drv-input
libeigen
libgtk1
java-junit3
lm_sensors2
kernel-extramodules
kernel-nongpl-nvidia
kernel-nongpl-fglrx
kernel-nongpl
automake1.6
libjpeg6b
kernel-nongpl-fglrx
kernel-nongpl-nvidia
db47
arts
kdegraphics
synaptic
libjpeg7
kdevelop
libgda
objectweb-asm1
objectweb-asm2
apache-tomcat5
java-junit381
jakarta-commons-lang24
openssl098
libpng12
java-servletapi4
tcltk84
make381
lilo
rpm516
ffmpeg052
rpm5
libpoppler6
x264-84
db51
kde-i18n
libwpg01
libwps01
libwpd08
db52

View File

@ -1,28 +1,99 @@
#!/bin/bash
#
# Autodist script for updating specfiles
#
# Copyright (c) 2007-2009 by Silvan Calarco <silvan.calarco@mambasoft.it>
# Copyright (c) 2007-2024 by Silvan Calarco <silvan.calarco@mambasoft.it>
# Released with the same license as autodist
#
[ "$1" ] || {
echo "Error: update-specfile: specfile not given; aborting."
SPECFILE=
NEWVERSION=
BUILDREQNUM=0
for ((i=1; i<=$#; i++)); do
case ${!i} in
--buildreq) let i+=1
if [ ! "${!i}" ]; then
echo "ERROR: --buildreq requires at least an argument; aborting."
exit 1
fi
let BUILDREQNUM+=1
BUILDREQ[$BUILDREQNUM]=${!i}
if [ "${!i+1}" -a "${!i+1:0:1}" != "-" ]; then
let i+=1
BUILDREQREL[$BUILDREQNUM]=${!i}
if [ ! "${!i+1}" -o "${!i+1:0:1}" = "-" ]; then
echo "ERROR: update-specfile: --buildreq requires one or three arguments; aborting."
exit 1
fi
let i+=1
BUILDREQVER[$BUILDREQNUM]=${!i}
fi
;;
*) if [ ! "$SPECFILE" ]; then
SPECFILE=${!i}
elif [ ! "$NEWVERSION" ]; then
NEWVERSION=${!i}
else
echo "ERROR: update-specfile: unrecognized script option: '${!i}'; aborting."
exit 1
fi
esac
done
[ "$SPECFILE" ] || {
echo "ERROR: update-specfile: specfile not given; aborting."
exit 1
}
[ -e $1 ] || {
[ -e $SPECFILE ] || {
echo "Error: update-specfile: file $1 does not exist; aborting."
exit 1
}
sed -i "s|^Vendor:.*|Vendor: openmamba|" $1
sed -i "s|^Distribution:.*|Distribution: openmamba|" $1
sed -i "s|silvan\.calarco@qilinux\.it|silvan.calarco@mambasoft.it|" $1
sed -i "/BuildRequires:[[:space:]]*libffmpeg-devel/d" $1
sed -i "s|\(BuildRequires:[[:space:]]*\)libmysql-devel|\1libmysql5-devel|" $1
sed -i "s|\(BuildRequires:[[:space:]]*\)libdb42-devel|\1libdb47-devel|" $1
sed -i "s|\(BuildRequires:[[:space:]]*\)firefox-devel|\1xulrunner-devel|" $1
sed -i "s|^PreReq:[[:space:]]*/sbin/install-info|Requires(post):%{__install_info}|" $1
sed -i "s|^PreReq:[[:space:]]*%{__install_info}|Requires(post):%{__install_info}|" $1
sed -i "s|^PreReq:[[:space:]]*|Requires(pre): |" $1
#sed -i "s|^\(Source.*:[[:space:]]*ftp://ftp.kde.org/pub/kde/stable/.*.tar.\)bz2|\1xz|" $1
# Distribution global changes
sed -i "s|^Vendor:.*|Vendor: openmamba|;
s|^Distribution:.*|Distribution: openmamba|;
/BuildRequires:[[:space:]]*libffmpeg-devel/d;
/^BuildRequires:[[:space:]]*libkdegames-devel/d;
/^BuildRequires:[[:space:]]*libkdegames5-devel/d;
/^BuildRequires:[[:space:]]*python3.7dist/d;
/^BuildRoot:[[:space:]]*.*/d;
\,%post.* -p /sbin/ldconfig$,d;
s|\(BuildRequires:[[:space:]]*\)libmysql-devel|\1libmysql5-devel|;
s|\(BuildRequires:[[:space:]]*\)libdb42-devel|\1libdb47-devel|;
s|\(BuildRequires:[[:space:]]*\)libdb51-devel|\1libdb53-devel|;
s|\(BuildRequires:[[:space:]]*\)firefox-devel|\1xulrunner-devel|;
s|^PreReq:[[:space:]]*/sbin/install-info|Requires(post):%{__install_info}|;
s|^PreReq:[[:space:]]*%{__install_info}|Requires(post):%{__install_info}|;
s|^PreReq:[[:space:]]*|Requires(pre): |;
s|^\(Requires:[[:space:]]*kde-workspace\)$|#\1|;
s|^%patch\([0-9][0-9]*\)|%patch \1|;
s|http://.*.dl\.sourceforge\.net/|https://downloads.sourceforge.net/|;
s|http://ftp.kde.org/stable/|https://download.kde.org/stable/|;
s|ftp://ftp.kde.org/pub/kde/|https://download.kde.org/|;
s|update-mime-database %{|update-mime-database -n %{|;
s|http://download.kde.org/stable/%{version}|https://download.kde.org/stable/applications/%{version}|;
s|http[s]*://pypi.python.org/packages/source/[^/]*/|https://pypi.debian.net/|;
s|http://ftp.gnome.org/pub/GNOME/sources/|https://download.gnome.org/sources/|;
s|ftp://ftp.gnome.org/pub/gnome/sources/|https://download.gnome.org/sources/|" $SPECFILE
# s|;s,.*/man/.*,&.gz,g||;
# s|http.*.cpan.org/.*/\([^/-]*\)\(-.*\)|https://cpan.metacpan.org/modules/by-module/\1/\1\2|;
#sed -i "s|^\(Source.*:[[:space:]]*ftp://ftp.kde.org/pub/kde/stable/.*.tar.\)bz2|\1xz|" $SPECFILE
if [ $BUILDREQNUM -gt 0 ]; then
grep "^## AUTOBUILDREQ-END" $SPECFILE > /dev/null || {
echo "ERROR: update-specfile: missing AUTOBUILDREQ block; aborting."
exit 1
}
for b in `seq 1 $BUILDREQNUM`; do
line=${BUILDREQ[$b]}
if [ "${BUILDREQREL[$b]}" ]; then
line="$line ${BUILDREQREL[$b]} ${BUILDREQVER[$b]}"
fi
sed -i "/^## AUTOBUILDREQ-END/,9999{/BuildRequires:[[:space:]]*${BUILDREQ[$b]}$/d}" $SPECFILE
sed -i "/^## AUTOBUILDREQ-END/,9999{/BuildRequires:[[:space:]]*${BUILDREQ[$b]}[[:space:]]/d}" $SPECFILE
sed -i "/^## AUTOBUILDREQ-END/a BuildRequires: $line" $SPECFILE
done
fi
exit 0

View File

@ -1 +0,0 @@
gcc

View File

@ -1,17 +0,0 @@
libatk
libgtk
libpango
tcltk
dbus
libgsf
python
glib
libnfsidmap
ghostscript
liblcms
ImageMagick4
ImageMagick
gcc
libtiff
libtiff3
libcairo

View File

@ -1,4 +0,0 @@
tcltk
libxml2
libpango
libatk

View File

@ -1,7 +0,0 @@
#!/bin/bash
find /var/autodist/RPM/RPMS/i586/ -maxdepth 1 -ctime +25 -exec rm -rf {} \;
find /var/autodist/RPM/RPMS/noarch/ -maxdepth 1 -ctime +25 -exec rm -rf {} \;
find /var/autodist/RPM/BUILD/ -maxdepth 1 -ctime +25 -exec rm -rf {} \;
find /var/autodist/RPM/SOURCES/ -maxdepth 1 -ctime +120 -exec rm -rf {} \;
find /var/autodist/RPM/SRPMS/ -maxdepth 1 -ctime +90 -exec rm -rf {} \;
find /var/tmp/autodist/ -maxdepth 1 -ctime +25 -exec rm -rf {} \;

View File

@ -0,0 +1,12 @@
#!/bin/bash
#
# autodist-git-sync daily cron script
# (c) 2024 by Silvan Calarco <silvan.calarco@mambasoft.it>
#
. /etc/autodist/config
if [ "$AUTODIST_GIT_SYNC" == "1" ]; then
autodist-git syncrepo
fi
exit 0

View File

@ -0,0 +1,17 @@
#!/bin/bash
#
# autodist autoupdate hourly cron script
# (c) 2008-2021 by Silvan Calarco <silvan.calarco@mambasoft.it>
#
. /etc/autodist/config
. /etc/sysconfig/autoport
# FIXME: parametrize automaint call
if [ ! "$AUTOPORT_UPDATE_NO_AUTOMAINT" ]; then
automaint -s devel-autodist -d base -p devel-makedist
fi
for i in `seq 0 ${#AUTOPORT_ARCH[*]}`; do
echo "Running autodist-launcher ${i}"
systemd-run -u autodist-launcher-${i} /usr/bin/autodist-launcher ${i}
done

14
etc/cron.hourly/65-autoport Executable file
View File

@ -0,0 +1,14 @@
#!/bin/bash
#
# openmamba-autobuild-autoport daily cron script
# (c) 2008-2021 by Silvan Calarco <silvan.calarco@mambasoft.it>
#
#. /etc/sysconfig/openmamba-central
. /etc/sysconfig/autoport
[ "$AUTOPORT_ENABLE" = "1" -o "$AUTOPORT_ENABLE" = "true" ] || exit 0
for i in `seq 0 ${#AUTOPORT_ARCH[*]}`; do
echo "Running autoport-launcher ${i}"
systemd-run -u autoport-launcher-${i} /usr/bin/autoport-launcher ${i}
done

View File

@ -1,98 +0,0 @@
#!/bin/bash
#
# openmamba-autobuild-autoport daily cron script
# (c) 2008-2012 by Silvan Calarco <silvan.calarco@mambasoft.it>
#
#. /etc/sysconfig/openmamba-central
. /etc/sysconfig/autoport
[ "$AUTOPORT_ENABLE" = "1" -o "$AUTOPORT_ENABLE" = "true" ] || exit 0
ME=`basename $0`
[ "$$" == "`pidof -x $ME`" ] || {
[[ "`/usr/bin/tty`" != "not a tty" ]] && echo "Warning: $ME script already running; exiting."
exit 0
}
PIDFILE=/var/run/autodist/autodist.pid
HOUR=`date +%H`
[ "`uname -m`" = "x86_64" ] && HOST_IS_X86_64=1
function pid_check() {
[ -e $PIDFILE ] && PIDCHECK=`cat $PIDFILE`
[ "$PIDCHECK" -a -e /proc/$PIDCHECK ] && {
echo "Error: an autodist process is already running; exiting for safety."
exit 0
}
}
pid_check
for i in `seq 0 ${#AUTOPORT_ARCH[*]}`; do
[ "${AUTOPORT_ARCH[$i]}" ] || continue
if [ "$HOST_IS_X86_64" -a "${AUTOPORT_ARCH[$i]}" != "x86_64" ]; then
CMD_PREFIX=linux32
else
CMD_PREFIX=
fi
echo "ARCH=${AUTOPORT_ARCH[$i]} CHROOT=${AUTOPORT_CHROOT[$i]} \
CROSS=${AUTOPORT_CROSS[$i]} NATIVE=${AUTOPORT_NATIVE[$i]} \
REPOSITORIES=${AUTOPORT_REPOSITORIES[$i]} CMD_PREFIX=$CMD_PREFIX"
for r in ${AUTOPORT_REPOSITORIES[$i]}; do
echo "Autoport start at `date`" > /var/autodist/log/autoport-$r.log
echo "========================" >> /var/autodist/log/autoport-$r.log
done
if [ "${AUTOPORT_CHROOT[$i]}" ]; then
a=${AUTOPORT_CHROOT[$i]}
# sudo mount -o bind /proc /var/autoport/$a/proc
[[ "`/usr/bin/tty`" != "not a tty" ]] && echo "Updating packages in $a chroot environment"
echo "Updating packages in $a chroot environment..." >> /var/autodist/log/autoport-chroot-$a.log
LANG=C /usr/sbin/chroot /var/autoport/$a smart update --quiet > /dev/null
LANG=C /usr/sbin/chroot /var/autoport/$a smart upgrade -y >> /var/autodist/log/autoport-chroot-$a.log
for r in ${AUTOPORT_REPOSITORIES[$i]}; do
echo "Working on $r($a) in chroot mode..." >> /var/autodist/log/autoport-$r.log
[[ "`/usr/bin/tty`" != "not a tty" ]] && echo "Working on $r($a) in chroot mode" > $local_ftp/$r/autoport-$a.log
$CMD_PREFIX /usr/sbin/chroot /var/autoport/$a su -l sdk -c "autoport -b -r $r" >> $local_ftp/$r/autoport-$a.log
cat /var/autoport/$a/home/sdk/.autoport/${AUTOPORT_ARCH[$i]}/log >> $local_ftp/$r/autoport-$a.log
echo >> $local_ftp/$r/autoport-$a.log
done
fi
if [ "${AUTOPORT_NATIVE[$i]}" ]; then
a=${AUTOPORT_ARCH[$i]}
[[ "`/usr/bin/tty`" != "not a tty" ]] && echo "Updating packages in $a native environment"
echo "Updating packages in $a native environment..." >> /var/autodist/log/autoport-native-$a.log
LANG=C smart update > /dev/null
LANG=C smart upgrade -y >> /var/log/autoupgrade
for r in ${AUTOPORT_REPOSITORIES[$i]}; do
echo "Working on $r($a) in native mode" >> /var/autodist/log/autoport-$r.log
su -l autodist -c "autoport -b -r $r" >> /var/autodist/log/autoport-$r.log
cat /var/autodist/.autoport/$a/log >> /var/autodist/log/autoport-$r.log
echo >> /var/autodist/log/autoport-$r.log
done
fi
if [ "${AUTOPORT_CROSS[$i]}" ]; then
a=${AUTOPORT_CROSS[$i]}
for r in ${AUTOPORT_REPOSITORIES[$i]}; do
[[ "`/usr/bin/tty`" != "not a tty" ]] && echo "Working on $r($a) in cross-platform mode"
echo "Working on $r($a) in cross-platform mode" >> /var/autodist/log/autoport-$r.log
su -l autodist -c "autoport -b -x $a -r $r" > $local_ftp/$r/autoport-$a.log
cat /var/autodist/.autoport/$a/log >> $local_ftp/$r/autoport-$a.log
echo >> $local_ftp/$r/autoport-$a.log
done
fi
for r in ${AUTOPORT_REPOSITORIES[$i]}; do
[ -e /var/autodist/log/autoport-$r.log ] && \
cp /var/autodist/log/autoport-$r.log /var/autodist/log/autoport-$r-last.log
done
done

8
etc/logrotate.d/webbuild Normal file
View File

@ -0,0 +1,8 @@
/var/webbuild/access_log {
monthly
rotate 12
copytruncate
compress
notifempty
missingok
}

View File

@ -2,16 +2,43 @@
# autoport global configuration
#
local_ftp=/var/ftp/pub/openmamba/
#AUTOBUILDS_STATUS_URL="http://www.openmamba.org/distribution/autobuilds.html"
#AUTOPORT_ENABLE=1
# Disabled by default because they would require local repository
AUTOPORT_UPDATE_NO_AUTOMAINT=1
AUTOPORT_UPDATE_NO_DISTROMATIC=1
#AUTOPORT_CGI_HOST=(http://localhost/cgi-bin/autodist)
#AUTOPORT_WEBBUILD_HOST=http://localhost/webbuild.html
#ICECREAM_MONITOR_HOST=localhost
AUTOPORT_DEVEL_IMPORT_REPOSITORIES="devel-makedist base devel-autodist \
devel-kernel devel-misc devel-future devel-past"
AUTOPORT_DEVEL_RELEASE_REPOSITORIES="milestone2-makedist milestone2-kernel milestone2-kernel-next"
AUTOPORT_MILESTONE2_IMPORT_REPOSITORIES="milestone2-makedist milestone2-updates milestone2-kernel \
milestone2-kde4 milestone2-xorg milestone2-kernel-next milestone2"
#AUTOPORT_ARCH[0]=x86_64
#AUTOPORT_DISABLE[0]=
#AUTOPORT_CHROOT[0]=devel-x86_64
#AUTOPORT_CHROOT_USER[0]=sdk
#AUTOPORT_CHROOT_ICECREAM[0]=1
#AUTOPORT_CROSS[0]=
#AUTOPORT_NATIVE[0]=
#AUTOPORT_REPOSITORIES[0]="devel-makedist"
#AUTOPORT_BASE_REPOSITORY[0]="devel-makedist"
#AUTOPORT_IMPORT_REPOSITORIES[0]="$AUTOPORT_DEVEL_IMPORT_REPOSITORIES"
#AUTOPORT_ARCH[1]=i586
#AUTOPORT_DISABLE[1]=
#AUTOPORT_CHROOT[1]=milestone2-i586
#AUTOPORT_CHROOT_USER[1]=sdk
#AUTOPORT_CHROOT_ICECREAM[1]=1
#AUTOPORT_CROSS[1]=
#AUTOPORT_NATIVE[1]=
#AUTOPORT_BASE_REPOSITORY[0]="devel-autodist"
#AUTOPORT_REPOSITORIES[1]="milestone2-makedist"
#AUTOPORT_BASE_REPOSITORY[0]="milestone2-makedist"
#AUTOPORT_IMPORT_REPOSITORIES[0]="$AUTOPORT_DEVEL_IMPORT_REPOSITORIES"

79
repology-openmamba.py Executable file
View File

@ -0,0 +1,79 @@
#!/usr/bin/python3
#
# repology-openmamba.py - find upstream packages updates from repology.org
# Copyright (c) 2021-2024 by Silvan Calarco <silvan.calarco@mambasoft.it>
#
import json
import rpm
import sys
import time
import urllib.request
with open("/var/ftp/pub/openmamba/base/legacy") as f:
legacy_packages = f.read().splitlines()
with open("/var/ftp/pub/openmamba/base/updates-conf.json") as f:
data = json.loads(f.read())
ignored_packages = data["repology"]["ignore"]
from_package = ""
last_from_package = "NONE"
results = []
while True:
if from_package == last_from_package:
break
requrl = "https://repology.org/api/v1/projects/"
if from_package != "":
requrl += from_package +"/"
requrl += "?inrepo=openmamba&outdated=1"
sys.stderr.write("Requesting: " + requrl + "\n")
req = urllib.request.Request(
requrl,
data=None,
headers={'User-Agent': 'autodist/1.5.3 (Linux; openmamba; reports@openmamba.org)'}
)
url = urllib.request.urlopen(req)
#print(requrl)
data = json.loads(url.read().decode())
if from_package != "" and len(data.keys()) <= 1:
break
for k in data.keys():
if k == from_package:
continue
package = k
openmamba_srcname = None
openmamba_version = None
openmamba_altnames = []
newest_version = None
newest_repos = []
for p in data[k]:
if p["repo"] == "openmamba":
if not p["srcname"] in ignored_packages and \
not p["srcname"] in legacy_packages:
if openmamba_srcname is None:
openmamba_version = p["version"]
openmamba_srcname = p["srcname"]
else:
openmamba_altnames.append(p["srcname"])
elif p["status"] == "newest":
# kaos_build provides unreleased kde package versions
if p["repo"] != "kaos_build":
newest_version = p["version"]
newest_repos.append(p["repo"])
newest_repos = list(dict.fromkeys(newest_repos))
if openmamba_srcname and newest_version is not None and len(newest_repos) > 0:
results.append(openmamba_srcname + " " + newest_version)
for altname in openmamba_altnames:
results.append(altname + " " + newest_version)
last_from_package = from_package
from_package = package
time.sleep(1)
results_sorted = sorted(set(results), key=str.casefold)
#results_unique = set(results_sorted)
for result in results_sorted:
print(result)

205
telegram/openmamba_bot.py Executable file
View File

@ -0,0 +1,205 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# openmamba bot for Telegram
#
# Copyright (C) 2016-2023 by Silvan Calarco <silvan.calarco@mambasoft.it>
#
# GPL v3 license
from telegram import (ParseMode, Update)
from telegram.ext import (Updater, CommandHandler, MessageHandler, Filters, RegexHandler,
ConversationHandler, Job, CallbackContext)
import logging
import subprocess
import sqlite3
import os
# Enable logging
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO)
logger = logging.getLogger(__name__)
timers = dict()
social_log_last_ids = dict()
reps = [ 'base', 'devel-makedist', 'devel-autodist', 'devel-kernel', 'devel-misc', 'devel-future', 'devel-past' ]
def start(update: Update, context: CallbackContext):
user = update.message.from_user
logger.info("User %s started the conversation." % user.first_name)
update.message.reply_text(
'Hi! This is the openmamba GNU/Linux Bot.\n'
'Send any text to search for packages.\n'
'Send /details [name] to see details of specified source package.\n'
'Send /set [seconds] to enable notifications.\n'
'Send /unset to disable notifications.\n\n')
return
def help(update: Update, context: CallbackContext):
update.message.reply_text(
'Send any text to search for packages.\n'
'Send /details [name] to see details of specified source package.\n'
'Send /set [seconds] to enable notifications.\n'
'Send /unset to disable notifications.\n\n')
return
def query(update: Update, context: CallbackContext):
user = update.message.from_user
logger.info("Query of %s: %s" % (user.first_name, update.message.text))
response = ""
for rep in reps:
conn = sqlite3.connect('/var/webbuild/db/%s-sources.db' % rep, check_same_thread=False)
cursor = conn.cursor()
print(rep)
cursor.execute(
'SELECT id,name,version,release,summary,url FROM sources where name like "%%%s%%" or summary like "%%%s%%" '
'ORDER BY name="%s" DESC, name like "%s%%" DESC, name like "%%%s%%" DESC limit 10'
% (update.message.text, update.message.text, update.message.text, update.message.text, update.message.text))
for row in cursor:
response += "<b>%s</b> %s-%s (%s)\n%s\n%s\n\n" % (row[1], row[2], row[3], rep, row[4], row[5])
if response != "":
update.message.reply_text(response, parse_mode=ParseMode.HTML)
else:
update.message.reply_text('No results found.')
return
def details(update: Update, context: CallbackContext):
user = update.message.from_user
logger.info("Details of %s: %s" % (user.first_name, update.message.text))
response = ""
for rep in reps:
conn = sqlite3.connect('/var/webbuild/db/%s-sources.db' % rep, check_same_thread=False)
cursor = conn.cursor()
cursor.execute(
'SELECT id,name,version,release,summary,url,description FROM sources where name="%s"' % (context.args[0]))
for row in cursor:
response += "<b>%s</b> %s-%s (devel)\n%s\n%s\n\n<i>%s</i>\n\n" % (row[1], row[2], row[3], row[4], row[5], row[6])
for arch in [ 'x86_64', 'aarch64', 'i586', 'arm' ]:
conn1 = sqlite3.connect('/var/webbuild/db/' + rep + '-' + arch + '.db', check_same_thread=False)
cursor1 = conn1.cursor()
cursor1.execute('SELECT id,name FROM packages where id_source=%s' % (row[0]))
for row1 in cursor1:
response += "<b>%s</b>(%s) " % (row1[1], arch)
response += "\n\n\n"
if response != "":
update.message.reply_text(response[0:4096], parse_mode=ParseMode.HTML)
else:
update.message.reply_text('No results found.')
return
def alarm(context):
social_log_conn = sqlite3.connect('/var/webbuild/webbuild.db')
social_log_cursor = social_log_conn.cursor()
social_log_cursor.execute('SELECT id,user,text,datetime(time,\'localtime\'),type FROM social_log where id>%s' % social_log_last_ids[context.job])
response = ""
for row in social_log_cursor:
if row[4] == "job":
response += "Job run by <i>%s</i> %s (%s)\n" % (row[1], row[2], row[3])
else:
response += "<i>%s</i> %s (%s)\n" % (row[1], row[2], row[3])
if response != "":
bot.sendMessage(context.job, response, parse_mode=ParseMode.HTML)
social_log_last_ids[context.job] = row[0]
def set(update: Update, context: CallbackContext):
chat_id = update.message.chat_id
try:
due = int(context.args[0])
if due < 0:
update.message.reply_text('Sorry we can not go back to future!')
return
#job = Job(alarm, context, next_t=due, repeat=True, context=chat_id)
#timers[chat_id] = job
context.job_queue.run_repeating(alarm, due)
#context.jobqueue.put(job)
social_log_conn = sqlite3.connect('/var/webbuild/webbuild.db')
social_log_cursor = social_log_conn.cursor()
social_log_cursor.execute('''SELECT MAX(id) FROM social_log''')
social_log_last_ids[chat_id] = social_log_cursor.fetchone()[0] - 5
update.message.reply_text('Notifications enabled!')
except (IndexError, ValueError):
update.message.reply_text('Usage: /set <seconds>')
def unset(update: Update, context: CallbackContext):
chat_id = update.message.chat_id
if chat_id not in timers:
update.message.reply_text('Notification were not enabled')
return
job = timers[chat_id]
job.schedule_removal()
del timers[chat_id]
update.message.reply_text('Notifications disabled')
def cancel(update: Update, context: CallbackContext):
user = update.message.from_user
logger.info("User %s canceled the conversation." % user.first_name)
update.message.reply_text('Bye!')
return ConversationHandler.END
def error(update: Update, context: CallbackContext):
logger.warning('Update "%s" caused error "%s"' % (update, context.error))
def main():
# Load bot token from external configuration file
bot_token = ""
with open("/etc/autodist/secrets") as myfile:
for line in myfile:
name, var = line.rstrip().split("=")
if name == "TELEGRAM_BOT_TOKEN":
bot_token = var
# Create the EventHandler and pass it your bot's token.
updater = Updater(bot_token)
# Get the dispatcher to register handlers
dp = updater.dispatcher
dp.add_handler(CommandHandler('start', start))
dp.add_handler(CommandHandler('help', help))
dp.add_handler(CommandHandler('details', details, pass_args=True))
dp.add_handler(CommandHandler('set', set, pass_args=True, pass_job_queue=True))
dp.add_handler(CommandHandler('unset', unset))
dp.add_handler(MessageHandler(Filters.text, query))
# log all errors
dp.add_error_handler(error)
# Start the Bot
updater.start_polling()
# Run the bot until the you presses Ctrl-C or the process receives SIGINT,
# SIGTERM or SIGABRT. This should be used most of the time, since
# start_polling() is non-blocking and will stop the bot gracefully.
updater.idle()
if __name__ == '__main__':
main()

View File

@ -0,0 +1,10 @@
[Unit]
Description=openmamba bot for Telegram
After=syslog.target
[Service]
Type=simple
ExecStart=/var/autodist/env/bin/python3 /usr/share/autodist/openmamba_bot.py
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1 @@
python-telegram-bot~=13.14

View File

@ -0,0 +1,60 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html><head>
<meta content="text/html; charset=utf-8" http-equiv="content-type">
<link rel="shortcut icon" type="image/x-icon" href="/images/webbuild.ico" />
<!-- styles needed by jScrollPane -->
<link type="text/css" href="/scripts/jquery.jscrollpane.css" rel="stylesheet" media="all" >
<!-- latest jQuery direct from google's CDN -->
<script type="text/javascript" src="/scripts/jquery.js"></script>
<!-- the mousewheel plugin - optional to provide mousewheel support -->
<script type="text/javascript" src="/scripts/jquery.mousewheel.js"></script>
<!-- the jScrollPane script -->
<script type="text/javascript" src="/scripts/jquery.jscrollpane.min.js"></script>
<link rel="stylesheet" type="text/css" href="/styles/webbuild.css">
<script type="text/javascript" src="/scripts/socialbox.js"></script>
<script type="text/javascript">
<!--
var lastupdate = 0;
var reloadtime = 0;
function ajax_getvalues() {
var url = window.location.protocol+"//"+window.location.hostname+"/cgi-bin/autodist?FORMAT=xml&"+window.location.href.replace(/.*\?/,"");
var xmlhttp;
if (window.XMLHttpRequest)
xmlhttp = new XMLHttpRequest();
else if (window.ActiveXObject)
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
else
return;
document.getElementById("noajax_msg").innerHTML = "";
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState != 4)
return;
var xmldoc = xmlhttp.responseXML.documentElement;
document.getElementById("output").innerHTML = xmldoc.getElementsByTagName("output")[0].childNodes[0].nodeValue;
reloadtime = xmldoc.getElementsByTagName("reloadtime")[0].childNodes[0].nodeValue;
lastupdate = (+new Date());
setTimeout("ajax_getvalues()", reloadtime);
}
xmlhttp.open("GET", url, true);
xmlhttp.send(null);
}
//-->
</script>
</head><body>
<div id=container style="margin-left:auto;margin-right:auto;width:95%;">
<div id="noajax_msg"><p>Il supporto per AJAX non è abilitato nel tuo browser. L'aggiornamento live non sarà disponibile, premi Ricarica per aggiornare la pagina.</p></div>
<span id="output">Caricamento in corso, attendere...</span>
<script>
ajax_getvalues("");
$("#output").mousemove(function(event) {
lastupdatetime = (+new Date()) - lastupdate; // milliseconds since last update
// var msg = "called " + lastupdatetime + "ms ago";
if (lastupdatetime > reloadtime) { lastupdate = lastupdatetime; ajax_getvalues(); }
});
</script>
</div>
</body></html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 894 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

BIN
webbuild/html/images/ok.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 927 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,7 @@
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8

View File

@ -0,0 +1,8 @@
*.txt text eol=lf
*.js text eol=lf
*.html text eol=lf
*.md text eol=lf
*.json text eol=lf
*.yml text eol=lf
*.css text eol=lf
*.svg text eol=lf

View File

@ -0,0 +1,5 @@
<!--
Do not use this bug tracker for questions. We have a forum (https://discuss.codemirror.net) for those.
In order to get us to look at something, you need to make it easy for us to understand what you are doing and what went wrong. When possible, a code example that demonstrates the problem helps a lot. If there's any chance at all that a problem is related to the browser, include information about which browser(s) you tested with.
-->

View File

@ -0,0 +1,5 @@
<!--
NOTE: We are not accepting pull requests for new modes or addons. Please put such code in a separate repository, and release them as stand-alone npm packages. See for example the [Elixir mode](https://github.com/ianwalter/codemirror-mode-elixir).
Also pull requests that rewrite big chunks of code or adjust code style to your own taste are generally not welcome. Make your changes in focused steps that fix or improve a specific thing.
-->

View File

@ -0,0 +1,14 @@
/node_modules
/demo
/doc
/test
/test*.html
/index.html
/mode/*/*test.js
/mode/*/*.html
/mode/index.html
.*
/bin/authors.sh
/bin/lint
/bin/release
/bin/upload-release.js

View File

@ -0,0 +1,5 @@
language: node_js
node_js:
- stable
sudo: false
cache: npm

View File

@ -0,0 +1,893 @@
List of CodeMirror contributors. Updated before every release.
4oo4
4r2r
Aaron Brooks
Abdelouahab
Abdussalam Abdurrahman
Abe Fettig
Abhishek Gahlot
Adam Ahmed
Adam King
Adam Particka
adanlobato
Adán Lobato
Aditya Toshniwal
Adrian Aichner
Adrian Heine
Adrian Kunz
Adrien Bertrand
aeroson
Ahmad Amireh
Ahmad M. Zawawi
ahoward
Ajin Abraham
Akeksandr Motsjonov
Alasdair Smith
AlbertHilb
Alberto González Palomo
Alberto Pose
Albert Xing
Alexander Pavlov
Alexander Schepanovski
Alexander Shvets
Alexander Solovyov
Alexandre Bique
Alex Churchill
alexey-k
Alex Piggott
Aliaksei Chapyzhenka
Allen Sarkisyan
Ami Fischman
Amin Shali
Amin Ullah Khan
amshali@google.com
Amsul
amuntean
Amy
Ananya Sen
anaran
AndersMad
Anders Nawroth
Anderson Mesquita
Anders Wåglund
Andrea G
Andreas Reischuck
Andres Taylor
Andre von Houck
Andrew Cheng
Andrew Dassonville
Andrey Fedorov
Andrey Klyuchnikov
Andrey Lushnikov
Andrey Shchekin
Andy Joslin
Andy Kimball
Andy Li
Angelo
angelozerr
angelo.zerr@gmail.com
Ankit
Ankit Ahuja
Ansel Santosa
Anthony Dugois
anthonygego
Anthony Gégo
Anthony Grimes
Anton Kovalyov
antosarho
Apollo Zhu
AQNOUCH Mohammed
Aram Shatakhtsyan
areos
Arnab Bose
Arnoud Buzing
Arsène von Wyss
Arthur Müller
Arun Narasani
as3boyan
asolove
atelierbram
AtomicPages LLC
Atul Bhouraskar
Aurelian Oancea
Axel Lewenhaupt
Baptiste Augrain
Barret Rennie
Bartosz Dziewoński
Basarat Ali Syed
Bastian Müller
belhaj
Bem Jones-Bey
benbro
Benedikt Meurer
benhormann
Ben Hormann
Beni Cherniavsky-Paskin
Benjamin DeCoste
Benjamin Young
Ben Keen
Ben Miller
Ben Mosher
Bernhard Sirlinger
Bert Chang
Bharad
BigBlueHat
Billy Moon
Bin Ni
binny
Bjorn Hansen
B Krishna Chaitanya
Blaine G
blukat29
Bo
boomyjee
Bo Peng
borawjm
Boris K
Brad Metcalf
Brandon Frohs
Brandon Wamboldt
Bret Little
Brett Zamir
Brian Grinstead
BrianHung
Brian Sletten
brrd
Bruce Mitchener
Bruno Logerfo
Bryan Gin-ge Chen
Bryan Massoth
Caitlin Potter
Calin Barbat
callodacity
Camilo Roca
Casey Klebba
cBiscuit87
César González Íñiguez
Chad Jolly
Chandra Sekhar Pydi
Charles Skelton
Cheah Chu Yeow
Chhekur
Chris Colborne
Chris Coyier
Chris Ford
Chris Granger
Chris Houseknecht
Chris Lohfink
Chris Morgan
Chris Reeves
Chris Smith
Christian Gruen
Christian Oyarzun
Christian Petrov
christopherblaser
Christopher Brown
Christopher Kramer
Christopher Mitchell
Christopher Pfohl
Christopher Wallis
Chunliang Lyu
ciaranj
clone-it
clso
CodeAnimal
CodeBitt
coderaiser
Cole R Lawrence
ComFreek
Cristian Prieto
Curran Kelleher
Curtis Gagliardi
d8888
dagsta
daines
Dale Jung
Dan Bentley
Dan Heberden
Daniel, Dao Quang Minh
Daniele Di Sarli
Daniel Faust
Daniel Hanggi
Daniel Huigens
Daniel Kesler
Daniel KJ
Daniel Neel
Daniel Parnell
Daniel Thwaites
Danila Malyutin
Danny Yoo
darealshinji
Darius Roberts
databricks-david-lewis
Dave Brondsema
Dave MacLachlan
Dave Myers
David Barnett
David H. Bronke
David Mignot
David Pathakjee
David Rodrigues
David Santana
David Vázquez
David Whittington
deebugger
Deep Thought
Denis Ovsienko
Devin Abbott
Devon Carew
Dick Choi
Diego Fernandez
dignifiedquire
Dimage Sapelkin
Dinindu D. Wanniarachchi
dmaclach
Dmitry Kiselyov
domagoj412
Dominator008
Domizio Demichelis
Doug Blank
Doug Wikle
Drew Bratcher
Drew Hintz
Drew Khoury
Drini Cami
Dror BG
Duncan Lilley
duralog
dwelle
Ealton
eborden
edoroshenko
edsharp
ekhaled
Elisée
elpnt
Emmanuel Schanzer
Enam Mijbah Noor
Eric Allam
Eric Bogard
Erik Demaine
Erik Welander
eustas
Evan Minsk
Fabien Dubosson
Fabien O'Carroll
Fabio Zendhi Nagao
Faiza Alsaied
Fauntleroy
fbuchinger
feizhang365
Felipe Lalanne
Felix Raab
ficristo
Filip Noetzel
Filip Stollár
Filype Pereira
finalfantasia
flack
Florian Felten
Fons van der Plas
Forbes Lindesay
ForbesLindesay
Ford_Lawnmower
Forrest Oliphant
Franco Catena
Frank Seifferth
Frank Wiegand
fraxx001
Fredrik Borg
FUJI Goro (gfx)
Gabriel Gheorghian
Gabriel Horner
Gabriel Nahmias
galambalazs
Gary Sheng
Gautam Mehta
Gavin Douglas
gekkoe
Geordie Hall
George Stephanis
geowarin
Gerard Braad
Gergely Hegykozi
Germain Chazot
Giovanni Calò
Glebov Boris
Glenn Jorde
Glenn Ruehle
goldsmcb
Golevka
Google LLC
Gordon Smith
Grant Skinner
greengiant
Gregory Koberger
Grzegorz Mazur
Guang Li
Guan Gui
Guillaume Massé
Guillaume Massé
guraga
Gustavo Rodrigues
Hakan Tunc
Hanno Fellmann
Hans Engel
Hanzhao Deng
Haoran Yu
Harald Schilly
Hardest
Harshvardhan Gupta
Hasan Delibaş
Hasan Karahan
Heanes
Hector Oswaldo Caballero
Hein Htat
Hélio
Hendrik Wallbaum
Henrik Haugbølle
Herculano Campos
hidaiy
Hiroyuki Makino
hitsthings
Hocdoc
Howard
Howard Jing
Hugues Malphettes
Ian Beck
Ian Davies
Ian Dickinson
ianhi
Ian Rose
Ian Wehrman
Ian Wetherbee
Ice White
ICHIKAWA, Yuji
idleberg
Igor Petruk
ilvalle
Ilya Kharlamov
Ilya Zverev
Ingo Richter
Intervue
Irakli Gozalishvili
Ivan Kurnosov
Ivoah
Jack Douglas
Jacob Lee
Jaimin
Jake Peyser
Jakob Miland
Jakub Vrana
Jakub Vrána
James Campos
James Cockshull
James Howard
James Thorne
Jamie Hill
Jamie Morris
Janice Leung
Jan Jongboom
jankeromnes
Jan Keromnes
Jan Odvarko
Jan Schär
Jan T. Sott
Jared Dean
Jared Forsyth
Jared Jacobs
Jason
Jason Barnabe
Jason Grout
Jason Heeris
Jason Johnston
Jason San Jose
Jason Siefken
Jayaprabhakar
Jay Contonio
Jaydeep Solanki
Jean Boussier
Jeff Blaisdell
Jeff Hanke
Jeff Jenkins
jeffkenton
Jeff Pickhardt
jem (graphite)
Jeremy Parmenter
Jim
Jim Avery
jkaplon
JobJob
jochenberger
Jochen Berger
Joel Einbinder
joelpinheiro
joewalsh
Johan Ask
Johannes
John Chen
John Connor
John-David Dalton
John Engler
John Lees-Miller
John Ryan
John Snelson
John Van Der Loo
Jon Ander Peñalba
Jonas Döbertin
Jonas Helfer
Jonathan Dierksen
Jonathan Hart
Jonathan Malmaud
Jon Gacnik
jongalloway
Jon Malmaud
Jon Sangster
Joo
Joost-Wim Boekesteijn
Joseph Pecoraro
Josh Barnes
Josh Cohen
Josh Soref
Joshua Newman
Josh Watzman
jots
Joy Zhong
jsoojeon
ju1ius
Juan Benavides Romero
Jucovschi Constantin
Juho Vuori
Julien CROUZET
Julien Rebetez
Justin Andresen
Justin Hileman
jwallers@gmail.com
kaniga
karevn
Karol
Kaushik Kulkarni
Kayur Patel
Kazuhito Hokamura
kcwiakala
Kees de Kooter
Kenan Christian Dimas
Ken Newman
ken restivo
Ken Rockot
Kevin Earls
Kevin Kwok
Kevin Muret
Kevin Sawicki
Kevin Ushey
Kier Darby
Klaus Silveira
Koh Zi Han, Cliff
komakino
Konstantin Lopuhin
koops
Kris Ciccarello
ks-ifware
kubelsmieci
kvncp
KwanEsq
Kyle Kelley
KyleMcNutt
LaKing
Lanfei
Lanny
laobubu
Laszlo Vidacs
leaf
leaf corcoran
Lemmon
Leo Baschy
Leonid Khachaturov
Leon Sorokin
Leonya Khachaturov
Liam Newman
Libo Cannici
Lior Goldberg
Lior Shub
LloydMilligan
LM
lochel
Lonnie Abelbeck
Lorenzo Simionato
Lorenzo Stoakes
Louis Mauchet
Luca Fabbri
Lucas Buchala
Luciano Longo
Luciano Santana
Lu Fangjian
Luke Browning
Luke Granger-Brown
Luke Stagner
lynschinzer
M1cha
Madhura Jayaratne
Maksim Lin
Maksym Taran
Malay Majithia
Manideep
Manuel Rego Casasnovas
Marat Dreizin
Marcel Gerber
Marcelo Camargo
Marco Aurélio
Marco Munizaga
Marcus Bointon
Marek Rudnicki
Marijn Haverbeke
Mário Gonçalves
Mario Pietsch
Mark Anderson
Mark Dalgleish
Mark Hamstra
Mark Lentczner
Marko Bonaci
Mark Peace
Markus Bordihn
Markus Olsson
Martin Balek
Martín Gaitán
Martin Hasoň
Martin Hunt
Martin Laine
Martin Zagora
Mason Malone
Mateusz Paprocki
Mathias Bynens
mats cronqvist
Matt Gaide
Matthew Bauer
Matthew Beale
Matthew Casperson
matthewhayes
Matthew Rathbone
Matthew Suozzo
Matthias Bussonnier
Matthias BUSSONNIER
Mattia Astorino
Matt MacPherson
Matt McDonald
Matt Pass
Matt Sacks
mauricio
Maximilian Hils
Maxim Kraev
Max Kirsch
Max Schaefer
Max Wu
Max Xiantu
mbarkhau
McBrainy
mce2
Mélanie Chauvel
melpon
meshuamam
Metatheos
Micah Dubinko
Michael
Michael Goderbauer
Michael Grey
Michael Kaminsky
Michael Lehenbauer
Michael Wadman
Michael Walker
Michael Zhou
Michal Čihař
Michal Dorner
Michal Kapiczynski
Mighty Guava
Miguel Castillo
mihailik
Mika Andrianarijaona
Mike
Mike Bostock
Mike Brevoort
Mike Diaz
Mike Ivanov
Mike Kadin
Mike Kobit
Milan Szekely
MinRK
Miraculix87
misfo
mkaminsky11
mloginov
Moritz Schubotz (physikerwelt)
Moritz Schwörer
Moshe Wajnberg
mps
ms
mtaran-google
Mu-An ✌️ Chiou
Mu-An Chiou
mzabuawala
Narciso Jaramillo
Nathan Williams
ndr
Neil Anderson
neon-dev
nerbert
NetworkNode
nextrevision
ngn
nguillaumin
Ng Zhi An
Nicholas Bollweg
Nicholas Bollweg (Nick)
NickKolok
Nick Kreeger
Nick Small
Nicolas Chevobbe
Nicolas Kick
Nicolò Ribaudo
Niels van Groningen
nightwing
Nikita Beloglazov
Nikita Vasilyev
Nikolaj Kappler
Nikolay Kostov
nilp0inter
Nils Knappmeier
Nisarg Jhaveri
nlwillia
noragrossman
Norman Rzepka
Nouzbe
Oleksandr Yakovenko
Olivia Ytterbrink
Opender Singh
opl-
Oreoluwa Onatemowo
orionlee
oscar.lofwenhamn
Oskar Segersvärd
ossdev
overdodactyl
pablo
pabloferz
Pablo Zubieta
paddya
Page
paladox
Panupong Pasupat
paris
Paris
Paris Kasidiaris
Patil Arpith
Patrick Kettner
Patrick Stoica
Patrick Strawderman
Paul Garvin
Paul Ivanov
Paul Masson
Paul Schmidt
Pavel
Pavel Feldman
Pavel Petržela
Pavel Strashkin
Paweł Bartkiewicz
peteguhl
peter
Peter Flynn
peterkroon
Peter Kroon
Peter László
Philipp A
Philipp Markovics
Philip Stadermann
Pi Delport
Pierre Gerold
Pieter Ouwerkerk
Pontus Melke
prasanthj
Prasanth J
Prayag Verma
prendota
Prendota
Qiang Li
Radek Piórkowski
Rahul
Rahul Anand
ramwin1
Randall Mason
Randy Burden
Randy Edmunds
Randy Luecke
Raphael Amorim
Rasmus Erik Voel Jensen
Rasmus Schultz
raymondf
Raymond Hill
ray ratchup
Ray Ratchup
Remi Nyborg
Renaud Durlin
Reynold Xin
Richard Denton
Richard van der Meer
Richard Z.H. Wang
Rishi Goomar
Robert Brignull
Robert Crossfield
Robert Martin
Roberto Abdelkader Martínez Pérez
robertop23
Roberto Vidal
Robert Plummer
Roman Janusz
Rrandom
Rrrandom
Ruslan Osmanov
rvalavicius
Ryan Pangrle
Ryan Petrello
Ryan Prior
ryu-sato
sabaca
Sam Lee
Sam Rawlins
Samuel Ainsworth
Sam Wilson
sandeepshetty
Sander AKA Redsandro
Sander Verweij
santec
Sarah McAlear and Wenlin Zhang
Sascha Peilicke
Sasha Varlamov
satamas
satchmorun
sathyamoorthi
Saul Costa
S. Chris Colbert
SCLINIC\jdecker
Scott Aikin
Scott Feeney
Scott Goodhew
Seb35
Sebastian Wilzbach
Sebastian Zaha
Seren D
Sergey Goder
Sergey Tselovalnikov
Se-Won Kim
Shane Liesegang
shaund
shaun gilchrist
Shawn A
Shea Bunge
sheopory
Shil S
Shiv Deepak
Shmuel Englard
Shubham Jain
Siamak Mokhtari
Siddhartha Gunti
silverwind
Simon Edwards
sinkuu
snasa
soliton4
sonson
Sorab Bisht
spastorelli
srajanpaliwal
Stanislav Oaserele
stan-z
Stas Kobzar
Stefan Borsje
Steffen Beyer
Steffen Bruchmann
Steffen Kowalski
Stephane Moore
Stephen Lavelle
Steve Champagne
Steve Hoover
Steve O'Hara
stockiNail
stoskov
Stryder Crown
Stu Kennedy
Sungho Kim
sverweij
Taha Jahangir
takamori
Tako Schotanus
Takuji Shimokawa
Takuya Matsuyama
Tarmil
T. Brandon Ashley
TDaglis
Teja
tel
Tentone
tfjgeorge
Thaddee Tyl
thanasis
TheHowl
themrmax
think
Thomas Brouard
Thomas Dvornik
Thomas Kluyver
thomasmaclean
Thomas Schmid
Tim Alby
Tim Baumann
Tim Gates
Timothy Farrell
Timothy Gu
Timothy Hatcher
Tim van der Lippe
Tobias Bertelsen
TobiasBg
Todd Berman
Todd Kennedy
tokafew420
Tomas-A
Tomas Varaneckas
Tom Erik Støwer
Tom Klancer
Tom MacWright
Tom McLaughlin
Tony Jian
tophf
Torgeir Thoresen
totalamd
Travis Heppe
Triangle717
Tristan Tarrant
TSUYUSATO Kitsune
Tugrul Elmas
twifkak
Tyler Long
Tyler Makaro
Vadim Dyachenko
Vadzim Ramanenka
Vaibhav Sagar
vamshi.revu
VapidWorx
Vestimir Markov
vf
Victor Bocharsky
Vincent Woo
Volker Mische
vtripolitakis
wdouglashall
Weiyan Shao
wenli
Wes Cossick
Wesley Wiser
Weston Ruter
Will Binns-Smith
Will Dean
William Desportes
William Jamieson
William Stein
Willy
Wojtek Ptak
wonderboyjon
Wu Cheng-Han
Xavier Mendez
Yang Guo
Yassin N. Hassan
YNH Webdev
yoongu
Yunchi Luo
Yuvi Panda
Yvonnick Esnault
Zac Anger
Zachary Dremann
ZeeshanNoor
Zeno Rocha
Zhang Hao
Ziv
zoobestik
zziuni
魏鹏刚

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,92 @@
# How to contribute
- [Getting help](#getting-help)
- [Submitting bug reports](#submitting-bug-reports)
- [Contributing code](#contributing-code)
## Getting help
Community discussion, questions, and informal bug reporting is done on the
[discuss.CodeMirror forum](http://discuss.codemirror.net).
## Submitting bug reports
The preferred way to report bugs is to use the
[GitHub issue tracker](http://github.com/codemirror/CodeMirror/issues). Before
reporting a bug, read these pointers.
**Note:** The issue tracker is for *bugs*, not requests for help. Questions
should be asked on the
[discuss.CodeMirror forum](http://discuss.codemirror.net) instead.
### Reporting bugs effectively
- CodeMirror is maintained by volunteers. They don't owe you anything, so be
polite. Reports with an indignant or belligerent tone tend to be moved to the
bottom of the pile.
- Include information about **the browser in which the problem occurred**. Even
if you tested several browsers, and the problem occurred in all of them,
mention this fact in the bug report. Also include browser version numbers and
the operating system that you're on.
- Mention which release of CodeMirror you're using. Preferably, try also with
the current development snapshot, to ensure the problem has not already been
fixed.
- Mention very precisely what went wrong. "X is broken" is not a good bug
report. What did you expect to happen? What happened instead? Describe the
exact steps a maintainer has to take to make the problem occur. We can not
fix something that we can not observe.
- If the problem can not be reproduced in any of the demos included in the
CodeMirror distribution, please provide an HTML document that demonstrates
the problem. The best way to do this is to go to
[jsbin.com](http://jsbin.com/ihunin/edit), enter it there, press save, and
include the resulting link in your bug report.
## Contributing code
Note that we are not accepting any new addons or modes into the main
distribution. If you've written such a module, please distribute it as
a separate NPM package.
- Make sure you have a [GitHub Account](https://github.com/signup/free)
- Fork [CodeMirror](https://github.com/codemirror/CodeMirror/)
([how to fork a repo](https://help.github.com/articles/fork-a-repo))
- Make your changes
- If your changes are easy to test or likely to regress, add tests.
Tests for the core go into `test/test.js`, some modes have their own
test suite under `mode/XXX/test.js`. Feel free to add new test
suites to modes that don't have one yet (be sure to link the new
tests into `test/index.html`).
- Follow the general code style of the rest of the project (see
below). Run `bin/lint` to verify that the linter is happy.
- Make sure all tests pass. Visit `test/index.html` in your browser to
run them.
- Submit a pull request
([how to create a pull request](https://help.github.com/articles/fork-a-repo)).
Don't put more than one feature/fix in a single pull request.
By contributing code to CodeMirror you
- agree to license the contributed code under CodeMirror's [MIT
license](https://codemirror.net/LICENSE).
- confirm that you have the right to contribute and license the code
in question. (Either you hold all rights on the code, or the rights
holder has explicitly granted the right to use it like this,
through a compatible open source license or through a direct
agreement with you.)
### Coding standards
- 2 spaces per indentation level, no tabs.
- Note that the linter (`bin/lint`) which is run after each commit
complains about unused variables and functions. Prefix their names
with an underscore to muffle it.
- CodeMirror does *not* follow JSHint or JSLint prescribed style.
Patches that try to 'fix' code to pass one of these linters will be
unceremoniously discarded.

View File

@ -0,0 +1,21 @@
MIT License
Copyright (C) 2017 by Marijn Haverbeke <marijnh@gmail.com> and others
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,48 @@
# CodeMirror
[![Build Status](https://travis-ci.org/codemirror/CodeMirror.svg)](https://travis-ci.org/codemirror/CodeMirror)
[![NPM version](https://img.shields.io/npm/v/codemirror.svg)](https://www.npmjs.org/package/codemirror)
[![Join the chat at https://gitter.im/codemirror/CodeMirror](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/codemirror/CodeMirror)
CodeMirror is a versatile text editor implemented in JavaScript for
the browser. It is specialized for editing code, and comes with over
100 language modes and various addons that implement more advanced
editing functionality. Every language comes with fully-featured code
and syntax highlighting to help with reading and editing complex code.
A rich programming API and a CSS theming system are available for
customizing CodeMirror to fit your application, and extending it with
new functionality.
You can find more information (and the
[manual](https://codemirror.net/doc/manual.html)) on the [project
page](https://codemirror.net). For questions and discussion, use the
[discussion forum](https://discuss.codemirror.net/).
See
[CONTRIBUTING.md](https://github.com/codemirror/CodeMirror/blob/master/CONTRIBUTING.md)
for contributing guidelines.
The CodeMirror community aims to be welcoming to everybody. We use the
[Contributor Covenant
(1.1)](http://contributor-covenant.org/version/1/1/0/) as our code of
conduct.
### Installation
Either get the [zip file](https://codemirror.net/codemirror.zip) with
the latest version, or make sure you have [Node](https://nodejs.org/)
installed and run:
npm install codemirror
**NOTE**: This is the source repository for the library, and not the
distribution channel. Cloning it is not the recommended way to install
the library, and will in fact not work unless you also run the build
step.
### Quickstart
To build the project, make sure you have Node.js installed (at least version 6)
and then `npm install`. To run, just open `index.html` in your
browser (you don't need to run a webserver). Run the tests with `npm test`.

View File

@ -0,0 +1,211 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var noOptions = {};
var nonWS = /[^\s\u00a0]/;
var Pos = CodeMirror.Pos, cmp = CodeMirror.cmpPos;
function firstNonWS(str) {
var found = str.search(nonWS);
return found == -1 ? 0 : found;
}
CodeMirror.commands.toggleComment = function(cm) {
cm.toggleComment();
};
CodeMirror.defineExtension("toggleComment", function(options) {
if (!options) options = noOptions;
var cm = this;
var minLine = Infinity, ranges = this.listSelections(), mode = null;
for (var i = ranges.length - 1; i >= 0; i--) {
var from = ranges[i].from(), to = ranges[i].to();
if (from.line >= minLine) continue;
if (to.line >= minLine) to = Pos(minLine, 0);
minLine = from.line;
if (mode == null) {
if (cm.uncomment(from, to, options)) mode = "un";
else { cm.lineComment(from, to, options); mode = "line"; }
} else if (mode == "un") {
cm.uncomment(from, to, options);
} else {
cm.lineComment(from, to, options);
}
}
});
// Rough heuristic to try and detect lines that are part of multi-line string
function probablyInsideString(cm, pos, line) {
return /\bstring\b/.test(cm.getTokenTypeAt(Pos(pos.line, 0))) && !/^[\'\"\`]/.test(line)
}
function getMode(cm, pos) {
var mode = cm.getMode()
return mode.useInnerComments === false || !mode.innerMode ? mode : cm.getModeAt(pos)
}
CodeMirror.defineExtension("lineComment", function(from, to, options) {
if (!options) options = noOptions;
var self = this, mode = getMode(self, from);
var firstLine = self.getLine(from.line);
if (firstLine == null || probablyInsideString(self, from, firstLine)) return;
var commentString = options.lineComment || mode.lineComment;
if (!commentString) {
if (options.blockCommentStart || mode.blockCommentStart) {
options.fullLines = true;
self.blockComment(from, to, options);
}
return;
}
var end = Math.min(to.ch != 0 || to.line == from.line ? to.line + 1 : to.line, self.lastLine() + 1);
var pad = options.padding == null ? " " : options.padding;
var blankLines = options.commentBlankLines || from.line == to.line;
self.operation(function() {
if (options.indent) {
var baseString = null;
for (var i = from.line; i < end; ++i) {
var line = self.getLine(i);
var whitespace = line.slice(0, firstNonWS(line));
if (baseString == null || baseString.length > whitespace.length) {
baseString = whitespace;
}
}
for (var i = from.line; i < end; ++i) {
var line = self.getLine(i), cut = baseString.length;
if (!blankLines && !nonWS.test(line)) continue;
if (line.slice(0, cut) != baseString) cut = firstNonWS(line);
self.replaceRange(baseString + commentString + pad, Pos(i, 0), Pos(i, cut));
}
} else {
for (var i = from.line; i < end; ++i) {
if (blankLines || nonWS.test(self.getLine(i)))
self.replaceRange(commentString + pad, Pos(i, 0));
}
}
});
});
CodeMirror.defineExtension("blockComment", function(from, to, options) {
if (!options) options = noOptions;
var self = this, mode = getMode(self, from);
var startString = options.blockCommentStart || mode.blockCommentStart;
var endString = options.blockCommentEnd || mode.blockCommentEnd;
if (!startString || !endString) {
if ((options.lineComment || mode.lineComment) && options.fullLines != false)
self.lineComment(from, to, options);
return;
}
if (/\bcomment\b/.test(self.getTokenTypeAt(Pos(from.line, 0)))) return
var end = Math.min(to.line, self.lastLine());
if (end != from.line && to.ch == 0 && nonWS.test(self.getLine(end))) --end;
var pad = options.padding == null ? " " : options.padding;
if (from.line > end) return;
self.operation(function() {
if (options.fullLines != false) {
var lastLineHasText = nonWS.test(self.getLine(end));
self.replaceRange(pad + endString, Pos(end));
self.replaceRange(startString + pad, Pos(from.line, 0));
var lead = options.blockCommentLead || mode.blockCommentLead;
if (lead != null) for (var i = from.line + 1; i <= end; ++i)
if (i != end || lastLineHasText)
self.replaceRange(lead + pad, Pos(i, 0));
} else {
var atCursor = cmp(self.getCursor("to"), to) == 0, empty = !self.somethingSelected()
self.replaceRange(endString, to);
if (atCursor) self.setSelection(empty ? to : self.getCursor("from"), to)
self.replaceRange(startString, from);
}
});
});
CodeMirror.defineExtension("uncomment", function(from, to, options) {
if (!options) options = noOptions;
var self = this, mode = getMode(self, from);
var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()), start = Math.min(from.line, end);
// Try finding line comments
var lineString = options.lineComment || mode.lineComment, lines = [];
var pad = options.padding == null ? " " : options.padding, didSomething;
lineComment: {
if (!lineString) break lineComment;
for (var i = start; i <= end; ++i) {
var line = self.getLine(i);
var found = line.indexOf(lineString);
if (found > -1 && !/comment/.test(self.getTokenTypeAt(Pos(i, found + 1)))) found = -1;
if (found == -1 && nonWS.test(line)) break lineComment;
if (found > -1 && nonWS.test(line.slice(0, found))) break lineComment;
lines.push(line);
}
self.operation(function() {
for (var i = start; i <= end; ++i) {
var line = lines[i - start];
var pos = line.indexOf(lineString), endPos = pos + lineString.length;
if (pos < 0) continue;
if (line.slice(endPos, endPos + pad.length) == pad) endPos += pad.length;
didSomething = true;
self.replaceRange("", Pos(i, pos), Pos(i, endPos));
}
});
if (didSomething) return true;
}
// Try block comments
var startString = options.blockCommentStart || mode.blockCommentStart;
var endString = options.blockCommentEnd || mode.blockCommentEnd;
if (!startString || !endString) return false;
var lead = options.blockCommentLead || mode.blockCommentLead;
var startLine = self.getLine(start), open = startLine.indexOf(startString)
if (open == -1) return false
var endLine = end == start ? startLine : self.getLine(end)
var close = endLine.indexOf(endString, end == start ? open + startString.length : 0);
var insideStart = Pos(start, open + 1), insideEnd = Pos(end, close + 1)
if (close == -1 ||
!/comment/.test(self.getTokenTypeAt(insideStart)) ||
!/comment/.test(self.getTokenTypeAt(insideEnd)) ||
self.getRange(insideStart, insideEnd, "\n").indexOf(endString) > -1)
return false;
// Avoid killing block comments completely outside the selection.
// Positions of the last startString before the start of the selection, and the first endString after it.
var lastStart = startLine.lastIndexOf(startString, from.ch);
var firstEnd = lastStart == -1 ? -1 : startLine.slice(0, from.ch).indexOf(endString, lastStart + startString.length);
if (lastStart != -1 && firstEnd != -1 && firstEnd + endString.length != from.ch) return false;
// Positions of the first endString after the end of the selection, and the last startString before it.
firstEnd = endLine.indexOf(endString, to.ch);
var almostLastStart = endLine.slice(to.ch).lastIndexOf(startString, firstEnd - to.ch);
lastStart = (firstEnd == -1 || almostLastStart == -1) ? -1 : to.ch + almostLastStart;
if (firstEnd != -1 && lastStart != -1 && lastStart != to.ch) return false;
self.operation(function() {
self.replaceRange("", Pos(end, close - (pad && endLine.slice(close - pad.length, close) == pad ? pad.length : 0)),
Pos(end, close + endString.length));
var openEnd = open + startString.length;
if (pad && startLine.slice(openEnd, openEnd + pad.length) == pad) openEnd += pad.length;
self.replaceRange("", Pos(start, open), Pos(start, openEnd));
if (lead) for (var i = start + 1; i <= end; ++i) {
var line = self.getLine(i), found = line.indexOf(lead);
if (found == -1 || nonWS.test(line.slice(0, found))) continue;
var foundEnd = found + lead.length;
if (pad && line.slice(foundEnd, foundEnd + pad.length) == pad) foundEnd += pad.length;
self.replaceRange("", Pos(i, found), Pos(i, foundEnd));
}
});
return true;
});
});

View File

@ -0,0 +1,114 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
var nonspace = /\S/g;
var repeat = String.prototype.repeat || function (n) { return Array(n + 1).join(this); };
function continueComment(cm) {
if (cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections(), mode, inserts = [];
for (var i = 0; i < ranges.length; i++) {
var pos = ranges[i].head
if (!/\bcomment\b/.test(cm.getTokenTypeAt(pos))) return CodeMirror.Pass;
var modeHere = cm.getModeAt(pos)
if (!mode) mode = modeHere;
else if (mode != modeHere) return CodeMirror.Pass;
var insert = null, line, found;
var blockStart = mode.blockCommentStart, lineCmt = mode.lineComment;
if (blockStart && mode.blockCommentContinue) {
line = cm.getLine(pos.line);
var end = line.lastIndexOf(mode.blockCommentEnd, pos.ch - mode.blockCommentEnd.length);
// 1. if this block comment ended
// 2. if this is actually inside a line comment
if (end != -1 && end == pos.ch - mode.blockCommentEnd.length ||
lineCmt && (found = line.lastIndexOf(lineCmt, pos.ch - 1)) > -1 &&
/\bcomment\b/.test(cm.getTokenTypeAt({line: pos.line, ch: found + 1}))) {
// ...then don't continue it
} else if (pos.ch >= blockStart.length &&
(found = line.lastIndexOf(blockStart, pos.ch - blockStart.length)) > -1 &&
found > end) {
// reuse the existing leading spaces/tabs/mixed
// or build the correct indent using CM's tab/indent options
if (nonspaceAfter(0, line) >= found) {
insert = line.slice(0, found);
} else {
var tabSize = cm.options.tabSize, numTabs;
found = CodeMirror.countColumn(line, found, tabSize);
insert = !cm.options.indentWithTabs ? repeat.call(" ", found) :
repeat.call("\t", (numTabs = Math.floor(found / tabSize))) +
repeat.call(" ", found - tabSize * numTabs);
}
} else if ((found = line.indexOf(mode.blockCommentContinue)) > -1 &&
found <= pos.ch &&
found <= nonspaceAfter(0, line)) {
insert = line.slice(0, found);
}
if (insert != null) insert += mode.blockCommentContinue
}
if (insert == null && lineCmt && continueLineCommentEnabled(cm)) {
if (line == null) line = cm.getLine(pos.line);
found = line.indexOf(lineCmt);
// cursor at pos 0, line comment also at pos 0 => shift it down, don't continue
if (!pos.ch && !found) insert = "";
// continue only if the line starts with an optional space + line comment
else if (found > -1 && nonspaceAfter(0, line) >= found) {
// don't continue if there's only space(s) after cursor or the end of the line
insert = nonspaceAfter(pos.ch, line) > -1;
// but always continue if the next line starts with a line comment too
if (!insert) {
var next = cm.getLine(pos.line + 1) || '',
nextFound = next.indexOf(lineCmt);
insert = nextFound > -1 && nonspaceAfter(0, next) >= nextFound || null;
}
if (insert) {
insert = line.slice(0, found) + lineCmt +
line.slice(found + lineCmt.length).match(/^\s*/)[0];
}
}
}
if (insert == null) return CodeMirror.Pass;
inserts[i] = "\n" + insert;
}
cm.operation(function() {
for (var i = ranges.length - 1; i >= 0; i--)
cm.replaceRange(inserts[i], ranges[i].from(), ranges[i].to(), "+insert");
});
}
function nonspaceAfter(ch, str) {
nonspace.lastIndex = ch;
var m = nonspace.exec(str);
return m ? m.index : -1;
}
function continueLineCommentEnabled(cm) {
var opt = cm.getOption("continueComments");
if (opt && typeof opt == "object")
return opt.continueLineComment !== false;
return true;
}
CodeMirror.defineOption("continueComments", null, function(cm, val, prev) {
if (prev && prev != CodeMirror.Init)
cm.removeKeyMap("continueComment");
if (val) {
var key = "Enter";
if (typeof val == "string")
key = val;
else if (typeof val == "object" && val.key)
key = val.key;
var map = {name: "continueComment"};
map[key] = continueComment;
cm.addKeyMap(map);
}
});
});

View File

@ -0,0 +1,32 @@
.CodeMirror-dialog {
position: absolute;
left: 0; right: 0;
background: inherit;
z-index: 15;
padding: .1em .8em;
overflow: hidden;
color: inherit;
}
.CodeMirror-dialog-top {
border-bottom: 1px solid #eee;
top: 0;
}
.CodeMirror-dialog-bottom {
border-top: 1px solid #eee;
bottom: 0;
}
.CodeMirror-dialog input {
border: none;
outline: none;
background: transparent;
width: 20em;
color: inherit;
font-family: monospace;
}
.CodeMirror-dialog button {
font-size: 70%;
}

View File

@ -0,0 +1,163 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
// Open simple dialogs on top of an editor. Relies on dialog.css.
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
function dialogDiv(cm, template, bottom) {
var wrap = cm.getWrapperElement();
var dialog;
dialog = wrap.appendChild(document.createElement("div"));
if (bottom)
dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom";
else
dialog.className = "CodeMirror-dialog CodeMirror-dialog-top";
if (typeof template == "string") {
dialog.innerHTML = template;
} else { // Assuming it's a detached DOM element.
dialog.appendChild(template);
}
CodeMirror.addClass(wrap, 'dialog-opened');
return dialog;
}
function closeNotification(cm, newVal) {
if (cm.state.currentNotificationClose)
cm.state.currentNotificationClose();
cm.state.currentNotificationClose = newVal;
}
CodeMirror.defineExtension("openDialog", function(template, callback, options) {
if (!options) options = {};
closeNotification(this, null);
var dialog = dialogDiv(this, template, options.bottom);
var closed = false, me = this;
function close(newVal) {
if (typeof newVal == 'string') {
inp.value = newVal;
} else {
if (closed) return;
closed = true;
CodeMirror.rmClass(dialog.parentNode, 'dialog-opened');
dialog.parentNode.removeChild(dialog);
me.focus();
if (options.onClose) options.onClose(dialog);
}
}
var inp = dialog.getElementsByTagName("input")[0], button;
if (inp) {
inp.focus();
if (options.value) {
inp.value = options.value;
if (options.selectValueOnOpen !== false) {
inp.select();
}
}
if (options.onInput)
CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);});
if (options.onKeyUp)
CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);});
CodeMirror.on(inp, "keydown", function(e) {
if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; }
if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) {
inp.blur();
CodeMirror.e_stop(e);
close();
}
if (e.keyCode == 13) callback(inp.value, e);
});
if (options.closeOnBlur !== false) CodeMirror.on(dialog, "focusout", function (evt) {
if (evt.relatedTarget !== null) close();
});
} else if (button = dialog.getElementsByTagName("button")[0]) {
CodeMirror.on(button, "click", function() {
close();
me.focus();
});
if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close);
button.focus();
}
return close;
});
CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) {
closeNotification(this, null);
var dialog = dialogDiv(this, template, options && options.bottom);
var buttons = dialog.getElementsByTagName("button");
var closed = false, me = this, blurring = 1;
function close() {
if (closed) return;
closed = true;
CodeMirror.rmClass(dialog.parentNode, 'dialog-opened');
dialog.parentNode.removeChild(dialog);
me.focus();
}
buttons[0].focus();
for (var i = 0; i < buttons.length; ++i) {
var b = buttons[i];
(function(callback) {
CodeMirror.on(b, "click", function(e) {
CodeMirror.e_preventDefault(e);
close();
if (callback) callback(me);
});
})(callbacks[i]);
CodeMirror.on(b, "blur", function() {
--blurring;
setTimeout(function() { if (blurring <= 0) close(); }, 200);
});
CodeMirror.on(b, "focus", function() { ++blurring; });
}
});
/*
* openNotification
* Opens a notification, that can be closed with an optional timer
* (default 5000ms timer) and always closes on click.
*
* If a notification is opened while another is opened, it will close the
* currently opened one and open the new one immediately.
*/
CodeMirror.defineExtension("openNotification", function(template, options) {
closeNotification(this, close);
var dialog = dialogDiv(this, template, options && options.bottom);
var closed = false, doneTimer;
var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000;
function close() {
if (closed) return;
closed = true;
clearTimeout(doneTimer);
CodeMirror.rmClass(dialog.parentNode, 'dialog-opened');
dialog.parentNode.removeChild(dialog);
}
CodeMirror.on(dialog, 'click', function(e) {
CodeMirror.e_preventDefault(e);
close();
});
if (duration)
doneTimer = setTimeout(close, duration);
return close;
});
});

View File

@ -0,0 +1,47 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"))
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod)
else // Plain browser env
mod(CodeMirror)
})(function(CodeMirror) {
"use strict"
CodeMirror.defineOption("autoRefresh", false, function(cm, val) {
if (cm.state.autoRefresh) {
stopListening(cm, cm.state.autoRefresh)
cm.state.autoRefresh = null
}
if (val && cm.display.wrapper.offsetHeight == 0)
startListening(cm, cm.state.autoRefresh = {delay: val.delay || 250})
})
function startListening(cm, state) {
function check() {
if (cm.display.wrapper.offsetHeight) {
stopListening(cm, state)
if (cm.display.lastWrapHeight != cm.display.wrapper.clientHeight)
cm.refresh()
} else {
state.timeout = setTimeout(check, state.delay)
}
}
state.timeout = setTimeout(check, state.delay)
state.hurry = function() {
clearTimeout(state.timeout)
state.timeout = setTimeout(check, 50)
}
CodeMirror.on(window, "mouseup", state.hurry)
CodeMirror.on(window, "keyup", state.hurry)
}
function stopListening(_cm, state) {
clearTimeout(state.timeout)
CodeMirror.off(window, "mouseup", state.hurry)
CodeMirror.off(window, "keyup", state.hurry)
}
});

View File

@ -0,0 +1,6 @@
.CodeMirror-fullscreen {
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
height: auto;
z-index: 9;
}

View File

@ -0,0 +1,41 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineOption("fullScreen", false, function(cm, val, old) {
if (old == CodeMirror.Init) old = false;
if (!old == !val) return;
if (val) setFullscreen(cm);
else setNormal(cm);
});
function setFullscreen(cm) {
var wrap = cm.getWrapperElement();
cm.state.fullScreenRestore = {scrollTop: window.pageYOffset, scrollLeft: window.pageXOffset,
width: wrap.style.width, height: wrap.style.height};
wrap.style.width = "";
wrap.style.height = "auto";
wrap.className += " CodeMirror-fullscreen";
document.documentElement.style.overflow = "hidden";
cm.refresh();
}
function setNormal(cm) {
var wrap = cm.getWrapperElement();
wrap.className = wrap.className.replace(/\s*CodeMirror-fullscreen\b/, "");
document.documentElement.style.overflow = "";
var info = cm.state.fullScreenRestore;
wrap.style.width = info.width; wrap.style.height = info.height;
window.scrollTo(info.scrollLeft, info.scrollTop);
cm.refresh();
}
});

View File

@ -0,0 +1,129 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function (mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function (CodeMirror) {
CodeMirror.defineExtension("addPanel", function (node, options) {
options = options || {};
if (!this.state.panels) initPanels(this);
var info = this.state.panels;
var wrapper = info.wrapper;
var cmWrapper = this.getWrapperElement();
var replace = options.replace instanceof Panel && !options.replace.cleared;
if (options.after instanceof Panel && !options.after.cleared) {
wrapper.insertBefore(node, options.before.node.nextSibling);
} else if (options.before instanceof Panel && !options.before.cleared) {
wrapper.insertBefore(node, options.before.node);
} else if (replace) {
wrapper.insertBefore(node, options.replace.node);
options.replace.clear(true);
} else if (options.position == "bottom") {
wrapper.appendChild(node);
} else if (options.position == "before-bottom") {
wrapper.insertBefore(node, cmWrapper.nextSibling);
} else if (options.position == "after-top") {
wrapper.insertBefore(node, cmWrapper);
} else {
wrapper.insertBefore(node, wrapper.firstChild);
}
var height = (options && options.height) || node.offsetHeight;
var panel = new Panel(this, node, options, height);
info.panels.push(panel);
this.setSize();
if (options.stable && isAtTop(this, node))
this.scrollTo(null, this.getScrollInfo().top + height);
return panel;
});
function Panel(cm, node, options, height) {
this.cm = cm;
this.node = node;
this.options = options;
this.height = height;
this.cleared = false;
}
/* when skipRemove is true, clear() was called from addPanel().
* Thus removePanels() should not be called (issue 5518) */
Panel.prototype.clear = function (skipRemove) {
if (this.cleared) return;
this.cleared = true;
var info = this.cm.state.panels;
info.panels.splice(info.panels.indexOf(this), 1);
this.cm.setSize();
if (this.options.stable && isAtTop(this.cm, this.node))
this.cm.scrollTo(null, this.cm.getScrollInfo().top - this.height)
info.wrapper.removeChild(this.node);
if (info.panels.length == 0 && !skipRemove) removePanels(this.cm);
};
Panel.prototype.changed = function () {
this.height = this.node.getBoundingClientRect().height;
this.cm.setSize();
};
function initPanels(cm) {
var wrap = cm.getWrapperElement();
var style = window.getComputedStyle ? window.getComputedStyle(wrap) : wrap.currentStyle;
var height = parseInt(style.height);
var info = cm.state.panels = {
setHeight: wrap.style.height,
panels: [],
wrapper: document.createElement("div")
};
wrap.parentNode.insertBefore(info.wrapper, wrap);
var hasFocus = cm.hasFocus();
info.wrapper.appendChild(wrap);
if (hasFocus) cm.focus();
cm._setSize = cm.setSize;
if (height != null) cm.setSize = function (width, newHeight) {
if (!newHeight) newHeight = info.wrapper.offsetHeight;
info.setHeight = newHeight;
if (typeof newHeight != "number") {
var px = /^(\d+\.?\d*)px$/.exec(newHeight);
if (px) {
newHeight = Number(px[1]);
} else {
info.wrapper.style.height = newHeight;
newHeight = info.wrapper.offsetHeight;
}
}
var editorheight = newHeight - info.panels
.map(function (p) { return p.node.getBoundingClientRect().height; })
.reduce(function (a, b) { return a + b; }, 0);
cm._setSize(width, editorheight);
height = newHeight;
};
}
function removePanels(cm) {
var info = cm.state.panels;
cm.state.panels = null;
var wrap = cm.getWrapperElement();
info.wrapper.parentNode.replaceChild(wrap, info.wrapper);
wrap.style.height = info.setHeight;
cm.setSize = cm._setSize;
cm.setSize();
}
function isAtTop(cm, dom) {
for (var sibling = dom.nextSibling; sibling; sibling = sibling.nextSibling)
if (sibling == cm.getWrapperElement()) return true
return false
}
});

View File

@ -0,0 +1,77 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
CodeMirror.defineOption("placeholder", "", function(cm, val, old) {
var prev = old && old != CodeMirror.Init;
if (val && !prev) {
cm.on("blur", onBlur);
cm.on("change", onChange);
cm.on("swapDoc", onChange);
CodeMirror.on(cm.getInputField(), "compositionupdate", cm.state.placeholderCompose = function() { onComposition(cm) })
onChange(cm);
} else if (!val && prev) {
cm.off("blur", onBlur);
cm.off("change", onChange);
cm.off("swapDoc", onChange);
CodeMirror.off(cm.getInputField(), "compositionupdate", cm.state.placeholderCompose)
clearPlaceholder(cm);
var wrapper = cm.getWrapperElement();
wrapper.className = wrapper.className.replace(" CodeMirror-empty", "");
}
if (val && !cm.hasFocus()) onBlur(cm);
});
function clearPlaceholder(cm) {
if (cm.state.placeholder) {
cm.state.placeholder.parentNode.removeChild(cm.state.placeholder);
cm.state.placeholder = null;
}
}
function setPlaceholder(cm) {
clearPlaceholder(cm);
var elt = cm.state.placeholder = document.createElement("pre");
elt.style.cssText = "height: 0; overflow: visible";
elt.style.direction = cm.getOption("direction");
elt.className = "CodeMirror-placeholder CodeMirror-line-like";
var placeHolder = cm.getOption("placeholder")
if (typeof placeHolder == "string") placeHolder = document.createTextNode(placeHolder)
elt.appendChild(placeHolder)
cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild);
}
function onComposition(cm) {
setTimeout(function() {
var empty = false, input = cm.getInputField()
if (input.nodeName == "TEXTAREA")
empty = !input.value
else if (cm.lineCount() == 1)
empty = !/[^\u200b]/.test(input.querySelector(".CodeMirror-line").textContent)
if (empty) setPlaceholder(cm)
else clearPlaceholder(cm)
}, 20)
}
function onBlur(cm) {
if (isEmpty(cm)) setPlaceholder(cm);
}
function onChange(cm) {
var wrapper = cm.getWrapperElement(), empty = isEmpty(cm);
wrapper.className = wrapper.className.replace(" CodeMirror-empty", "") + (empty ? " CodeMirror-empty" : "");
if (empty) setPlaceholder(cm);
else clearPlaceholder(cm);
}
function isEmpty(cm) {
return (cm.lineCount() === 1) && (cm.getLine(0) === "");
}
});

View File

@ -0,0 +1,51 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineOption("rulers", false, function(cm, val) {
if (cm.state.rulerDiv) {
cm.state.rulerDiv.parentElement.removeChild(cm.state.rulerDiv)
cm.state.rulerDiv = null
cm.off("refresh", drawRulers)
}
if (val && val.length) {
cm.state.rulerDiv = cm.display.lineSpace.parentElement.insertBefore(document.createElement("div"), cm.display.lineSpace)
cm.state.rulerDiv.className = "CodeMirror-rulers"
drawRulers(cm)
cm.on("refresh", drawRulers)
}
});
function drawRulers(cm) {
cm.state.rulerDiv.textContent = ""
var val = cm.getOption("rulers");
var cw = cm.defaultCharWidth();
var left = cm.charCoords(CodeMirror.Pos(cm.firstLine(), 0), "div").left;
cm.state.rulerDiv.style.minHeight = (cm.display.scroller.offsetHeight + 30) + "px";
for (var i = 0; i < val.length; i++) {
var elt = document.createElement("div");
elt.className = "CodeMirror-ruler";
var col, conf = val[i];
if (typeof conf == "number") {
col = conf;
} else {
col = conf.column;
if (conf.className) elt.className += " " + conf.className;
if (conf.color) elt.style.borderColor = conf.color;
if (conf.lineStyle) elt.style.borderLeftStyle = conf.lineStyle;
if (conf.width) elt.style.borderLeftWidth = conf.width;
}
elt.style.left = (left + col * cw) + "px";
cm.state.rulerDiv.appendChild(elt)
}
}
});

View File

@ -0,0 +1,191 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
var defaults = {
pairs: "()[]{}''\"\"",
closeBefore: ")]}'\":;>",
triples: "",
explode: "[]{}"
};
var Pos = CodeMirror.Pos;
CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
if (old && old != CodeMirror.Init) {
cm.removeKeyMap(keyMap);
cm.state.closeBrackets = null;
}
if (val) {
ensureBound(getOption(val, "pairs"))
cm.state.closeBrackets = val;
cm.addKeyMap(keyMap);
}
});
function getOption(conf, name) {
if (name == "pairs" && typeof conf == "string") return conf;
if (typeof conf == "object" && conf[name] != null) return conf[name];
return defaults[name];
}
var keyMap = {Backspace: handleBackspace, Enter: handleEnter};
function ensureBound(chars) {
for (var i = 0; i < chars.length; i++) {
var ch = chars.charAt(i), key = "'" + ch + "'"
if (!keyMap[key]) keyMap[key] = handler(ch)
}
}
ensureBound(defaults.pairs + "`")
function handler(ch) {
return function(cm) { return handleChar(cm, ch); };
}
function getConfig(cm) {
var deflt = cm.state.closeBrackets;
if (!deflt || deflt.override) return deflt;
var mode = cm.getModeAt(cm.getCursor());
return mode.closeBrackets || deflt;
}
function handleBackspace(cm) {
var conf = getConfig(cm);
if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
var pairs = getOption(conf, "pairs");
var ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) {
if (!ranges[i].empty()) return CodeMirror.Pass;
var around = charsAround(cm, ranges[i].head);
if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
}
for (var i = ranges.length - 1; i >= 0; i--) {
var cur = ranges[i].head;
cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1), "+delete");
}
}
function handleEnter(cm) {
var conf = getConfig(cm);
var explode = conf && getOption(conf, "explode");
if (!explode || cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) {
if (!ranges[i].empty()) return CodeMirror.Pass;
var around = charsAround(cm, ranges[i].head);
if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass;
}
cm.operation(function() {
var linesep = cm.lineSeparator() || "\n";
cm.replaceSelection(linesep + linesep, null);
cm.execCommand("goCharLeft");
ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) {
var line = ranges[i].head.line;
cm.indentLine(line, null, true);
cm.indentLine(line + 1, null, true);
}
});
}
function contractSelection(sel) {
var inverted = CodeMirror.cmpPos(sel.anchor, sel.head) > 0;
return {anchor: new Pos(sel.anchor.line, sel.anchor.ch + (inverted ? -1 : 1)),
head: new Pos(sel.head.line, sel.head.ch + (inverted ? 1 : -1))};
}
function handleChar(cm, ch) {
var conf = getConfig(cm);
if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
var pairs = getOption(conf, "pairs");
var pos = pairs.indexOf(ch);
if (pos == -1) return CodeMirror.Pass;
var closeBefore = getOption(conf,"closeBefore");
var triples = getOption(conf, "triples");
var identical = pairs.charAt(pos + 1) == ch;
var ranges = cm.listSelections();
var opening = pos % 2 == 0;
var type;
for (var i = 0; i < ranges.length; i++) {
var range = ranges[i], cur = range.head, curType;
var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
if (opening && !range.empty()) {
curType = "surround";
} else if ((identical || !opening) && next == ch) {
if (identical && stringStartsAfter(cm, cur))
curType = "both";
else if (triples.indexOf(ch) >= 0 && cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == ch + ch + ch)
curType = "skipThree";
else
curType = "skip";
} else if (identical && cur.ch > 1 && triples.indexOf(ch) >= 0 &&
cm.getRange(Pos(cur.line, cur.ch - 2), cur) == ch + ch) {
if (cur.ch > 2 && /\bstring/.test(cm.getTokenTypeAt(Pos(cur.line, cur.ch - 2)))) return CodeMirror.Pass;
curType = "addFour";
} else if (identical) {
var prev = cur.ch == 0 ? " " : cm.getRange(Pos(cur.line, cur.ch - 1), cur)
if (!CodeMirror.isWordChar(next) && prev != ch && !CodeMirror.isWordChar(prev)) curType = "both";
else return CodeMirror.Pass;
} else if (opening && (next.length === 0 || /\s/.test(next) || closeBefore.indexOf(next) > -1)) {
curType = "both";
} else {
return CodeMirror.Pass;
}
if (!type) type = curType;
else if (type != curType) return CodeMirror.Pass;
}
var left = pos % 2 ? pairs.charAt(pos - 1) : ch;
var right = pos % 2 ? ch : pairs.charAt(pos + 1);
cm.operation(function() {
if (type == "skip") {
cm.execCommand("goCharRight");
} else if (type == "skipThree") {
for (var i = 0; i < 3; i++)
cm.execCommand("goCharRight");
} else if (type == "surround") {
var sels = cm.getSelections();
for (var i = 0; i < sels.length; i++)
sels[i] = left + sels[i] + right;
cm.replaceSelections(sels, "around");
sels = cm.listSelections().slice();
for (var i = 0; i < sels.length; i++)
sels[i] = contractSelection(sels[i]);
cm.setSelections(sels);
} else if (type == "both") {
cm.replaceSelection(left + right, null);
cm.triggerElectric(left + right);
cm.execCommand("goCharLeft");
} else if (type == "addFour") {
cm.replaceSelection(left + left + left + left, "before");
cm.execCommand("goCharRight");
}
});
}
function charsAround(cm, pos) {
var str = cm.getRange(Pos(pos.line, pos.ch - 1),
Pos(pos.line, pos.ch + 1));
return str.length == 2 ? str : null;
}
function stringStartsAfter(cm, pos) {
var token = cm.getTokenAt(Pos(pos.line, pos.ch + 1))
return /\bstring/.test(token.type) && token.start == pos.ch &&
(pos.ch == 0 || !/\bstring/.test(cm.getTokenTypeAt(pos)))
}
});

View File

@ -0,0 +1,184 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
/**
* Tag-closer extension for CodeMirror.
*
* This extension adds an "autoCloseTags" option that can be set to
* either true to get the default behavior, or an object to further
* configure its behavior.
*
* These are supported options:
*
* `whenClosing` (default true)
* Whether to autoclose when the '/' of a closing tag is typed.
* `whenOpening` (default true)
* Whether to autoclose the tag when the final '>' of an opening
* tag is typed.
* `dontCloseTags` (default is empty tags for HTML, none for XML)
* An array of tag names that should not be autoclosed.
* `indentTags` (default is block tags for HTML, none for XML)
* An array of tag names that should, when opened, cause a
* blank line to be added inside the tag, and the blank line and
* closing line to be indented.
* `emptyTags` (default is none)
* An array of XML tag names that should be autoclosed with '/>'.
*
* See demos/closetag.html for a usage example.
*/
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../fold/xml-fold"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "../fold/xml-fold"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
CodeMirror.defineOption("autoCloseTags", false, function(cm, val, old) {
if (old != CodeMirror.Init && old)
cm.removeKeyMap("autoCloseTags");
if (!val) return;
var map = {name: "autoCloseTags"};
if (typeof val != "object" || val.whenClosing !== false)
map["'/'"] = function(cm) { return autoCloseSlash(cm); };
if (typeof val != "object" || val.whenOpening !== false)
map["'>'"] = function(cm) { return autoCloseGT(cm); };
cm.addKeyMap(map);
});
var htmlDontClose = ["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param",
"source", "track", "wbr"];
var htmlIndent = ["applet", "blockquote", "body", "button", "div", "dl", "fieldset", "form", "frameset", "h1", "h2", "h3", "h4",
"h5", "h6", "head", "html", "iframe", "layer", "legend", "object", "ol", "p", "select", "table", "ul"];
function autoCloseGT(cm) {
if (cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections(), replacements = [];
var opt = cm.getOption("autoCloseTags");
for (var i = 0; i < ranges.length; i++) {
if (!ranges[i].empty()) return CodeMirror.Pass;
var pos = ranges[i].head, tok = cm.getTokenAt(pos);
var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
var tagInfo = inner.mode.xmlCurrentTag && inner.mode.xmlCurrentTag(state)
var tagName = tagInfo && tagInfo.name
if (!tagName) return CodeMirror.Pass
var html = inner.mode.configuration == "html";
var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose);
var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent);
if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch);
var lowerTagName = tagName.toLowerCase();
// Don't process the '>' at the end of an end-tag or self-closing tag
if (!tagName ||
tok.type == "string" && (tok.end != pos.ch || !/[\"\']/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1) ||
tok.type == "tag" && tagInfo.close ||
tok.string.indexOf("/") == (pos.ch - tok.start - 1) || // match something like <someTagName />
dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 ||
closingTagExists(cm, inner.mode.xmlCurrentContext && inner.mode.xmlCurrentContext(state) || [], tagName, pos, true))
return CodeMirror.Pass;
var emptyTags = typeof opt == "object" && opt.emptyTags;
if (emptyTags && indexOf(emptyTags, tagName) > -1) {
replacements[i] = { text: "/>", newPos: CodeMirror.Pos(pos.line, pos.ch + 2) };
continue;
}
var indent = indentTags && indexOf(indentTags, lowerTagName) > -1;
replacements[i] = {indent: indent,
text: ">" + (indent ? "\n\n" : "") + "</" + tagName + ">",
newPos: indent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1)};
}
var dontIndentOnAutoClose = (typeof opt == "object" && opt.dontIndentOnAutoClose);
for (var i = ranges.length - 1; i >= 0; i--) {
var info = replacements[i];
cm.replaceRange(info.text, ranges[i].head, ranges[i].anchor, "+insert");
var sel = cm.listSelections().slice(0);
sel[i] = {head: info.newPos, anchor: info.newPos};
cm.setSelections(sel);
if (!dontIndentOnAutoClose && info.indent) {
cm.indentLine(info.newPos.line, null, true);
cm.indentLine(info.newPos.line + 1, null, true);
}
}
}
function autoCloseCurrent(cm, typingSlash) {
var ranges = cm.listSelections(), replacements = [];
var head = typingSlash ? "/" : "</";
var opt = cm.getOption("autoCloseTags");
var dontIndentOnAutoClose = (typeof opt == "object" && opt.dontIndentOnSlash);
for (var i = 0; i < ranges.length; i++) {
if (!ranges[i].empty()) return CodeMirror.Pass;
var pos = ranges[i].head, tok = cm.getTokenAt(pos);
var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
if (typingSlash && (tok.type == "string" || tok.string.charAt(0) != "<" ||
tok.start != pos.ch - 1))
return CodeMirror.Pass;
// Kludge to get around the fact that we are not in XML mode
// when completing in JS/CSS snippet in htmlmixed mode. Does not
// work for other XML embedded languages (there is no general
// way to go from a mixed mode to its current XML state).
var replacement, mixed = inner.mode.name != "xml" && cm.getMode().name == "htmlmixed"
if (mixed && inner.mode.name == "javascript") {
replacement = head + "script";
} else if (mixed && inner.mode.name == "css") {
replacement = head + "style";
} else {
var context = inner.mode.xmlCurrentContext && inner.mode.xmlCurrentContext(state)
if (!context || (context.length && closingTagExists(cm, context, context[context.length - 1], pos)))
return CodeMirror.Pass;
replacement = head + context[context.length - 1]
}
if (cm.getLine(pos.line).charAt(tok.end) != ">") replacement += ">";
replacements[i] = replacement;
}
cm.replaceSelections(replacements);
ranges = cm.listSelections();
if (!dontIndentOnAutoClose) {
for (var i = 0; i < ranges.length; i++)
if (i == ranges.length - 1 || ranges[i].head.line < ranges[i + 1].head.line)
cm.indentLine(ranges[i].head.line);
}
}
function autoCloseSlash(cm) {
if (cm.getOption("disableInput")) return CodeMirror.Pass;
return autoCloseCurrent(cm, true);
}
CodeMirror.commands.closeTag = function(cm) { return autoCloseCurrent(cm); };
function indexOf(collection, elt) {
if (collection.indexOf) return collection.indexOf(elt);
for (var i = 0, e = collection.length; i < e; ++i)
if (collection[i] == elt) return i;
return -1;
}
// If xml-fold is loaded, we use its functionality to try and verify
// whether a given tag is actually unclosed.
function closingTagExists(cm, context, tagName, pos, newTag) {
if (!CodeMirror.scanForClosingTag) return false;
var end = Math.min(cm.lastLine() + 1, pos.line + 500);
var nextClose = CodeMirror.scanForClosingTag(cm, pos, null, end);
if (!nextClose || nextClose.tag != tagName) return false;
// If the immediate wrapping context contains onCx instances of
// the same tag, a closing tag only exists if there are at least
// that many closing tags of that type following.
var onCx = newTag ? 1 : 0
for (var i = context.length - 1; i >= 0; i--) {
if (context[i] == tagName) ++onCx
else break
}
pos = nextClose.to;
for (var i = 1; i < onCx; i++) {
var next = CodeMirror.scanForClosingTag(cm, pos, null, end);
if (!next || next.tag != tagName) return false;
pos = next.to;
}
return true;
}
});

View File

@ -0,0 +1,101 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var listRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/,
emptyListRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]|[*+-]|(\d+)[.)])(\s*)$/,
unorderedListRE = /[*+-]\s/;
CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) {
if (cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections(), replacements = [];
for (var i = 0; i < ranges.length; i++) {
var pos = ranges[i].head;
// If we're not in Markdown mode, fall back to normal newlineAndIndent
var eolState = cm.getStateAfter(pos.line);
var inner = CodeMirror.innerMode(cm.getMode(), eolState);
if (inner.mode.name !== "markdown") {
cm.execCommand("newlineAndIndent");
return;
} else {
eolState = inner.state;
}
var inList = eolState.list !== false;
var inQuote = eolState.quote !== 0;
var line = cm.getLine(pos.line), match = listRE.exec(line);
var cursorBeforeBullet = /^\s*$/.test(line.slice(0, pos.ch));
if (!ranges[i].empty() || (!inList && !inQuote) || !match || cursorBeforeBullet) {
cm.execCommand("newlineAndIndent");
return;
}
if (emptyListRE.test(line)) {
var endOfQuote = inQuote && />\s*$/.test(line)
var endOfList = !/>\s*$/.test(line)
if (endOfQuote || endOfList) cm.replaceRange("", {
line: pos.line, ch: 0
}, {
line: pos.line, ch: pos.ch + 1
});
replacements[i] = "\n";
} else {
var indent = match[1], after = match[5];
var numbered = !(unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0);
var bullet = numbered ? (parseInt(match[3], 10) + 1) + match[4] : match[2].replace("x", " ");
replacements[i] = "\n" + indent + bullet + after;
if (numbered) incrementRemainingMarkdownListNumbers(cm, pos);
}
}
cm.replaceSelections(replacements);
};
// Auto-updating Markdown list numbers when a new item is added to the
// middle of a list
function incrementRemainingMarkdownListNumbers(cm, pos) {
var startLine = pos.line, lookAhead = 0, skipCount = 0;
var startItem = listRE.exec(cm.getLine(startLine)), startIndent = startItem[1];
do {
lookAhead += 1;
var nextLineNumber = startLine + lookAhead;
var nextLine = cm.getLine(nextLineNumber), nextItem = listRE.exec(nextLine);
if (nextItem) {
var nextIndent = nextItem[1];
var newNumber = (parseInt(startItem[3], 10) + lookAhead - skipCount);
var nextNumber = (parseInt(nextItem[3], 10)), itemNumber = nextNumber;
if (startIndent === nextIndent && !isNaN(nextNumber)) {
if (newNumber === nextNumber) itemNumber = nextNumber + 1;
if (newNumber > nextNumber) itemNumber = newNumber + 1;
cm.replaceRange(
nextLine.replace(listRE, nextIndent + itemNumber + nextItem[4] + nextItem[5]),
{
line: nextLineNumber, ch: 0
}, {
line: nextLineNumber, ch: nextLine.length
});
} else {
if (startIndent.length > nextIndent.length) return;
// This doesn't run if the next line immediatley indents, as it is
// not clear of the users intention (new indented item or same level)
if ((startIndent.length < nextIndent.length) && (lookAhead === 1)) return;
skipCount += 1;
}
}
} while (nextItem);
}
});

View File

@ -0,0 +1,158 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
var ie_lt8 = /MSIE \d/.test(navigator.userAgent) &&
(document.documentMode == null || document.documentMode < 8);
var Pos = CodeMirror.Pos;
var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<", "<": ">>", ">": "<<"};
function bracketRegex(config) {
return config && config.bracketRegex || /[(){}[\]]/
}
function findMatchingBracket(cm, where, config) {
var line = cm.getLineHandle(where.line), pos = where.ch - 1;
var afterCursor = config && config.afterCursor
if (afterCursor == null)
afterCursor = /(^| )cm-fat-cursor($| )/.test(cm.getWrapperElement().className)
var re = bracketRegex(config)
// A cursor is defined as between two characters, but in in vim command mode
// (i.e. not insert mode), the cursor is visually represented as a
// highlighted box on top of the 2nd character. Otherwise, we allow matches
// from before or after the cursor.
var match = (!afterCursor && pos >= 0 && re.test(line.text.charAt(pos)) && matching[line.text.charAt(pos)]) ||
re.test(line.text.charAt(pos + 1)) && matching[line.text.charAt(++pos)];
if (!match) return null;
var dir = match.charAt(1) == ">" ? 1 : -1;
if (config && config.strict && (dir > 0) != (pos == where.ch)) return null;
var style = cm.getTokenTypeAt(Pos(where.line, pos + 1));
var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config);
if (found == null) return null;
return {from: Pos(where.line, pos), to: found && found.pos,
match: found && found.ch == match.charAt(0), forward: dir > 0};
}
// bracketRegex is used to specify which type of bracket to scan
// should be a regexp, e.g. /[[\]]/
//
// Note: If "where" is on an open bracket, then this bracket is ignored.
//
// Returns false when no bracket was found, null when it reached
// maxScanLines and gave up
function scanForBracket(cm, where, dir, style, config) {
var maxScanLen = (config && config.maxScanLineLength) || 10000;
var maxScanLines = (config && config.maxScanLines) || 1000;
var stack = [];
var re = bracketRegex(config)
var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1)
: Math.max(cm.firstLine() - 1, where.line - maxScanLines);
for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) {
var line = cm.getLine(lineNo);
if (!line) continue;
var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1;
if (line.length > maxScanLen) continue;
if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0);
for (; pos != end; pos += dir) {
var ch = line.charAt(pos);
if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) {
var match = matching[ch];
if (match && (match.charAt(1) == ">") == (dir > 0)) stack.push(ch);
else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch};
else stack.pop();
}
}
}
return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null;
}
function matchBrackets(cm, autoclear, config) {
// Disable brace matching in long lines, since it'll cause hugely slow updates
var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000;
var marks = [], ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) {
var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, config);
if (match && cm.getLine(match.from.line).length <= maxHighlightLen) {
var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style}));
if (match.to && cm.getLine(match.to.line).length <= maxHighlightLen)
marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style}));
}
}
if (marks.length) {
// Kludge to work around the IE bug from issue #1193, where text
// input stops going to the textare whever this fires.
if (ie_lt8 && cm.state.focused) cm.focus();
var clear = function() {
cm.operation(function() {
for (var i = 0; i < marks.length; i++) marks[i].clear();
});
};
if (autoclear) setTimeout(clear, 800);
else return clear;
}
}
function doMatchBrackets(cm) {
cm.operation(function() {
if (cm.state.matchBrackets.currentlyHighlighted) {
cm.state.matchBrackets.currentlyHighlighted();
cm.state.matchBrackets.currentlyHighlighted = null;
}
cm.state.matchBrackets.currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets);
});
}
CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) {
function clear(cm) {
if (cm.state.matchBrackets && cm.state.matchBrackets.currentlyHighlighted) {
cm.state.matchBrackets.currentlyHighlighted();
cm.state.matchBrackets.currentlyHighlighted = null;
}
}
if (old && old != CodeMirror.Init) {
cm.off("cursorActivity", doMatchBrackets);
cm.off("focus", doMatchBrackets)
cm.off("blur", clear)
clear(cm);
}
if (val) {
cm.state.matchBrackets = typeof val == "object" ? val : {};
cm.on("cursorActivity", doMatchBrackets);
cm.on("focus", doMatchBrackets)
cm.on("blur", clear)
}
});
CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);});
CodeMirror.defineExtension("findMatchingBracket", function(pos, config, oldConfig){
// Backwards-compatibility kludge
if (oldConfig || typeof config == "boolean") {
if (!oldConfig) {
config = config ? {strict: true} : null
} else {
oldConfig.strict = config
config = oldConfig
}
}
return findMatchingBracket(this, pos, config)
});
CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){
return scanForBracket(this, pos, dir, style, config);
});
});

View File

@ -0,0 +1,66 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../fold/xml-fold"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "../fold/xml-fold"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineOption("matchTags", false, function(cm, val, old) {
if (old && old != CodeMirror.Init) {
cm.off("cursorActivity", doMatchTags);
cm.off("viewportChange", maybeUpdateMatch);
clear(cm);
}
if (val) {
cm.state.matchBothTags = typeof val == "object" && val.bothTags;
cm.on("cursorActivity", doMatchTags);
cm.on("viewportChange", maybeUpdateMatch);
doMatchTags(cm);
}
});
function clear(cm) {
if (cm.state.tagHit) cm.state.tagHit.clear();
if (cm.state.tagOther) cm.state.tagOther.clear();
cm.state.tagHit = cm.state.tagOther = null;
}
function doMatchTags(cm) {
cm.state.failedTagMatch = false;
cm.operation(function() {
clear(cm);
if (cm.somethingSelected()) return;
var cur = cm.getCursor(), range = cm.getViewport();
range.from = Math.min(range.from, cur.line); range.to = Math.max(cur.line + 1, range.to);
var match = CodeMirror.findMatchingTag(cm, cur, range);
if (!match) return;
if (cm.state.matchBothTags) {
var hit = match.at == "open" ? match.open : match.close;
if (hit) cm.state.tagHit = cm.markText(hit.from, hit.to, {className: "CodeMirror-matchingtag"});
}
var other = match.at == "close" ? match.open : match.close;
if (other)
cm.state.tagOther = cm.markText(other.from, other.to, {className: "CodeMirror-matchingtag"});
else
cm.state.failedTagMatch = true;
});
}
function maybeUpdateMatch(cm) {
if (cm.state.failedTagMatch) doMatchTags(cm);
}
CodeMirror.commands.toMatchingTag = function(cm) {
var found = CodeMirror.findMatchingTag(cm, cm.getCursor());
if (found) {
var other = found.at == "close" ? found.open : found.close;
if (other) cm.extendSelection(other.to, other.from);
}
};
});

View File

@ -0,0 +1,27 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
CodeMirror.defineOption("showTrailingSpace", false, function(cm, val, prev) {
if (prev == CodeMirror.Init) prev = false;
if (prev && !val)
cm.removeOverlay("trailingspace");
else if (!prev && val)
cm.addOverlay({
token: function(stream) {
for (var l = stream.string.length, i = l; i && /\s/.test(stream.string.charAt(i - 1)); --i) {}
if (i > stream.pos) { stream.pos = i; return null; }
stream.pos = l;
return "trailingspace";
},
name: "trailingspace"
});
});
});

View File

@ -0,0 +1,105 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.registerHelper("fold", "brace", function(cm, start) {
var line = start.line, lineText = cm.getLine(line);
var tokenType;
function findOpening(openCh) {
for (var at = start.ch, pass = 0;;) {
var found = at <= 0 ? -1 : lineText.lastIndexOf(openCh, at - 1);
if (found == -1) {
if (pass == 1) break;
pass = 1;
at = lineText.length;
continue;
}
if (pass == 1 && found < start.ch) break;
tokenType = cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1));
if (!/^(comment|string)/.test(tokenType)) return found + 1;
at = found - 1;
}
}
var startToken = "{", endToken = "}", startCh = findOpening("{");
if (startCh == null) {
startToken = "[", endToken = "]";
startCh = findOpening("[");
}
if (startCh == null) return;
var count = 1, lastLine = cm.lastLine(), end, endCh;
outer: for (var i = line; i <= lastLine; ++i) {
var text = cm.getLine(i), pos = i == line ? startCh : 0;
for (;;) {
var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, pos);
if (nextOpen < 0) nextOpen = text.length;
if (nextClose < 0) nextClose = text.length;
pos = Math.min(nextOpen, nextClose);
if (pos == text.length) break;
if (cm.getTokenTypeAt(CodeMirror.Pos(i, pos + 1)) == tokenType) {
if (pos == nextOpen) ++count;
else if (!--count) { end = i; endCh = pos; break outer; }
}
++pos;
}
}
if (end == null || line == end) return;
return {from: CodeMirror.Pos(line, startCh),
to: CodeMirror.Pos(end, endCh)};
});
CodeMirror.registerHelper("fold", "import", function(cm, start) {
function hasImport(line) {
if (line < cm.firstLine() || line > cm.lastLine()) return null;
var start = cm.getTokenAt(CodeMirror.Pos(line, 1));
if (!/\S/.test(start.string)) start = cm.getTokenAt(CodeMirror.Pos(line, start.end + 1));
if (start.type != "keyword" || start.string != "import") return null;
// Now find closing semicolon, return its position
for (var i = line, e = Math.min(cm.lastLine(), line + 10); i <= e; ++i) {
var text = cm.getLine(i), semi = text.indexOf(";");
if (semi != -1) return {startCh: start.end, end: CodeMirror.Pos(i, semi)};
}
}
var startLine = start.line, has = hasImport(startLine), prev;
if (!has || hasImport(startLine - 1) || ((prev = hasImport(startLine - 2)) && prev.end.line == startLine - 1))
return null;
for (var end = has.end;;) {
var next = hasImport(end.line + 1);
if (next == null) break;
end = next.end;
}
return {from: cm.clipPos(CodeMirror.Pos(startLine, has.startCh + 1)), to: end};
});
CodeMirror.registerHelper("fold", "include", function(cm, start) {
function hasInclude(line) {
if (line < cm.firstLine() || line > cm.lastLine()) return null;
var start = cm.getTokenAt(CodeMirror.Pos(line, 1));
if (!/\S/.test(start.string)) start = cm.getTokenAt(CodeMirror.Pos(line, start.end + 1));
if (start.type == "meta" && start.string.slice(0, 8) == "#include") return start.start + 8;
}
var startLine = start.line, has = hasInclude(startLine);
if (has == null || hasInclude(startLine - 1) != null) return null;
for (var end = startLine;;) {
var next = hasInclude(end + 1);
if (next == null) break;
++end;
}
return {from: CodeMirror.Pos(startLine, has + 1),
to: cm.clipPos(CodeMirror.Pos(end))};
});
});

View File

@ -0,0 +1,59 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.registerGlobalHelper("fold", "comment", function(mode) {
return mode.blockCommentStart && mode.blockCommentEnd;
}, function(cm, start) {
var mode = cm.getModeAt(start), startToken = mode.blockCommentStart, endToken = mode.blockCommentEnd;
if (!startToken || !endToken) return;
var line = start.line, lineText = cm.getLine(line);
var startCh;
for (var at = start.ch, pass = 0;;) {
var found = at <= 0 ? -1 : lineText.lastIndexOf(startToken, at - 1);
if (found == -1) {
if (pass == 1) return;
pass = 1;
at = lineText.length;
continue;
}
if (pass == 1 && found < start.ch) return;
if (/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1))) &&
(found == 0 || lineText.slice(found - endToken.length, found) == endToken ||
!/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found))))) {
startCh = found + startToken.length;
break;
}
at = found - 1;
}
var depth = 1, lastLine = cm.lastLine(), end, endCh;
outer: for (var i = line; i <= lastLine; ++i) {
var text = cm.getLine(i), pos = i == line ? startCh : 0;
for (;;) {
var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, pos);
if (nextOpen < 0) nextOpen = text.length;
if (nextClose < 0) nextClose = text.length;
pos = Math.min(nextOpen, nextClose);
if (pos == text.length) break;
if (pos == nextOpen) ++depth;
else if (!--depth) { end = i; endCh = pos; break outer; }
++pos;
}
}
if (end == null || line == end && endCh == startCh) return;
return {from: CodeMirror.Pos(line, startCh),
to: CodeMirror.Pos(end, endCh)};
});
});

View File

@ -0,0 +1,157 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
function doFold(cm, pos, options, force) {
if (options && options.call) {
var finder = options;
options = null;
} else {
var finder = getOption(cm, options, "rangeFinder");
}
if (typeof pos == "number") pos = CodeMirror.Pos(pos, 0);
var minSize = getOption(cm, options, "minFoldSize");
function getRange(allowFolded) {
var range = finder(cm, pos);
if (!range || range.to.line - range.from.line < minSize) return null;
var marks = cm.findMarksAt(range.from);
for (var i = 0; i < marks.length; ++i) {
if (marks[i].__isFold && force !== "fold") {
if (!allowFolded) return null;
range.cleared = true;
marks[i].clear();
}
}
return range;
}
var range = getRange(true);
if (getOption(cm, options, "scanUp")) while (!range && pos.line > cm.firstLine()) {
pos = CodeMirror.Pos(pos.line - 1, 0);
range = getRange(false);
}
if (!range || range.cleared || force === "unfold") return;
var myWidget = makeWidget(cm, options, range);
CodeMirror.on(myWidget, "mousedown", function(e) {
myRange.clear();
CodeMirror.e_preventDefault(e);
});
var myRange = cm.markText(range.from, range.to, {
replacedWith: myWidget,
clearOnEnter: getOption(cm, options, "clearOnEnter"),
__isFold: true
});
myRange.on("clear", function(from, to) {
CodeMirror.signal(cm, "unfold", cm, from, to);
});
CodeMirror.signal(cm, "fold", cm, range.from, range.to);
}
function makeWidget(cm, options, range) {
var widget = getOption(cm, options, "widget");
if (typeof widget == "function") {
widget = widget(range.from, range.to);
}
if (typeof widget == "string") {
var text = document.createTextNode(widget);
widget = document.createElement("span");
widget.appendChild(text);
widget.className = "CodeMirror-foldmarker";
} else if (widget) {
widget = widget.cloneNode(true)
}
return widget;
}
// Clumsy backwards-compatible interface
CodeMirror.newFoldFunction = function(rangeFinder, widget) {
return function(cm, pos) { doFold(cm, pos, {rangeFinder: rangeFinder, widget: widget}); };
};
// New-style interface
CodeMirror.defineExtension("foldCode", function(pos, options, force) {
doFold(this, pos, options, force);
});
CodeMirror.defineExtension("isFolded", function(pos) {
var marks = this.findMarksAt(pos);
for (var i = 0; i < marks.length; ++i)
if (marks[i].__isFold) return true;
});
CodeMirror.commands.toggleFold = function(cm) {
cm.foldCode(cm.getCursor());
};
CodeMirror.commands.fold = function(cm) {
cm.foldCode(cm.getCursor(), null, "fold");
};
CodeMirror.commands.unfold = function(cm) {
cm.foldCode(cm.getCursor(), null, "unfold");
};
CodeMirror.commands.foldAll = function(cm) {
cm.operation(function() {
for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
cm.foldCode(CodeMirror.Pos(i, 0), null, "fold");
});
};
CodeMirror.commands.unfoldAll = function(cm) {
cm.operation(function() {
for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
cm.foldCode(CodeMirror.Pos(i, 0), null, "unfold");
});
};
CodeMirror.registerHelper("fold", "combine", function() {
var funcs = Array.prototype.slice.call(arguments, 0);
return function(cm, start) {
for (var i = 0; i < funcs.length; ++i) {
var found = funcs[i](cm, start);
if (found) return found;
}
};
});
CodeMirror.registerHelper("fold", "auto", function(cm, start) {
var helpers = cm.getHelpers(start, "fold");
for (var i = 0; i < helpers.length; i++) {
var cur = helpers[i](cm, start);
if (cur) return cur;
}
});
var defaultOptions = {
rangeFinder: CodeMirror.fold.auto,
widget: "\u2194",
minFoldSize: 0,
scanUp: false,
clearOnEnter: true
};
CodeMirror.defineOption("foldOptions", null);
function getOption(cm, options, name) {
if (options && options[name] !== undefined)
return options[name];
var editorOptions = cm.options.foldOptions;
if (editorOptions && editorOptions[name] !== undefined)
return editorOptions[name];
return defaultOptions[name];
}
CodeMirror.defineExtension("foldOption", function(options, name) {
return getOption(this, options, name);
});
});

View File

@ -0,0 +1,20 @@
.CodeMirror-foldmarker {
color: blue;
text-shadow: #b9f 1px 1px 2px, #b9f -1px -1px 2px, #b9f 1px -1px 2px, #b9f -1px 1px 2px;
font-family: arial;
line-height: .3;
cursor: pointer;
}
.CodeMirror-foldgutter {
width: .7em;
}
.CodeMirror-foldgutter-open,
.CodeMirror-foldgutter-folded {
cursor: pointer;
}
.CodeMirror-foldgutter-open:after {
content: "\25BE";
}
.CodeMirror-foldgutter-folded:after {
content: "\25B8";
}

View File

@ -0,0 +1,163 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("./foldcode"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "./foldcode"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineOption("foldGutter", false, function(cm, val, old) {
if (old && old != CodeMirror.Init) {
cm.clearGutter(cm.state.foldGutter.options.gutter);
cm.state.foldGutter = null;
cm.off("gutterClick", onGutterClick);
cm.off("changes", onChange);
cm.off("viewportChange", onViewportChange);
cm.off("fold", onFold);
cm.off("unfold", onFold);
cm.off("swapDoc", onChange);
}
if (val) {
cm.state.foldGutter = new State(parseOptions(val));
updateInViewport(cm);
cm.on("gutterClick", onGutterClick);
cm.on("changes", onChange);
cm.on("viewportChange", onViewportChange);
cm.on("fold", onFold);
cm.on("unfold", onFold);
cm.on("swapDoc", onChange);
}
});
var Pos = CodeMirror.Pos;
function State(options) {
this.options = options;
this.from = this.to = 0;
}
function parseOptions(opts) {
if (opts === true) opts = {};
if (opts.gutter == null) opts.gutter = "CodeMirror-foldgutter";
if (opts.indicatorOpen == null) opts.indicatorOpen = "CodeMirror-foldgutter-open";
if (opts.indicatorFolded == null) opts.indicatorFolded = "CodeMirror-foldgutter-folded";
return opts;
}
function isFolded(cm, line) {
var marks = cm.findMarks(Pos(line, 0), Pos(line + 1, 0));
for (var i = 0; i < marks.length; ++i) {
if (marks[i].__isFold) {
var fromPos = marks[i].find(-1);
if (fromPos && fromPos.line === line)
return marks[i];
}
}
}
function marker(spec) {
if (typeof spec == "string") {
var elt = document.createElement("div");
elt.className = spec + " CodeMirror-guttermarker-subtle";
return elt;
} else {
return spec.cloneNode(true);
}
}
function updateFoldInfo(cm, from, to) {
var opts = cm.state.foldGutter.options, cur = from - 1;
var minSize = cm.foldOption(opts, "minFoldSize");
var func = cm.foldOption(opts, "rangeFinder");
// we can reuse the built-in indicator element if its className matches the new state
var clsFolded = typeof opts.indicatorFolded == "string" && classTest(opts.indicatorFolded);
var clsOpen = typeof opts.indicatorOpen == "string" && classTest(opts.indicatorOpen);
cm.eachLine(from, to, function(line) {
++cur;
var mark = null;
var old = line.gutterMarkers;
if (old) old = old[opts.gutter];
if (isFolded(cm, cur)) {
if (clsFolded && old && clsFolded.test(old.className)) return;
mark = marker(opts.indicatorFolded);
} else {
var pos = Pos(cur, 0);
var range = func && func(cm, pos);
if (range && range.to.line - range.from.line >= minSize) {
if (clsOpen && old && clsOpen.test(old.className)) return;
mark = marker(opts.indicatorOpen);
}
}
if (!mark && !old) return;
cm.setGutterMarker(line, opts.gutter, mark);
});
}
// copied from CodeMirror/src/util/dom.js
function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") }
function updateInViewport(cm) {
var vp = cm.getViewport(), state = cm.state.foldGutter;
if (!state) return;
cm.operation(function() {
updateFoldInfo(cm, vp.from, vp.to);
});
state.from = vp.from; state.to = vp.to;
}
function onGutterClick(cm, line, gutter) {
var state = cm.state.foldGutter;
if (!state) return;
var opts = state.options;
if (gutter != opts.gutter) return;
var folded = isFolded(cm, line);
if (folded) folded.clear();
else cm.foldCode(Pos(line, 0), opts);
}
function onChange(cm) {
var state = cm.state.foldGutter;
if (!state) return;
var opts = state.options;
state.from = state.to = 0;
clearTimeout(state.changeUpdate);
state.changeUpdate = setTimeout(function() { updateInViewport(cm); }, opts.foldOnChangeTimeSpan || 600);
}
function onViewportChange(cm) {
var state = cm.state.foldGutter;
if (!state) return;
var opts = state.options;
clearTimeout(state.changeUpdate);
state.changeUpdate = setTimeout(function() {
var vp = cm.getViewport();
if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) {
updateInViewport(cm);
} else {
cm.operation(function() {
if (vp.from < state.from) {
updateFoldInfo(cm, vp.from, state.from);
state.from = vp.from;
}
if (vp.to > state.to) {
updateFoldInfo(cm, state.to, vp.to);
state.to = vp.to;
}
});
}
}, opts.updateViewportTimeSpan || 400);
}
function onFold(cm, from) {
var state = cm.state.foldGutter;
if (!state) return;
var line = from.line;
if (line >= state.from && line < state.to)
updateFoldInfo(cm, line, line + 1);
}
});

View File

@ -0,0 +1,48 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
function lineIndent(cm, lineNo) {
var text = cm.getLine(lineNo)
var spaceTo = text.search(/\S/)
if (spaceTo == -1 || /\bcomment\b/.test(cm.getTokenTypeAt(CodeMirror.Pos(lineNo, spaceTo + 1))))
return -1
return CodeMirror.countColumn(text, null, cm.getOption("tabSize"))
}
CodeMirror.registerHelper("fold", "indent", function(cm, start) {
var myIndent = lineIndent(cm, start.line)
if (myIndent < 0) return
var lastLineInFold = null
// Go through lines until we find a line that definitely doesn't belong in
// the block we're folding, or to the end.
for (var i = start.line + 1, end = cm.lastLine(); i <= end; ++i) {
var indent = lineIndent(cm, i)
if (indent == -1) {
} else if (indent > myIndent) {
// Lines with a greater indent are considered part of the block.
lastLineInFold = i;
} else {
// If this line has non-space, non-comment content, and is
// indented less or equal to the start line, it is the start of
// another block.
break;
}
}
if (lastLineInFold) return {
from: CodeMirror.Pos(start.line, cm.getLine(start.line).length),
to: CodeMirror.Pos(lastLineInFold, cm.getLine(lastLineInFold).length)
};
});
});

View File

@ -0,0 +1,49 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.registerHelper("fold", "markdown", function(cm, start) {
var maxDepth = 100;
function isHeader(lineNo) {
var tokentype = cm.getTokenTypeAt(CodeMirror.Pos(lineNo, 0));
return tokentype && /\bheader\b/.test(tokentype);
}
function headerLevel(lineNo, line, nextLine) {
var match = line && line.match(/^#+/);
if (match && isHeader(lineNo)) return match[0].length;
match = nextLine && nextLine.match(/^[=\-]+\s*$/);
if (match && isHeader(lineNo + 1)) return nextLine[0] == "=" ? 1 : 2;
return maxDepth;
}
var firstLine = cm.getLine(start.line), nextLine = cm.getLine(start.line + 1);
var level = headerLevel(start.line, firstLine, nextLine);
if (level === maxDepth) return undefined;
var lastLineNo = cm.lastLine();
var end = start.line, nextNextLine = cm.getLine(end + 2);
while (end < lastLineNo) {
if (headerLevel(end + 1, nextLine, nextNextLine) <= level) break;
++end;
nextLine = nextNextLine;
nextNextLine = cm.getLine(end + 2);
}
return {
from: CodeMirror.Pos(start.line, firstLine.length),
to: CodeMirror.Pos(end, cm.getLine(end).length)
};
});
});

View File

@ -0,0 +1,184 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var Pos = CodeMirror.Pos;
function cmp(a, b) { return a.line - b.line || a.ch - b.ch; }
var nameStartChar = "A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
var nameChar = nameStartChar + "\-\:\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
var xmlTagStart = new RegExp("<(/?)([" + nameStartChar + "][" + nameChar + "]*)", "g");
function Iter(cm, line, ch, range) {
this.line = line; this.ch = ch;
this.cm = cm; this.text = cm.getLine(line);
this.min = range ? Math.max(range.from, cm.firstLine()) : cm.firstLine();
this.max = range ? Math.min(range.to - 1, cm.lastLine()) : cm.lastLine();
}
function tagAt(iter, ch) {
var type = iter.cm.getTokenTypeAt(Pos(iter.line, ch));
return type && /\btag\b/.test(type);
}
function nextLine(iter) {
if (iter.line >= iter.max) return;
iter.ch = 0;
iter.text = iter.cm.getLine(++iter.line);
return true;
}
function prevLine(iter) {
if (iter.line <= iter.min) return;
iter.text = iter.cm.getLine(--iter.line);
iter.ch = iter.text.length;
return true;
}
function toTagEnd(iter) {
for (;;) {
var gt = iter.text.indexOf(">", iter.ch);
if (gt == -1) { if (nextLine(iter)) continue; else return; }
if (!tagAt(iter, gt + 1)) { iter.ch = gt + 1; continue; }
var lastSlash = iter.text.lastIndexOf("/", gt);
var selfClose = lastSlash > -1 && !/\S/.test(iter.text.slice(lastSlash + 1, gt));
iter.ch = gt + 1;
return selfClose ? "selfClose" : "regular";
}
}
function toTagStart(iter) {
for (;;) {
var lt = iter.ch ? iter.text.lastIndexOf("<", iter.ch - 1) : -1;
if (lt == -1) { if (prevLine(iter)) continue; else return; }
if (!tagAt(iter, lt + 1)) { iter.ch = lt; continue; }
xmlTagStart.lastIndex = lt;
iter.ch = lt;
var match = xmlTagStart.exec(iter.text);
if (match && match.index == lt) return match;
}
}
function toNextTag(iter) {
for (;;) {
xmlTagStart.lastIndex = iter.ch;
var found = xmlTagStart.exec(iter.text);
if (!found) { if (nextLine(iter)) continue; else return; }
if (!tagAt(iter, found.index + 1)) { iter.ch = found.index + 1; continue; }
iter.ch = found.index + found[0].length;
return found;
}
}
function toPrevTag(iter) {
for (;;) {
var gt = iter.ch ? iter.text.lastIndexOf(">", iter.ch - 1) : -1;
if (gt == -1) { if (prevLine(iter)) continue; else return; }
if (!tagAt(iter, gt + 1)) { iter.ch = gt; continue; }
var lastSlash = iter.text.lastIndexOf("/", gt);
var selfClose = lastSlash > -1 && !/\S/.test(iter.text.slice(lastSlash + 1, gt));
iter.ch = gt + 1;
return selfClose ? "selfClose" : "regular";
}
}
function findMatchingClose(iter, tag) {
var stack = [];
for (;;) {
var next = toNextTag(iter), end, startLine = iter.line, startCh = iter.ch - (next ? next[0].length : 0);
if (!next || !(end = toTagEnd(iter))) return;
if (end == "selfClose") continue;
if (next[1]) { // closing tag
for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == next[2]) {
stack.length = i;
break;
}
if (i < 0 && (!tag || tag == next[2])) return {
tag: next[2],
from: Pos(startLine, startCh),
to: Pos(iter.line, iter.ch)
};
} else { // opening tag
stack.push(next[2]);
}
}
}
function findMatchingOpen(iter, tag) {
var stack = [];
for (;;) {
var prev = toPrevTag(iter);
if (!prev) return;
if (prev == "selfClose") { toTagStart(iter); continue; }
var endLine = iter.line, endCh = iter.ch;
var start = toTagStart(iter);
if (!start) return;
if (start[1]) { // closing tag
stack.push(start[2]);
} else { // opening tag
for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == start[2]) {
stack.length = i;
break;
}
if (i < 0 && (!tag || tag == start[2])) return {
tag: start[2],
from: Pos(iter.line, iter.ch),
to: Pos(endLine, endCh)
};
}
}
}
CodeMirror.registerHelper("fold", "xml", function(cm, start) {
var iter = new Iter(cm, start.line, 0);
for (;;) {
var openTag = toNextTag(iter)
if (!openTag || iter.line != start.line) return
var end = toTagEnd(iter)
if (!end) return
if (!openTag[1] && end != "selfClose") {
var startPos = Pos(iter.line, iter.ch);
var endPos = findMatchingClose(iter, openTag[2]);
return endPos && cmp(endPos.from, startPos) > 0 ? {from: startPos, to: endPos.from} : null
}
}
});
CodeMirror.findMatchingTag = function(cm, pos, range) {
var iter = new Iter(cm, pos.line, pos.ch, range);
if (iter.text.indexOf(">") == -1 && iter.text.indexOf("<") == -1) return;
var end = toTagEnd(iter), to = end && Pos(iter.line, iter.ch);
var start = end && toTagStart(iter);
if (!end || !start || cmp(iter, pos) > 0) return;
var here = {from: Pos(iter.line, iter.ch), to: to, tag: start[2]};
if (end == "selfClose") return {open: here, close: null, at: "open"};
if (start[1]) { // closing tag
return {open: findMatchingOpen(iter, start[2]), close: here, at: "close"};
} else { // opening tag
iter = new Iter(cm, to.line, to.ch, range);
return {open: here, close: findMatchingClose(iter, start[2]), at: "open"};
}
};
CodeMirror.findEnclosingTag = function(cm, pos, range, tag) {
var iter = new Iter(cm, pos.line, pos.ch, range);
for (;;) {
var open = findMatchingOpen(iter, tag);
if (!open) break;
var forward = new Iter(cm, pos.line, pos.ch, range);
var close = findMatchingClose(forward, open.tag);
if (close) return {open: open, close: close};
}
};
// Used by addon/edit/closetag.js
CodeMirror.scanForClosingTag = function(cm, pos, name, end) {
var iter = new Iter(cm, pos.line, pos.ch, end ? {from: 0, to: end} : null);
return findMatchingClose(iter, name);
};
});

View File

@ -0,0 +1,41 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var WORD = /[\w$]+/, RANGE = 500;
CodeMirror.registerHelper("hint", "anyword", function(editor, options) {
var word = options && options.word || WORD;
var range = options && options.range || RANGE;
var cur = editor.getCursor(), curLine = editor.getLine(cur.line);
var end = cur.ch, start = end;
while (start && word.test(curLine.charAt(start - 1))) --start;
var curWord = start != end && curLine.slice(start, end);
var list = options && options.list || [], seen = {};
var re = new RegExp(word.source, "g");
for (var dir = -1; dir <= 1; dir += 2) {
var line = cur.line, endLine = Math.min(Math.max(line + dir * range, editor.firstLine()), editor.lastLine()) + dir;
for (; line != endLine; line += dir) {
var text = editor.getLine(line), m;
while (m = re.exec(text)) {
if (line == cur.line && m[0] === curWord) continue;
if ((!curWord || m[0].lastIndexOf(curWord, 0) == 0) && !Object.prototype.hasOwnProperty.call(seen, m[0])) {
seen[m[0]] = true;
list.push(m[0]);
}
}
}
}
return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)};
});
});

View File

@ -0,0 +1,66 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../../mode/css/css"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "../../mode/css/css"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var pseudoClasses = {"active":1, "after":1, "before":1, "checked":1, "default":1,
"disabled":1, "empty":1, "enabled":1, "first-child":1, "first-letter":1,
"first-line":1, "first-of-type":1, "focus":1, "hover":1, "in-range":1,
"indeterminate":1, "invalid":1, "lang":1, "last-child":1, "last-of-type":1,
"link":1, "not":1, "nth-child":1, "nth-last-child":1, "nth-last-of-type":1,
"nth-of-type":1, "only-of-type":1, "only-child":1, "optional":1, "out-of-range":1,
"placeholder":1, "read-only":1, "read-write":1, "required":1, "root":1,
"selection":1, "target":1, "valid":1, "visited":1
};
CodeMirror.registerHelper("hint", "css", function(cm) {
var cur = cm.getCursor(), token = cm.getTokenAt(cur);
var inner = CodeMirror.innerMode(cm.getMode(), token.state);
if (inner.mode.name != "css") return;
if (token.type == "keyword" && "!important".indexOf(token.string) == 0)
return {list: ["!important"], from: CodeMirror.Pos(cur.line, token.start),
to: CodeMirror.Pos(cur.line, token.end)};
var start = token.start, end = cur.ch, word = token.string.slice(0, end - start);
if (/[^\w$_-]/.test(word)) {
word = ""; start = end = cur.ch;
}
var spec = CodeMirror.resolveMode("text/css");
var result = [];
function add(keywords) {
for (var name in keywords)
if (!word || name.lastIndexOf(word, 0) == 0)
result.push(name);
}
var st = inner.state.state;
if (st == "pseudo" || token.type == "variable-3") {
add(pseudoClasses);
} else if (st == "block" || st == "maybeprop") {
add(spec.propertyKeywords);
} else if (st == "prop" || st == "parens" || st == "at" || st == "params") {
add(spec.valueKeywords);
add(spec.colorKeywords);
} else if (st == "media" || st == "media_parens") {
add(spec.mediaTypes);
add(spec.mediaFeatures);
}
if (result.length) return {
list: result,
from: CodeMirror.Pos(cur.line, start),
to: CodeMirror.Pos(cur.line, end)
};
});
});

View File

@ -0,0 +1,350 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("./xml-hint"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "./xml-hint"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var langs = "ab aa af ak sq am ar an hy as av ae ay az bm ba eu be bn bh bi bs br bg my ca ch ce ny zh cv kw co cr hr cs da dv nl dz en eo et ee fo fj fi fr ff gl ka de el gn gu ht ha he hz hi ho hu ia id ie ga ig ik io is it iu ja jv kl kn kr ks kk km ki rw ky kv kg ko ku kj la lb lg li ln lo lt lu lv gv mk mg ms ml mt mi mr mh mn na nv nb nd ne ng nn no ii nr oc oj cu om or os pa pi fa pl ps pt qu rm rn ro ru sa sc sd se sm sg sr gd sn si sk sl so st es su sw ss sv ta te tg th ti bo tk tl tn to tr ts tt tw ty ug uk ur uz ve vi vo wa cy wo fy xh yi yo za zu".split(" ");
var targets = ["_blank", "_self", "_top", "_parent"];
var charsets = ["ascii", "utf-8", "utf-16", "latin1", "latin1"];
var methods = ["get", "post", "put", "delete"];
var encs = ["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"];
var media = ["all", "screen", "print", "embossed", "braille", "handheld", "print", "projection", "screen", "tty", "tv", "speech",
"3d-glasses", "resolution [>][<][=] [X]", "device-aspect-ratio: X/Y", "orientation:portrait",
"orientation:landscape", "device-height: [X]", "device-width: [X]"];
var s = { attrs: {} }; // Simple tag, reused for a whole lot of tags
var data = {
a: {
attrs: {
href: null, ping: null, type: null,
media: media,
target: targets,
hreflang: langs
}
},
abbr: s,
acronym: s,
address: s,
applet: s,
area: {
attrs: {
alt: null, coords: null, href: null, target: null, ping: null,
media: media, hreflang: langs, type: null,
shape: ["default", "rect", "circle", "poly"]
}
},
article: s,
aside: s,
audio: {
attrs: {
src: null, mediagroup: null,
crossorigin: ["anonymous", "use-credentials"],
preload: ["none", "metadata", "auto"],
autoplay: ["", "autoplay"],
loop: ["", "loop"],
controls: ["", "controls"]
}
},
b: s,
base: { attrs: { href: null, target: targets } },
basefont: s,
bdi: s,
bdo: s,
big: s,
blockquote: { attrs: { cite: null } },
body: s,
br: s,
button: {
attrs: {
form: null, formaction: null, name: null, value: null,
autofocus: ["", "autofocus"],
disabled: ["", "autofocus"],
formenctype: encs,
formmethod: methods,
formnovalidate: ["", "novalidate"],
formtarget: targets,
type: ["submit", "reset", "button"]
}
},
canvas: { attrs: { width: null, height: null } },
caption: s,
center: s,
cite: s,
code: s,
col: { attrs: { span: null } },
colgroup: { attrs: { span: null } },
command: {
attrs: {
type: ["command", "checkbox", "radio"],
label: null, icon: null, radiogroup: null, command: null, title: null,
disabled: ["", "disabled"],
checked: ["", "checked"]
}
},
data: { attrs: { value: null } },
datagrid: { attrs: { disabled: ["", "disabled"], multiple: ["", "multiple"] } },
datalist: { attrs: { data: null } },
dd: s,
del: { attrs: { cite: null, datetime: null } },
details: { attrs: { open: ["", "open"] } },
dfn: s,
dir: s,
div: s,
dl: s,
dt: s,
em: s,
embed: { attrs: { src: null, type: null, width: null, height: null } },
eventsource: { attrs: { src: null } },
fieldset: { attrs: { disabled: ["", "disabled"], form: null, name: null } },
figcaption: s,
figure: s,
font: s,
footer: s,
form: {
attrs: {
action: null, name: null,
"accept-charset": charsets,
autocomplete: ["on", "off"],
enctype: encs,
method: methods,
novalidate: ["", "novalidate"],
target: targets
}
},
frame: s,
frameset: s,
h1: s, h2: s, h3: s, h4: s, h5: s, h6: s,
head: {
attrs: {},
children: ["title", "base", "link", "style", "meta", "script", "noscript", "command"]
},
header: s,
hgroup: s,
hr: s,
html: {
attrs: { manifest: null },
children: ["head", "body"]
},
i: s,
iframe: {
attrs: {
src: null, srcdoc: null, name: null, width: null, height: null,
sandbox: ["allow-top-navigation", "allow-same-origin", "allow-forms", "allow-scripts"],
seamless: ["", "seamless"]
}
},
img: {
attrs: {
alt: null, src: null, ismap: null, usemap: null, width: null, height: null,
crossorigin: ["anonymous", "use-credentials"]
}
},
input: {
attrs: {
alt: null, dirname: null, form: null, formaction: null,
height: null, list: null, max: null, maxlength: null, min: null,
name: null, pattern: null, placeholder: null, size: null, src: null,
step: null, value: null, width: null,
accept: ["audio/*", "video/*", "image/*"],
autocomplete: ["on", "off"],
autofocus: ["", "autofocus"],
checked: ["", "checked"],
disabled: ["", "disabled"],
formenctype: encs,
formmethod: methods,
formnovalidate: ["", "novalidate"],
formtarget: targets,
multiple: ["", "multiple"],
readonly: ["", "readonly"],
required: ["", "required"],
type: ["hidden", "text", "search", "tel", "url", "email", "password", "datetime", "date", "month",
"week", "time", "datetime-local", "number", "range", "color", "checkbox", "radio",
"file", "submit", "image", "reset", "button"]
}
},
ins: { attrs: { cite: null, datetime: null } },
kbd: s,
keygen: {
attrs: {
challenge: null, form: null, name: null,
autofocus: ["", "autofocus"],
disabled: ["", "disabled"],
keytype: ["RSA"]
}
},
label: { attrs: { "for": null, form: null } },
legend: s,
li: { attrs: { value: null } },
link: {
attrs: {
href: null, type: null,
hreflang: langs,
media: media,
sizes: ["all", "16x16", "16x16 32x32", "16x16 32x32 64x64"]
}
},
map: { attrs: { name: null } },
mark: s,
menu: { attrs: { label: null, type: ["list", "context", "toolbar"] } },
meta: {
attrs: {
content: null,
charset: charsets,
name: ["viewport", "application-name", "author", "description", "generator", "keywords"],
"http-equiv": ["content-language", "content-type", "default-style", "refresh"]
}
},
meter: { attrs: { value: null, min: null, low: null, high: null, max: null, optimum: null } },
nav: s,
noframes: s,
noscript: s,
object: {
attrs: {
data: null, type: null, name: null, usemap: null, form: null, width: null, height: null,
typemustmatch: ["", "typemustmatch"]
}
},
ol: { attrs: { reversed: ["", "reversed"], start: null, type: ["1", "a", "A", "i", "I"] } },
optgroup: { attrs: { disabled: ["", "disabled"], label: null } },
option: { attrs: { disabled: ["", "disabled"], label: null, selected: ["", "selected"], value: null } },
output: { attrs: { "for": null, form: null, name: null } },
p: s,
param: { attrs: { name: null, value: null } },
pre: s,
progress: { attrs: { value: null, max: null } },
q: { attrs: { cite: null } },
rp: s,
rt: s,
ruby: s,
s: s,
samp: s,
script: {
attrs: {
type: ["text/javascript"],
src: null,
async: ["", "async"],
defer: ["", "defer"],
charset: charsets
}
},
section: s,
select: {
attrs: {
form: null, name: null, size: null,
autofocus: ["", "autofocus"],
disabled: ["", "disabled"],
multiple: ["", "multiple"]
}
},
small: s,
source: { attrs: { src: null, type: null, media: null } },
span: s,
strike: s,
strong: s,
style: {
attrs: {
type: ["text/css"],
media: media,
scoped: null
}
},
sub: s,
summary: s,
sup: s,
table: s,
tbody: s,
td: { attrs: { colspan: null, rowspan: null, headers: null } },
textarea: {
attrs: {
dirname: null, form: null, maxlength: null, name: null, placeholder: null,
rows: null, cols: null,
autofocus: ["", "autofocus"],
disabled: ["", "disabled"],
readonly: ["", "readonly"],
required: ["", "required"],
wrap: ["soft", "hard"]
}
},
tfoot: s,
th: { attrs: { colspan: null, rowspan: null, headers: null, scope: ["row", "col", "rowgroup", "colgroup"] } },
thead: s,
time: { attrs: { datetime: null } },
title: s,
tr: s,
track: {
attrs: {
src: null, label: null, "default": null,
kind: ["subtitles", "captions", "descriptions", "chapters", "metadata"],
srclang: langs
}
},
tt: s,
u: s,
ul: s,
"var": s,
video: {
attrs: {
src: null, poster: null, width: null, height: null,
crossorigin: ["anonymous", "use-credentials"],
preload: ["auto", "metadata", "none"],
autoplay: ["", "autoplay"],
mediagroup: ["movie"],
muted: ["", "muted"],
controls: ["", "controls"]
}
},
wbr: s
};
var globalAttrs = {
accesskey: ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"],
"class": null,
contenteditable: ["true", "false"],
contextmenu: null,
dir: ["ltr", "rtl", "auto"],
draggable: ["true", "false", "auto"],
dropzone: ["copy", "move", "link", "string:", "file:"],
hidden: ["hidden"],
id: null,
inert: ["inert"],
itemid: null,
itemprop: null,
itemref: null,
itemscope: ["itemscope"],
itemtype: null,
lang: ["en", "es"],
spellcheck: ["true", "false"],
autocorrect: ["true", "false"],
autocapitalize: ["true", "false"],
style: null,
tabindex: ["1", "2", "3", "4", "5", "6", "7", "8", "9"],
title: null,
translate: ["yes", "no"],
onclick: null,
rel: ["stylesheet", "alternate", "author", "bookmark", "help", "license", "next", "nofollow", "noreferrer", "prefetch", "prev", "search", "tag"]
};
function populate(obj) {
for (var attr in globalAttrs) if (globalAttrs.hasOwnProperty(attr))
obj.attrs[attr] = globalAttrs[attr];
}
populate(s);
for (var tag in data) if (data.hasOwnProperty(tag) && data[tag] != s)
populate(data[tag]);
CodeMirror.htmlSchema = data;
function htmlHint(cm, options) {
var local = {schemaInfo: data};
if (options) for (var opt in options) local[opt] = options[opt];
return CodeMirror.hint.xml(cm, local);
}
CodeMirror.registerHelper("hint", "html", htmlHint);
});

View File

@ -0,0 +1,162 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
var Pos = CodeMirror.Pos;
function forEach(arr, f) {
for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
}
function arrayContains(arr, item) {
if (!Array.prototype.indexOf) {
var i = arr.length;
while (i--) {
if (arr[i] === item) {
return true;
}
}
return false;
}
return arr.indexOf(item) != -1;
}
function scriptHint(editor, keywords, getToken, options) {
// Find the token at the cursor
var cur = editor.getCursor(), token = getToken(editor, cur);
if (/\b(?:string|comment)\b/.test(token.type)) return;
var innerMode = CodeMirror.innerMode(editor.getMode(), token.state);
if (innerMode.mode.helperType === "json") return;
token.state = innerMode.state;
// If it's not a 'word-style' token, ignore the token.
if (!/^[\w$_]*$/.test(token.string)) {
token = {start: cur.ch, end: cur.ch, string: "", state: token.state,
type: token.string == "." ? "property" : null};
} else if (token.end > cur.ch) {
token.end = cur.ch;
token.string = token.string.slice(0, cur.ch - token.start);
}
var tprop = token;
// If it is a property, find out what it is a property of.
while (tprop.type == "property") {
tprop = getToken(editor, Pos(cur.line, tprop.start));
if (tprop.string != ".") return;
tprop = getToken(editor, Pos(cur.line, tprop.start));
if (!context) var context = [];
context.push(tprop);
}
return {list: getCompletions(token, context, keywords, options),
from: Pos(cur.line, token.start),
to: Pos(cur.line, token.end)};
}
function javascriptHint(editor, options) {
return scriptHint(editor, javascriptKeywords,
function (e, cur) {return e.getTokenAt(cur);},
options);
};
CodeMirror.registerHelper("hint", "javascript", javascriptHint);
function getCoffeeScriptToken(editor, cur) {
// This getToken, it is for coffeescript, imitates the behavior of
// getTokenAt method in javascript.js, that is, returning "property"
// type and treat "." as indepenent token.
var token = editor.getTokenAt(cur);
if (cur.ch == token.start + 1 && token.string.charAt(0) == '.') {
token.end = token.start;
token.string = '.';
token.type = "property";
}
else if (/^\.[\w$_]*$/.test(token.string)) {
token.type = "property";
token.start++;
token.string = token.string.replace(/\./, '');
}
return token;
}
function coffeescriptHint(editor, options) {
return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken, options);
}
CodeMirror.registerHelper("hint", "coffeescript", coffeescriptHint);
var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " +
"toUpperCase toLowerCase split concat match replace search").split(" ");
var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " +
"lastIndexOf every some filter forEach map reduce reduceRight ").split(" ");
var funcProps = "prototype apply call bind".split(" ");
var javascriptKeywords = ("break case catch class const continue debugger default delete do else export extends false finally for function " +
"if in import instanceof new null return super switch this throw true try typeof var void while with yield").split(" ");
var coffeescriptKeywords = ("and break catch class continue delete do else extends false finally for " +
"if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" ");
function forAllProps(obj, callback) {
if (!Object.getOwnPropertyNames || !Object.getPrototypeOf) {
for (var name in obj) callback(name)
} else {
for (var o = obj; o; o = Object.getPrototypeOf(o))
Object.getOwnPropertyNames(o).forEach(callback)
}
}
function getCompletions(token, context, keywords, options) {
var found = [], start = token.string, global = options && options.globalScope || window;
function maybeAdd(str) {
if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str);
}
function gatherCompletions(obj) {
if (typeof obj == "string") forEach(stringProps, maybeAdd);
else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
else if (obj instanceof Function) forEach(funcProps, maybeAdd);
forAllProps(obj, maybeAdd)
}
if (context && context.length) {
// If this is a property, see if it belongs to some object we can
// find in the current environment.
var obj = context.pop(), base;
if (obj.type && obj.type.indexOf("variable") === 0) {
if (options && options.additionalContext)
base = options.additionalContext[obj.string];
if (!options || options.useGlobalScope !== false)
base = base || global[obj.string];
} else if (obj.type == "string") {
base = "";
} else if (obj.type == "atom") {
base = 1;
} else if (obj.type == "function") {
if (global.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') &&
(typeof global.jQuery == 'function'))
base = global.jQuery();
else if (global._ != null && (obj.string == '_') && (typeof global._ == 'function'))
base = global._();
}
while (base != null && context.length)
base = base[context.pop().string];
if (base != null) gatherCompletions(base);
} else {
// If not, just look in the global object, any local scope, and optional additional-context
// (reading into JS mode internals to get at the local and global variables)
for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
for (var c = token.state.context; c; c = c.prev)
for (var v = c.vars; v; v = v.next) maybeAdd(v.name)
for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name);
if (options && options.additionalContext != null)
for (var key in options.additionalContext)
maybeAdd(key);
if (!options || options.useGlobalScope !== false)
gatherCompletions(global);
forEach(keywords, maybeAdd);
}
return found;
}
});

View File

@ -0,0 +1,36 @@
.CodeMirror-hints {
position: absolute;
z-index: 10;
overflow: hidden;
list-style: none;
margin: 0;
padding: 2px;
-webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
-moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
box-shadow: 2px 3px 5px rgba(0,0,0,.2);
border-radius: 3px;
border: 1px solid silver;
background: white;
font-size: 90%;
font-family: monospace;
max-height: 20em;
overflow-y: auto;
}
.CodeMirror-hint {
margin: 0;
padding: 0 4px;
border-radius: 2px;
white-space: pre;
color: black;
cursor: pointer;
}
li.CodeMirror-hint-active {
background: #08f;
color: white;
}

View File

@ -0,0 +1,479 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var HINT_ELEMENT_CLASS = "CodeMirror-hint";
var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active";
// This is the old interface, kept around for now to stay
// backwards-compatible.
CodeMirror.showHint = function(cm, getHints, options) {
if (!getHints) return cm.showHint(options);
if (options && options.async) getHints.async = true;
var newOpts = {hint: getHints};
if (options) for (var prop in options) newOpts[prop] = options[prop];
return cm.showHint(newOpts);
};
CodeMirror.defineExtension("showHint", function(options) {
options = parseOptions(this, this.getCursor("start"), options);
var selections = this.listSelections()
if (selections.length > 1) return;
// By default, don't allow completion when something is selected.
// A hint function can have a `supportsSelection` property to
// indicate that it can handle selections.
if (this.somethingSelected()) {
if (!options.hint.supportsSelection) return;
// Don't try with cross-line selections
for (var i = 0; i < selections.length; i++)
if (selections[i].head.line != selections[i].anchor.line) return;
}
if (this.state.completionActive) this.state.completionActive.close();
var completion = this.state.completionActive = new Completion(this, options);
if (!completion.options.hint) return;
CodeMirror.signal(this, "startCompletion", this);
completion.update(true);
});
CodeMirror.defineExtension("closeHint", function() {
if (this.state.completionActive) this.state.completionActive.close()
})
function Completion(cm, options) {
this.cm = cm;
this.options = options;
this.widget = null;
this.debounce = 0;
this.tick = 0;
this.startPos = this.cm.getCursor("start");
this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length;
var self = this;
cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
}
var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
return setTimeout(fn, 1000/60);
};
var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
Completion.prototype = {
close: function() {
if (!this.active()) return;
this.cm.state.completionActive = null;
this.tick = null;
this.cm.off("cursorActivity", this.activityFunc);
if (this.widget && this.data) CodeMirror.signal(this.data, "close");
if (this.widget) this.widget.close();
CodeMirror.signal(this.cm, "endCompletion", this.cm);
},
active: function() {
return this.cm.state.completionActive == this;
},
pick: function(data, i) {
var completion = data.list[i], self = this;
this.cm.operation(function() {
if (completion.hint)
completion.hint(self.cm, data, completion);
else
self.cm.replaceRange(getText(completion), completion.from || data.from,
completion.to || data.to, "complete");
CodeMirror.signal(data, "pick", completion);
self.cm.scrollIntoView();
})
this.close();
},
cursorActivity: function() {
if (this.debounce) {
cancelAnimationFrame(this.debounce);
this.debounce = 0;
}
var identStart = this.startPos;
if(this.data) {
identStart = this.data.from;
}
var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
pos.ch < identStart.ch || this.cm.somethingSelected() ||
(!pos.ch || this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
this.close();
} else {
var self = this;
this.debounce = requestAnimationFrame(function() {self.update();});
if (this.widget) this.widget.disable();
}
},
update: function(first) {
if (this.tick == null) return
var self = this, myTick = ++this.tick
fetchHints(this.options.hint, this.cm, this.options, function(data) {
if (self.tick == myTick) self.finishUpdate(data, first)
})
},
finishUpdate: function(data, first) {
if (this.data) CodeMirror.signal(this.data, "update");
var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
if (this.widget) this.widget.close();
this.data = data;
if (data && data.list.length) {
if (picked && data.list.length == 1) {
this.pick(data, 0);
} else {
this.widget = new Widget(this, data);
CodeMirror.signal(data, "shown");
}
}
}
};
function parseOptions(cm, pos, options) {
var editor = cm.options.hintOptions;
var out = {};
for (var prop in defaultOptions) out[prop] = defaultOptions[prop];
if (editor) for (var prop in editor)
if (editor[prop] !== undefined) out[prop] = editor[prop];
if (options) for (var prop in options)
if (options[prop] !== undefined) out[prop] = options[prop];
if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos)
return out;
}
function getText(completion) {
if (typeof completion == "string") return completion;
else return completion.text;
}
function buildKeyMap(completion, handle) {
var baseMap = {
Up: function() {handle.moveFocus(-1);},
Down: function() {handle.moveFocus(1);},
PageUp: function() {handle.moveFocus(-handle.menuSize() + 1, true);},
PageDown: function() {handle.moveFocus(handle.menuSize() - 1, true);},
Home: function() {handle.setFocus(0);},
End: function() {handle.setFocus(handle.length - 1);},
Enter: handle.pick,
Tab: handle.pick,
Esc: handle.close
};
var mac = /Mac/.test(navigator.platform);
if (mac) {
baseMap["Ctrl-P"] = function() {handle.moveFocus(-1);};
baseMap["Ctrl-N"] = function() {handle.moveFocus(1);};
}
var custom = completion.options.customKeys;
var ourMap = custom ? {} : baseMap;
function addBinding(key, val) {
var bound;
if (typeof val != "string")
bound = function(cm) { return val(cm, handle); };
// This mechanism is deprecated
else if (baseMap.hasOwnProperty(val))
bound = baseMap[val];
else
bound = val;
ourMap[key] = bound;
}
if (custom)
for (var key in custom) if (custom.hasOwnProperty(key))
addBinding(key, custom[key]);
var extra = completion.options.extraKeys;
if (extra)
for (var key in extra) if (extra.hasOwnProperty(key))
addBinding(key, extra[key]);
return ourMap;
}
function getHintElement(hintsElement, el) {
while (el && el != hintsElement) {
if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement) return el;
el = el.parentNode;
}
}
function Widget(completion, data) {
this.completion = completion;
this.data = data;
this.picked = false;
var widget = this, cm = completion.cm;
var ownerDocument = cm.getInputField().ownerDocument;
var parentWindow = ownerDocument.defaultView || ownerDocument.parentWindow;
var hints = this.hints = ownerDocument.createElement("ul");
var theme = completion.cm.options.theme;
hints.className = "CodeMirror-hints " + theme;
this.selectedHint = data.selectedHint || 0;
var completions = data.list;
for (var i = 0; i < completions.length; ++i) {
var elt = hints.appendChild(ownerDocument.createElement("li")), cur = completions[i];
var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS);
if (cur.className != null) className = cur.className + " " + className;
elt.className = className;
if (cur.render) cur.render(elt, data, cur);
else elt.appendChild(ownerDocument.createTextNode(cur.displayText || getText(cur)));
elt.hintId = i;
}
var container = completion.options.container || ownerDocument.body;
var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null);
var left = pos.left, top = pos.bottom, below = true;
var offsetLeft = 0, offsetTop = 0;
if (container !== ownerDocument.body) {
// We offset the cursor position because left and top are relative to the offsetParent's top left corner.
var isContainerPositioned = ['absolute', 'relative', 'fixed'].indexOf(parentWindow.getComputedStyle(container).position) !== -1;
var offsetParent = isContainerPositioned ? container : container.offsetParent;
var offsetParentPosition = offsetParent.getBoundingClientRect();
var bodyPosition = ownerDocument.body.getBoundingClientRect();
offsetLeft = (offsetParentPosition.left - bodyPosition.left - offsetParent.scrollLeft);
offsetTop = (offsetParentPosition.top - bodyPosition.top - offsetParent.scrollTop);
}
hints.style.left = (left - offsetLeft) + "px";
hints.style.top = (top - offsetTop) + "px";
// If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
var winW = parentWindow.innerWidth || Math.max(ownerDocument.body.offsetWidth, ownerDocument.documentElement.offsetWidth);
var winH = parentWindow.innerHeight || Math.max(ownerDocument.body.offsetHeight, ownerDocument.documentElement.offsetHeight);
container.appendChild(hints);
var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;
var scrolls = hints.scrollHeight > hints.clientHeight + 1
var startScroll = cm.getScrollInfo();
if (overlapY > 0) {
var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
if (curTop - height > 0) { // Fits above cursor
hints.style.top = (top = pos.top - height - offsetTop) + "px";
below = false;
} else if (height > winH) {
hints.style.height = (winH - 5) + "px";
hints.style.top = (top = pos.bottom - box.top - offsetTop) + "px";
var cursor = cm.getCursor();
if (data.from.ch != cursor.ch) {
pos = cm.cursorCoords(cursor);
hints.style.left = (left = pos.left - offsetLeft) + "px";
box = hints.getBoundingClientRect();
}
}
}
var overlapX = box.right - winW;
if (overlapX > 0) {
if (box.right - box.left > winW) {
hints.style.width = (winW - 5) + "px";
overlapX -= (box.right - box.left) - winW;
}
hints.style.left = (left = pos.left - overlapX - offsetLeft) + "px";
}
if (scrolls) for (var node = hints.firstChild; node; node = node.nextSibling)
node.style.paddingRight = cm.display.nativeBarWidth + "px"
cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
setFocus: function(n) { widget.changeActive(n); },
menuSize: function() { return widget.screenAmount(); },
length: completions.length,
close: function() { completion.close(); },
pick: function() { widget.pick(); },
data: data
}));
if (completion.options.closeOnUnfocus) {
var closingOnBlur;
cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); });
cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
}
cm.on("scroll", this.onScroll = function() {
var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
var newTop = top + startScroll.top - curScroll.top;
var point = newTop - (parentWindow.pageYOffset || (ownerDocument.documentElement || ownerDocument.body).scrollTop);
if (!below) point += hints.offsetHeight;
if (point <= editor.top || point >= editor.bottom) return completion.close();
hints.style.top = newTop + "px";
hints.style.left = (left + startScroll.left - curScroll.left) + "px";
});
CodeMirror.on(hints, "dblclick", function(e) {
var t = getHintElement(hints, e.target || e.srcElement);
if (t && t.hintId != null) {widget.changeActive(t.hintId); widget.pick();}
});
CodeMirror.on(hints, "click", function(e) {
var t = getHintElement(hints, e.target || e.srcElement);
if (t && t.hintId != null) {
widget.changeActive(t.hintId);
if (completion.options.completeOnSingleClick) widget.pick();
}
});
CodeMirror.on(hints, "mousedown", function() {
setTimeout(function(){cm.focus();}, 20);
});
this.scrollToActive()
CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]);
return true;
}
Widget.prototype = {
close: function() {
if (this.completion.widget != this) return;
this.completion.widget = null;
this.hints.parentNode.removeChild(this.hints);
this.completion.cm.removeKeyMap(this.keyMap);
var cm = this.completion.cm;
if (this.completion.options.closeOnUnfocus) {
cm.off("blur", this.onBlur);
cm.off("focus", this.onFocus);
}
cm.off("scroll", this.onScroll);
},
disable: function() {
this.completion.cm.removeKeyMap(this.keyMap);
var widget = this;
this.keyMap = {Enter: function() { widget.picked = true; }};
this.completion.cm.addKeyMap(this.keyMap);
},
pick: function() {
this.completion.pick(this.data, this.selectedHint);
},
changeActive: function(i, avoidWrap) {
if (i >= this.data.list.length)
i = avoidWrap ? this.data.list.length - 1 : 0;
else if (i < 0)
i = avoidWrap ? 0 : this.data.list.length - 1;
if (this.selectedHint == i) return;
var node = this.hints.childNodes[this.selectedHint];
if (node) node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
node = this.hints.childNodes[this.selectedHint = i];
node.className += " " + ACTIVE_HINT_ELEMENT_CLASS;
this.scrollToActive()
CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
},
scrollToActive: function() {
var margin = this.completion.options.scrollMargin || 0;
var node1 = this.hints.childNodes[Math.max(0, this.selectedHint - margin)];
var node2 = this.hints.childNodes[Math.min(this.data.list.length - 1, this.selectedHint + margin)];
var firstNode = this.hints.firstChild;
if (node1.offsetTop < this.hints.scrollTop)
this.hints.scrollTop = node1.offsetTop - firstNode.offsetTop;
else if (node2.offsetTop + node2.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
this.hints.scrollTop = node2.offsetTop + node2.offsetHeight - this.hints.clientHeight + firstNode.offsetTop;
},
screenAmount: function() {
return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
}
};
function applicableHelpers(cm, helpers) {
if (!cm.somethingSelected()) return helpers
var result = []
for (var i = 0; i < helpers.length; i++)
if (helpers[i].supportsSelection) result.push(helpers[i])
return result
}
function fetchHints(hint, cm, options, callback) {
if (hint.async) {
hint(cm, callback, options)
} else {
var result = hint(cm, options)
if (result && result.then) result.then(callback)
else callback(result)
}
}
function resolveAutoHints(cm, pos) {
var helpers = cm.getHelpers(pos, "hint"), words
if (helpers.length) {
var resolved = function(cm, callback, options) {
var app = applicableHelpers(cm, helpers);
function run(i) {
if (i == app.length) return callback(null)
fetchHints(app[i], cm, options, function(result) {
if (result && result.list.length > 0) callback(result)
else run(i + 1)
})
}
run(0)
}
resolved.async = true
resolved.supportsSelection = true
return resolved
} else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
return function(cm) { return CodeMirror.hint.fromList(cm, {words: words}) }
} else if (CodeMirror.hint.anyword) {
return function(cm, options) { return CodeMirror.hint.anyword(cm, options) }
} else {
return function() {}
}
}
CodeMirror.registerHelper("hint", "auto", {
resolve: resolveAutoHints
});
CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
var cur = cm.getCursor(), token = cm.getTokenAt(cur)
var term, from = CodeMirror.Pos(cur.line, token.start), to = cur
if (token.start < cur.ch && /\w/.test(token.string.charAt(cur.ch - token.start - 1))) {
term = token.string.substr(0, cur.ch - token.start)
} else {
term = ""
from = cur
}
var found = [];
for (var i = 0; i < options.words.length; i++) {
var word = options.words[i];
if (word.slice(0, term.length) == term)
found.push(word);
}
if (found.length) return {list: found, from: from, to: to};
});
CodeMirror.commands.autocomplete = CodeMirror.showHint;
var defaultOptions = {
hint: CodeMirror.hint.auto,
completeSingle: true,
alignWithWord: true,
closeCharacters: /[\s()\[\]{};:>,]/,
closeOnUnfocus: true,
completeOnSingleClick: true,
container: null,
customKeys: null,
extraKeys: null
};
CodeMirror.defineOption("hintOptions", null);
});

View File

@ -0,0 +1,304 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../../mode/sql/sql"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "../../mode/sql/sql"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var tables;
var defaultTable;
var keywords;
var identifierQuote;
var CONS = {
QUERY_DIV: ";",
ALIAS_KEYWORD: "AS"
};
var Pos = CodeMirror.Pos, cmpPos = CodeMirror.cmpPos;
function isArray(val) { return Object.prototype.toString.call(val) == "[object Array]" }
function getKeywords(editor) {
var mode = editor.doc.modeOption;
if (mode === "sql") mode = "text/x-sql";
return CodeMirror.resolveMode(mode).keywords;
}
function getIdentifierQuote(editor) {
var mode = editor.doc.modeOption;
if (mode === "sql") mode = "text/x-sql";
return CodeMirror.resolveMode(mode).identifierQuote || "`";
}
function getText(item) {
return typeof item == "string" ? item : item.text;
}
function wrapTable(name, value) {
if (isArray(value)) value = {columns: value}
if (!value.text) value.text = name
return value
}
function parseTables(input) {
var result = {}
if (isArray(input)) {
for (var i = input.length - 1; i >= 0; i--) {
var item = input[i]
result[getText(item).toUpperCase()] = wrapTable(getText(item), item)
}
} else if (input) {
for (var name in input)
result[name.toUpperCase()] = wrapTable(name, input[name])
}
return result
}
function getTable(name) {
return tables[name.toUpperCase()]
}
function shallowClone(object) {
var result = {};
for (var key in object) if (object.hasOwnProperty(key))
result[key] = object[key];
return result;
}
function match(string, word) {
var len = string.length;
var sub = getText(word).substr(0, len);
return string.toUpperCase() === sub.toUpperCase();
}
function addMatches(result, search, wordlist, formatter) {
if (isArray(wordlist)) {
for (var i = 0; i < wordlist.length; i++)
if (match(search, wordlist[i])) result.push(formatter(wordlist[i]))
} else {
for (var word in wordlist) if (wordlist.hasOwnProperty(word)) {
var val = wordlist[word]
if (!val || val === true)
val = word
else
val = val.displayText ? {text: val.text, displayText: val.displayText} : val.text
if (match(search, val)) result.push(formatter(val))
}
}
}
function cleanName(name) {
// Get rid name from identifierQuote and preceding dot(.)
if (name.charAt(0) == ".") {
name = name.substr(1);
}
// replace doublicated identifierQuotes with single identifierQuotes
// and remove single identifierQuotes
var nameParts = name.split(identifierQuote+identifierQuote);
for (var i = 0; i < nameParts.length; i++)
nameParts[i] = nameParts[i].replace(new RegExp(identifierQuote,"g"), "");
return nameParts.join(identifierQuote);
}
function insertIdentifierQuotes(name) {
var nameParts = getText(name).split(".");
for (var i = 0; i < nameParts.length; i++)
nameParts[i] = identifierQuote +
// doublicate identifierQuotes
nameParts[i].replace(new RegExp(identifierQuote,"g"), identifierQuote+identifierQuote) +
identifierQuote;
var escaped = nameParts.join(".");
if (typeof name == "string") return escaped;
name = shallowClone(name);
name.text = escaped;
return name;
}
function nameCompletion(cur, token, result, editor) {
// Try to complete table, column names and return start position of completion
var useIdentifierQuotes = false;
var nameParts = [];
var start = token.start;
var cont = true;
while (cont) {
cont = (token.string.charAt(0) == ".");
useIdentifierQuotes = useIdentifierQuotes || (token.string.charAt(0) == identifierQuote);
start = token.start;
nameParts.unshift(cleanName(token.string));
token = editor.getTokenAt(Pos(cur.line, token.start));
if (token.string == ".") {
cont = true;
token = editor.getTokenAt(Pos(cur.line, token.start));
}
}
// Try to complete table names
var string = nameParts.join(".");
addMatches(result, string, tables, function(w) {
return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;
});
// Try to complete columns from defaultTable
addMatches(result, string, defaultTable, function(w) {
return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;
});
// Try to complete columns
string = nameParts.pop();
var table = nameParts.join(".");
var alias = false;
var aliasTable = table;
// Check if table is available. If not, find table by Alias
if (!getTable(table)) {
var oldTable = table;
table = findTableByAlias(table, editor);
if (table !== oldTable) alias = true;
}
var columns = getTable(table);
if (columns && columns.columns)
columns = columns.columns;
if (columns) {
addMatches(result, string, columns, function(w) {
var tableInsert = table;
if (alias == true) tableInsert = aliasTable;
if (typeof w == "string") {
w = tableInsert + "." + w;
} else {
w = shallowClone(w);
w.text = tableInsert + "." + w.text;
}
return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;
});
}
return start;
}
function eachWord(lineText, f) {
var words = lineText.split(/\s+/)
for (var i = 0; i < words.length; i++)
if (words[i]) f(words[i].replace(/[,;]/g, ''))
}
function findTableByAlias(alias, editor) {
var doc = editor.doc;
var fullQuery = doc.getValue();
var aliasUpperCase = alias.toUpperCase();
var previousWord = "";
var table = "";
var separator = [];
var validRange = {
start: Pos(0, 0),
end: Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).length)
};
//add separator
var indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV);
while(indexOfSeparator != -1) {
separator.push(doc.posFromIndex(indexOfSeparator));
indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV, indexOfSeparator+1);
}
separator.unshift(Pos(0, 0));
separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length));
//find valid range
var prevItem = null;
var current = editor.getCursor()
for (var i = 0; i < separator.length; i++) {
if ((prevItem == null || cmpPos(current, prevItem) > 0) && cmpPos(current, separator[i]) <= 0) {
validRange = {start: prevItem, end: separator[i]};
break;
}
prevItem = separator[i];
}
if (validRange.start) {
var query = doc.getRange(validRange.start, validRange.end, false);
for (var i = 0; i < query.length; i++) {
var lineText = query[i];
eachWord(lineText, function(word) {
var wordUpperCase = word.toUpperCase();
if (wordUpperCase === aliasUpperCase && getTable(previousWord))
table = previousWord;
if (wordUpperCase !== CONS.ALIAS_KEYWORD)
previousWord = word;
});
if (table) break;
}
}
return table;
}
CodeMirror.registerHelper("hint", "sql", function(editor, options) {
tables = parseTables(options && options.tables)
var defaultTableName = options && options.defaultTable;
var disableKeywords = options && options.disableKeywords;
defaultTable = defaultTableName && getTable(defaultTableName);
keywords = getKeywords(editor);
identifierQuote = getIdentifierQuote(editor);
if (defaultTableName && !defaultTable)
defaultTable = findTableByAlias(defaultTableName, editor);
defaultTable = defaultTable || [];
if (defaultTable.columns)
defaultTable = defaultTable.columns;
var cur = editor.getCursor();
var result = [];
var token = editor.getTokenAt(cur), start, end, search;
if (token.end > cur.ch) {
token.end = cur.ch;
token.string = token.string.slice(0, cur.ch - token.start);
}
if (token.string.match(/^[.`"'\w@][\w$#]*$/g)) {
search = token.string;
start = token.start;
end = token.end;
} else {
start = end = cur.ch;
search = "";
}
if (search.charAt(0) == "." || search.charAt(0) == identifierQuote) {
start = nameCompletion(cur, token, result, editor);
} else {
var objectOrClass = function(w, className) {
if (typeof w === "object") {
w.className = className;
} else {
w = { text: w, className: className };
}
return w;
};
addMatches(result, search, defaultTable, function(w) {
return objectOrClass(w, "CodeMirror-hint-table CodeMirror-hint-default-table");
});
addMatches(
result,
search,
tables, function(w) {
return objectOrClass(w, "CodeMirror-hint-table");
}
);
if (!disableKeywords)
addMatches(result, search, keywords, function(w) {
return objectOrClass(w.toUpperCase(), "CodeMirror-hint-keyword");
});
}
return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)};
});
});

View File

@ -0,0 +1,132 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var Pos = CodeMirror.Pos;
function matches(hint, typed, matchInMiddle) {
if (matchInMiddle) return hint.indexOf(typed) >= 0;
else return hint.lastIndexOf(typed, 0) == 0;
}
function getHints(cm, options) {
var tags = options && options.schemaInfo;
var quote = (options && options.quoteChar) || '"';
var matchInMiddle = options && options.matchInMiddle;
if (!tags) return;
var cur = cm.getCursor(), token = cm.getTokenAt(cur);
if (token.end > cur.ch) {
token.end = cur.ch;
token.string = token.string.slice(0, cur.ch - token.start);
}
var inner = CodeMirror.innerMode(cm.getMode(), token.state);
if (!inner.mode.xmlCurrentTag) return
var result = [], replaceToken = false, prefix;
var tag = /\btag\b/.test(token.type) && !/>$/.test(token.string);
var tagName = tag && /^\w/.test(token.string), tagStart;
if (tagName) {
var before = cm.getLine(cur.line).slice(Math.max(0, token.start - 2), token.start);
var tagType = /<\/$/.test(before) ? "close" : /<$/.test(before) ? "open" : null;
if (tagType) tagStart = token.start - (tagType == "close" ? 2 : 1);
} else if (tag && token.string == "<") {
tagType = "open";
} else if (tag && token.string == "</") {
tagType = "close";
}
var tagInfo = inner.mode.xmlCurrentTag(inner.state)
if (!tag && !tagInfo || tagType) {
if (tagName)
prefix = token.string;
replaceToken = tagType;
var context = inner.mode.xmlCurrentContext ? inner.mode.xmlCurrentContext(inner.state) : []
var inner = context.length && context[context.length - 1]
var curTag = inner && tags[inner]
var childList = inner ? curTag && curTag.children : tags["!top"];
if (childList && tagType != "close") {
for (var i = 0; i < childList.length; ++i) if (!prefix || matches(childList[i], prefix, matchInMiddle))
result.push("<" + childList[i]);
} else if (tagType != "close") {
for (var name in tags)
if (tags.hasOwnProperty(name) && name != "!top" && name != "!attrs" && (!prefix || matches(name, prefix, matchInMiddle)))
result.push("<" + name);
}
if (inner && (!prefix || tagType == "close" && matches(inner, prefix, matchInMiddle)))
result.push("</" + inner + ">");
} else {
// Attribute completion
var curTag = tagInfo && tags[tagInfo.name], attrs = curTag && curTag.attrs;
var globalAttrs = tags["!attrs"];
if (!attrs && !globalAttrs) return;
if (!attrs) {
attrs = globalAttrs;
} else if (globalAttrs) { // Combine tag-local and global attributes
var set = {};
for (var nm in globalAttrs) if (globalAttrs.hasOwnProperty(nm)) set[nm] = globalAttrs[nm];
for (var nm in attrs) if (attrs.hasOwnProperty(nm)) set[nm] = attrs[nm];
attrs = set;
}
if (token.type == "string" || token.string == "=") { // A value
var before = cm.getRange(Pos(cur.line, Math.max(0, cur.ch - 60)),
Pos(cur.line, token.type == "string" ? token.start : token.end));
var atName = before.match(/([^\s\u00a0=<>\"\']+)=$/), atValues;
if (!atName || !attrs.hasOwnProperty(atName[1]) || !(atValues = attrs[atName[1]])) return;
if (typeof atValues == 'function') atValues = atValues.call(this, cm); // Functions can be used to supply values for autocomplete widget
if (token.type == "string") {
prefix = token.string;
var n = 0;
if (/['"]/.test(token.string.charAt(0))) {
quote = token.string.charAt(0);
prefix = token.string.slice(1);
n++;
}
var len = token.string.length;
if (/['"]/.test(token.string.charAt(len - 1))) {
quote = token.string.charAt(len - 1);
prefix = token.string.substr(n, len - 2);
}
if (n) { // an opening quote
var line = cm.getLine(cur.line);
if (line.length > token.end && line.charAt(token.end) == quote) token.end++; // include a closing quote
}
replaceToken = true;
}
function returnHintsFromAtValues(atValues) {
if (atValues)
for (var i = 0; i < atValues.length; ++i) if (!prefix || matches(atValues[i], prefix, matchInMiddle))
result.push(quote + atValues[i] + quote);
return returnHints();
}
if (atValues && atValues.then) return atValues.then(returnHintsFromAtValues);
return returnHintsFromAtValues(atValues);
} else { // An attribute name
if (token.type == "attribute") {
prefix = token.string;
replaceToken = true;
}
for (var attr in attrs) if (attrs.hasOwnProperty(attr) && (!prefix || matches(attr, prefix, matchInMiddle)))
result.push(attr);
}
}
function returnHints() {
return {
list: result,
from: replaceToken ? Pos(cur.line, tagStart == null ? token.start : tagStart) : cur,
to: replaceToken ? Pos(cur.line, token.end) : cur
};
}
return returnHints();
}
CodeMirror.registerHelper("hint", "xml", getHints);
});

View File

@ -0,0 +1,47 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
// Depends on coffeelint.js from http://www.coffeelint.org/js/coffeelint.js
// declare global: coffeelint
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.registerHelper("lint", "coffeescript", function(text) {
var found = [];
if (!window.coffeelint) {
if (window.console) {
window.console.error("Error: window.coffeelint not defined, CodeMirror CoffeeScript linting cannot run.");
}
return found;
}
var parseError = function(err) {
var loc = err.lineNumber;
found.push({from: CodeMirror.Pos(loc-1, 0),
to: CodeMirror.Pos(loc, 0),
severity: err.level,
message: err.message});
};
try {
var res = coffeelint.lint(text);
for(var i = 0; i < res.length; i++) {
parseError(res[i]);
}
} catch(e) {
found.push({from: CodeMirror.Pos(e.location.first_line, 0),
to: CodeMirror.Pos(e.location.last_line, e.location.last_column),
severity: 'error',
message: e.message});
}
return found;
});
});

View File

@ -0,0 +1,40 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
// Depends on csslint.js from https://github.com/stubbornella/csslint
// declare global: CSSLint
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.registerHelper("lint", "css", function(text, options) {
var found = [];
if (!window.CSSLint) {
if (window.console) {
window.console.error("Error: window.CSSLint not defined, CodeMirror CSS linting cannot run.");
}
return found;
}
var results = CSSLint.verify(text, options), messages = results.messages, message = null;
for ( var i = 0; i < messages.length; i++) {
message = messages[i];
var startLine = message.line -1, endLine = message.line -1, startCol = message.col -1, endCol = message.col;
found.push({
from: CodeMirror.Pos(startLine, startCol),
to: CodeMirror.Pos(endLine, endCol),
message: message.message,
severity : message.type
});
}
return found;
});
});

View File

@ -0,0 +1,59 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
// Depends on htmlhint.js from http://htmlhint.com/js/htmlhint.js
// declare global: HTMLHint
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("htmlhint"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "htmlhint"], mod);
else // Plain browser env
mod(CodeMirror, window.HTMLHint);
})(function(CodeMirror, HTMLHint) {
"use strict";
var defaultRules = {
"tagname-lowercase": true,
"attr-lowercase": true,
"attr-value-double-quotes": true,
"doctype-first": false,
"tag-pair": true,
"spec-char-escape": true,
"id-unique": true,
"src-not-empty": true,
"attr-no-duplication": true
};
CodeMirror.registerHelper("lint", "html", function(text, options) {
var found = [];
if (HTMLHint && !HTMLHint.verify) {
if(typeof HTMLHint.default !== 'undefined') {
HTMLHint = HTMLHint.default;
} else {
HTMLHint = HTMLHint.HTMLHint;
}
}
if (!HTMLHint) HTMLHint = window.HTMLHint;
if (!HTMLHint) {
if (window.console) {
window.console.error("Error: HTMLHint not found, not defined on window, or not available through define/require, CodeMirror HTML linting cannot run.");
}
return found;
}
var messages = HTMLHint.verify(text, options && options.rules || defaultRules);
for (var i = 0; i < messages.length; i++) {
var message = messages[i];
var startLine = message.line - 1, endLine = message.line - 1, startCol = message.col - 1, endCol = message.col;
found.push({
from: CodeMirror.Pos(startLine, startCol),
to: CodeMirror.Pos(endLine, endCol),
message: message.message,
severity : message.type
});
}
return found;
});
});

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