Show More
@@ -67,8 +67,8 b' pdebug = false' | |||||
67 | #smtp_use_tls = false |
|
67 | #smtp_use_tls = false | |
68 |
|
68 | |||
69 | [server:main] |
|
69 | [server:main] | |
70 | ## PASTE ## |
|
70 | ## Gearbox default web server ## | |
71 | #use = egg:Paste#http |
|
71 | #use = egg:gearbox#wsgiref | |
72 | ## nr of worker threads to spawn |
|
72 | ## nr of worker threads to spawn | |
73 | #threadpool_workers = 1 |
|
73 | #threadpool_workers = 1 | |
74 | ## max request before thread respawn |
|
74 | ## max request before thread respawn | |
@@ -76,6 +76,9 b' pdebug = false' | |||||
76 | ## option to use threads of process |
|
76 | ## option to use threads of process | |
77 | #use_threadpool = true |
|
77 | #use_threadpool = true | |
78 |
|
78 | |||
|
79 | ## Gearbox gevent web server ## | |||
|
80 | #use = egg:gearbox#gevent | |||
|
81 | ||||
79 | ## WAITRESS ## |
|
82 | ## WAITRESS ## | |
80 | use = egg:waitress#main |
|
83 | use = egg:waitress#main | |
81 | ## number of worker threads |
|
84 | ## number of worker threads | |
@@ -509,7 +512,7 b' script_location = kallithea:alembic' | |||||
509 | ################################ |
|
512 | ################################ | |
510 |
|
513 | |||
511 | [loggers] |
|
514 | [loggers] | |
512 | keys = root, routes, kallithea, sqlalchemy, beaker, templates, whoosh_indexer |
|
515 | keys = root, routes, kallithea, sqlalchemy, gearbox, beaker, templates, whoosh_indexer | |
513 |
|
516 | |||
514 | [handlers] |
|
517 | [handlers] | |
515 | keys = console, console_sql |
|
518 | keys = console, console_sql | |
@@ -550,6 +553,12 b' handlers =' | |||||
550 | qualname = kallithea |
|
553 | qualname = kallithea | |
551 | propagate = 1 |
|
554 | propagate = 1 | |
552 |
|
555 | |||
|
556 | [logger_gearbox] | |||
|
557 | level = DEBUG | |||
|
558 | handlers = | |||
|
559 | qualname = gearbox | |||
|
560 | propagate = 1 | |||
|
561 | ||||
553 | [logger_sqlalchemy] |
|
562 | [logger_sqlalchemy] | |
554 | level = INFO |
|
563 | level = INFO | |
555 | handlers = console_sql |
|
564 | handlers = console_sql |
@@ -36,9 +36,9 b' To get started with development::' | |||||
36 | source ../kallithea-venv/bin/activate |
|
36 | source ../kallithea-venv/bin/activate | |
37 | pip install --upgrade pip setuptools |
|
37 | pip install --upgrade pip setuptools | |
38 | pip install -e . |
|
38 | pip install -e . | |
39 |
|
|
39 | TODO make-config Kallithea my.ini | |
40 |
|
|
40 | gearbox setup-db -c my.ini --user=user --email=user@example.com --password=password --repos=/tmp | |
41 |
|
|
41 | gearbox serve -c my.ini --reload & | |
42 | firefox http://127.0.0.1:5000/ |
|
42 | firefox http://127.0.0.1:5000/ | |
43 |
|
43 | |||
44 | You can also start out by forking https://bitbucket.org/conservancy/kallithea |
|
44 | You can also start out by forking https://bitbucket.org/conservancy/kallithea | |
@@ -66,7 +66,7 b' SQLite database specified there.' | |||||
66 | It is possible to avoid recreating the full test database on each invocation of |
|
66 | It is possible to avoid recreating the full test database on each invocation of | |
67 | the tests, thus eliminating the initial delay. To achieve this, run the tests as:: |
|
67 | the tests, thus eliminating the initial delay. To achieve this, run the tests as:: | |
68 |
|
68 | |||
69 |
|
|
69 | gearbox serve -c kallithea/tests/test.ini --pid-file=test.pid --daemon | |
70 | KALLITHEA_WHOOSH_TEST_DISABLE=1 KALLITHEA_NO_TMP_PATH=1 py.test |
|
70 | KALLITHEA_WHOOSH_TEST_DISABLE=1 KALLITHEA_NO_TMP_PATH=1 py.test | |
71 | kill -9 $(cat test.pid) |
|
71 | kill -9 $(cat test.pid) | |
72 |
|
72 |
@@ -18,7 +18,7 b' 1. :ref:`Create a Kallithea configuratio' | |||||
18 | 2. Create a separate throwaway configuration for iterating on the actual |
|
18 | 2. Create a separate throwaway configuration for iterating on the actual | |
19 | database changes:: |
|
19 | database changes:: | |
20 |
|
20 | |||
21 |
|
|
21 | TODO make-config Kallithea temp.ini | |
22 |
|
22 | |||
23 | Edit the file to change database settings. SQLite is typically fine, |
|
23 | Edit the file to change database settings. SQLite is typically fine, | |
24 | but make sure to change the path to e.g. ``temp.db``, to avoid |
|
24 | but make sure to change the path to e.g. ``temp.db``, to avoid | |
@@ -30,8 +30,8 b' 4. After every database schema change, r' | |||||
30 | to test the changes:: |
|
30 | to test the changes:: | |
31 |
|
31 | |||
32 | rm temp.db |
|
32 | rm temp.db | |
33 |
|
|
33 | gearbox setup-db -c temp.ini --repos=/var/repos --user=doe --email doe@example.com --password=123456 --no-public-access --force-yes | |
34 |
|
|
34 | gearbox repo-scan -c temp.ini | |
35 |
|
35 | |||
36 | 5. Once satisfied with the schema changes, auto-generate a draft Alembic |
|
36 | 5. Once satisfied with the schema changes, auto-generate a draft Alembic | |
37 | script using the development database that has *not* been upgraded. |
|
37 | script using the development database that has *not* been upgraded. |
@@ -59,7 +59,7 b' ISAPI handler' | |||||
59 |
|
59 | |||
60 | The ISAPI handler can be generated using:: |
|
60 | The ISAPI handler can be generated using:: | |
61 |
|
61 | |||
62 |
|
|
62 | gearbox install-iis -c my.ini --virtualdir=/ | |
63 |
|
63 | |||
64 | This will generate a ``dispatch.py`` file in the current directory that contains |
|
64 | This will generate a ``dispatch.py`` file in the current directory that contains | |
65 | the necessary components to finalize an installation into IIS. Once this file |
|
65 | the necessary components to finalize an installation into IIS. Once this file | |
@@ -74,7 +74,7 b' This accomplishes two things: generating' | |||||
74 |
|
74 | |||
75 | The ISAPI handler is registered to all file extensions, so it will automatically |
|
75 | The ISAPI handler is registered to all file extensions, so it will automatically | |
76 | be the one handling all requests to the specified virtual directory. When the website starts |
|
76 | be the one handling all requests to the specified virtual directory. When the website starts | |
77 |
the ISAPI handler, it will start a thread pool managed wrapper around the |
|
77 | the ISAPI handler, it will start a thread pool managed wrapper around the | |
78 | middleware WSGI handler that Kallithea runs within and each HTTP request to the |
|
78 | middleware WSGI handler that Kallithea runs within and each HTTP request to the | |
79 | site will be processed through this logic henceforth. |
|
79 | site will be processed through this logic henceforth. | |
80 |
|
80 | |||
@@ -111,7 +111,7 b' Troubleshooting' | |||||
111 | --------------- |
|
111 | --------------- | |
112 |
|
112 | |||
113 | Typically, any issues in this setup will either be entirely in IIS or entirely |
|
113 | Typically, any issues in this setup will either be entirely in IIS or entirely | |
114 |
in Kallithea (or Kallithea's WSGI |
|
114 | in Kallithea (or Kallithea's WSGI middleware). Consequently, two | |
115 | different options for finding issues exist: IIS' failed request tracking which |
|
115 | different options for finding issues exist: IIS' failed request tracking which | |
116 | is great at finding issues until they exist inside Kallithea, at which point the |
|
116 | is great at finding issues until they exist inside Kallithea, at which point the | |
117 | ISAPI-WSGI wrapper above uses ``win32traceutil``, which is part of ``pywin32``. |
|
117 | ISAPI-WSGI wrapper above uses ``win32traceutil``, which is part of ``pywin32``. |
@@ -166,7 +166,7 b' it, reopen it following the same command' | |||||
166 | one). When ready, type:: |
|
166 | one). When ready, type:: | |
167 |
|
167 | |||
168 | cd C:\Kallithea\Bin |
|
168 | cd C:\Kallithea\Bin | |
169 |
|
|
169 | TODO make-config Kallithea production.ini | |
170 |
|
170 | |||
171 | Then you must edit production.ini to fit your needs (IP address, IP |
|
171 | Then you must edit production.ini to fit your needs (IP address, IP | |
172 | port, mail settings, database, etc.). `NotePad++`__ or a similar text |
|
172 | port, mail settings, database, etc.). `NotePad++`__ or a similar text | |
@@ -177,7 +177,7 b' differences between Unix and Windows.' | |||||
177 |
|
177 | |||
178 | For the sake of simplicity, run it with the default settings. After your edits (if any) in the previous command prompt, type:: |
|
178 | For the sake of simplicity, run it with the default settings. After your edits (if any) in the previous command prompt, type:: | |
179 |
|
179 | |||
180 |
|
|
180 | gearbox setup-db -c production.ini | |
181 |
|
181 | |||
182 | .. warning:: This time a *new* database will be installed. You must |
|
182 | .. warning:: This time a *new* database will be installed. You must | |
183 | follow a different process to later :ref:`upgrade <upgrade>` |
|
183 | follow a different process to later :ref:`upgrade <upgrade>` | |
@@ -200,7 +200,7 b' Step 10 -- Running Kallithea' | |||||
200 |
|
200 | |||
201 | In the previous command prompt, being in the C:\\Kallithea\\Bin folder, type:: |
|
201 | In the previous command prompt, being in the C:\\Kallithea\\Bin folder, type:: | |
202 |
|
202 | |||
203 |
|
|
203 | gearbox serve -c production.ini | |
204 |
|
204 | |||
205 | Open your web server, and go to http://127.0.0.1:5000 |
|
205 | Open your web server, and go to http://127.0.0.1:5000 | |
206 |
|
206 |
@@ -204,7 +204,7 b' if you closed it reopen it following the' | |||||
204 | "activate" one). When ready, just type:: |
|
204 | "activate" one). When ready, just type:: | |
205 |
|
205 | |||
206 | cd C:\Kallithea\Bin |
|
206 | cd C:\Kallithea\Bin | |
207 |
|
|
207 | TODO make-config Kallithea production.ini | |
208 |
|
208 | |||
209 | Then, you must edit production.ini to fit your needs (network address and |
|
209 | Then, you must edit production.ini to fit your needs (network address and | |
210 | port, mail settings, database, whatever). I recommend using NotePad++ |
|
210 | port, mail settings, database, whatever). I recommend using NotePad++ | |
@@ -215,7 +215,7 b' character differences between Unix and W' | |||||
215 | For the sake of simplicity lets run it with the default settings. After |
|
215 | For the sake of simplicity lets run it with the default settings. After | |
216 | your edits (if any), in the previous Command Prompt, type:: |
|
216 | your edits (if any), in the previous Command Prompt, type:: | |
217 |
|
217 | |||
218 |
|
|
218 | gearbox setup-db -c production.ini | |
219 |
|
219 | |||
220 | .. warning:: This time a *new* database will be installed. You must |
|
220 | .. warning:: This time a *new* database will be installed. You must | |
221 | follow a different process to later :ref:`upgrade <upgrade>` |
|
221 | follow a different process to later :ref:`upgrade <upgrade>` | |
@@ -239,7 +239,7 b' Step 9 -- Running Kallithea' | |||||
239 | In the previous command prompt, being in the C:\\Kallithea\\Bin folder, |
|
239 | In the previous command prompt, being in the C:\\Kallithea\\Bin folder, | |
240 | just type:: |
|
240 | just type:: | |
241 |
|
241 | |||
242 |
|
|
242 | gearbox serve -c production.ini | |
243 |
|
243 | |||
244 | Open yout web server, and go to http://127.0.0.1:5000 |
|
244 | Open yout web server, and go to http://127.0.0.1:5000 | |
245 |
|
245 |
@@ -84,17 +84,17 b' to use web server authentication.' | |||||
84 |
|
84 | |||
85 | There are several web server options: |
|
85 | There are several web server options: | |
86 |
|
86 | |||
87 |
- Kallithea uses the |
|
87 | - Kallithea uses the Gearbox_ tool as command line interface. Gearbox provides | |
88 |
`` |
|
88 | ``gearbox serve`` as a convenient way to launch a Python WSGI / web server | |
89 | from the command line. That is perfect for development and evaluation. |
|
89 | from the command line. That is perfect for development and evaluation. | |
90 | Actual use in production might have different requirements and need extra |
|
90 | Actual use in production might have different requirements and need extra | |
91 | work to make it manageable as a scalable system service. |
|
91 | work to make it manageable as a scalable system service. | |
92 |
|
92 | |||
93 |
|
|
93 | Gearbox comes with its own built-in web server but Kallithea defaults to use | |
94 | Waitress_. Gunicorn_ is also an option. These web servers have different |
|
94 | Waitress_. Gunicorn_ is also an option. These web servers have different | |
95 | limited feature sets. |
|
95 | limited feature sets. | |
96 |
|
96 | |||
97 |
The web server used by `` |
|
97 | The web server used by ``gearbox`` is configured in the ``.ini`` file passed | |
98 | to it. The entry point for the WSGI application is configured |
|
98 | to it. The entry point for the WSGI application is configured | |
99 | in ``setup.py`` as ``kallithea.config.middleware:make_app``. |
|
99 | in ``setup.py`` as ``kallithea.config.middleware:make_app``. | |
100 |
|
100 | |||
@@ -113,7 +113,7 b' There are several web server options:' | |||||
113 | encryption or special authentication or for other security reasons, to |
|
113 | encryption or special authentication or for other security reasons, to | |
114 | provide caching of static files, or to provide load balancing or fail-over. |
|
114 | provide caching of static files, or to provide load balancing or fail-over. | |
115 | Nginx_, Varnish_ and HAProxy_ are often used for this purpose, often in front |
|
115 | Nginx_, Varnish_ and HAProxy_ are often used for this purpose, often in front | |
116 |
of a `` |
|
116 | of a ``gearbox serve`` that somehow is wrapped as a service. | |
117 |
|
117 | |||
118 | The best option depends on what you are familiar with and the requirements for |
|
118 | The best option depends on what you are familiar with and the requirements for | |
119 | performance and stability. Also, keep in mind that Kallithea mainly is serving |
|
119 | performance and stability. Also, keep in mind that Kallithea mainly is serving | |
@@ -126,7 +126,7 b' continuous hammering from the internet.' | |||||
126 | .. _Gunicorn: http://gunicorn.org/ |
|
126 | .. _Gunicorn: http://gunicorn.org/ | |
127 | .. _Waitress: http://waitress.readthedocs.org/en/latest/ |
|
127 | .. _Waitress: http://waitress.readthedocs.org/en/latest/ | |
128 | .. _virtualenv: http://pypi.python.org/pypi/virtualenv |
|
128 | .. _virtualenv: http://pypi.python.org/pypi/virtualenv | |
129 | .. _Paste: http://pythonpaste.org/ |
|
129 | .. _Gearbox: http://turbogears.readthedocs.io/en/latest/turbogears/gearbox.html | |
130 | .. _PyPI: https://pypi.python.org/pypi |
|
130 | .. _PyPI: https://pypi.python.org/pypi | |
131 | .. _Apache httpd: http://httpd.apache.org/ |
|
131 | .. _Apache httpd: http://httpd.apache.org/ | |
132 | .. _mod_wsgi: https://code.google.com/p/modwsgi/ |
|
132 | .. _mod_wsgi: https://code.google.com/p/modwsgi/ |
@@ -11,7 +11,7 b' Setting up Kallithea' | |||||
11 | First, you will need to create a Kallithea configuration file. Run the |
|
11 | First, you will need to create a Kallithea configuration file. Run the | |
12 | following command to do so:: |
|
12 | following command to do so:: | |
13 |
|
13 | |||
14 |
|
|
14 | TODO make-config Kallithea my.ini | |
15 |
|
15 | |||
16 | This will create the file ``my.ini`` in the current directory. This |
|
16 | This will create the file ``my.ini`` in the current directory. This | |
17 | configuration file contains the various settings for Kallithea, e.g. |
|
17 | configuration file contains the various settings for Kallithea, e.g. | |
@@ -25,7 +25,7 b' configuration file to use this other dat' | |||||
25 | PostgreSQL, SQLite and MySQL databases. Create the database by running |
|
25 | PostgreSQL, SQLite and MySQL databases. Create the database by running | |
26 | the following command:: |
|
26 | the following command:: | |
27 |
|
27 | |||
28 |
|
|
28 | gearbox setup-db -c my.ini | |
29 |
|
29 | |||
30 | This will prompt you for a "root" path. This "root" path is the location where |
|
30 | This will prompt you for a "root" path. This "root" path is the location where | |
31 | Kallithea will store all of its repositories on the current machine. After |
|
31 | Kallithea will store all of its repositories on the current machine. After | |
@@ -36,7 +36,7 b' up for you.' | |||||
36 | The ``setup-db`` values can also be given on the command line. |
|
36 | The ``setup-db`` values can also be given on the command line. | |
37 | Example:: |
|
37 | Example:: | |
38 |
|
38 | |||
39 |
|
|
39 | gearbox setup-db -c my.ini --user=nn --password=secret --email=nn@example.com --repos=/srv/repos | |
40 |
|
40 | |||
41 | The ``setup-db`` command will create all needed tables and an |
|
41 | The ``setup-db`` command will create all needed tables and an | |
42 | admin account. When choosing a root path you can either use a new |
|
42 | admin account. When choosing a root path you can either use a new | |
@@ -54,7 +54,7 b' path to the root).' | |||||
54 |
|
54 | |||
55 | You are now ready to use Kallithea. To run it simply execute:: |
|
55 | You are now ready to use Kallithea. To run it simply execute:: | |
56 |
|
56 | |||
57 |
|
|
57 | gearbox serve -c my.ini | |
58 |
|
58 | |||
59 | - This command runs the Kallithea server. The web app should be available at |
|
59 | - This command runs the Kallithea server. The web app should be available at | |
60 | http://127.0.0.1:5000. The IP address and port is configurable via the |
|
60 | http://127.0.0.1:5000. The IP address and port is configurable via the | |
@@ -111,23 +111,23 b' Kallithea provides full text search of r' | |||||
111 |
|
111 | |||
112 | For an incremental index build, run:: |
|
112 | For an incremental index build, run:: | |
113 |
|
113 | |||
114 |
|
|
114 | gearbox make-index -c my.ini | |
115 |
|
115 | |||
116 | For a full index rebuild, run:: |
|
116 | For a full index rebuild, run:: | |
117 |
|
117 | |||
118 |
|
|
118 | gearbox make-index -c my.ini -f | |
119 |
|
119 | |||
120 | The ``--repo-location`` option allows the location of the repositories to be overridden; |
|
120 | The ``--repo-location`` option allows the location of the repositories to be overridden; | |
121 | usually, the location is retrieved from the Kallithea database. |
|
121 | usually, the location is retrieved from the Kallithea database. | |
122 |
|
122 | |||
123 | The ``--index-only`` option can be used to limit the indexed repositories to a comma-separated list:: |
|
123 | The ``--index-only`` option can be used to limit the indexed repositories to a comma-separated list:: | |
124 |
|
124 | |||
125 |
|
|
125 | gearbox make-index -c my.ini --index-only=vcs,kallithea | |
126 |
|
126 | |||
127 | To keep your index up-to-date it is necessary to do periodic index builds; |
|
127 | To keep your index up-to-date it is necessary to do periodic index builds; | |
128 | for this, it is recommended to use a crontab entry. Example:: |
|
128 | for this, it is recommended to use a crontab entry. Example:: | |
129 |
|
129 | |||
130 |
0 3 * * * /path/to/virtualenv/bin/ |
|
130 | 0 3 * * * /path/to/virtualenv/bin/gearbox make-index -c /path/to/kallithea/my.ini | |
131 |
|
131 | |||
132 | When using incremental mode (the default), Whoosh will check the last |
|
132 | When using incremental mode (the default), Whoosh will check the last | |
133 | modification date of each file and add it to be reindexed if a newer file is |
|
133 | modification date of each file and add it to be reindexed if a newer file is | |
@@ -592,7 +592,10 b' Celery. So for example setting `BROKER_H' | |||||
592 |
|
592 | |||
593 | To start the Celery process, run:: |
|
593 | To start the Celery process, run:: | |
594 |
|
594 | |||
595 |
|
|
595 | gearbox celeryd -c <configfile.ini> | |
|
596 | ||||
|
597 | Extra options to the Celery worker can be passed after ``--`` - see ``-- -h`` | |||
|
598 | for more info. | |||
596 |
|
599 | |||
597 | .. note:: |
|
600 | .. note:: | |
598 | Make sure you run this command from the same virtualenv, and with the same |
|
601 | Make sure you run this command from the same virtualenv, and with the same |
@@ -93,7 +93,7 b' 5. Upgrade your configuration' | |||||
93 |
|
93 | |||
94 | Run the following command to upgrade your configuration (``.ini``) file:: |
|
94 | Run the following command to upgrade your configuration (``.ini``) file:: | |
95 |
|
95 | |||
96 |
|
|
96 | TODO make-config Kallithea my.ini | |
97 |
|
97 | |||
98 | This will display any changes made by the new version of Kallithea to your |
|
98 | This will display any changes made by the new version of Kallithea to your | |
99 | current configuration, and attempt an automatic merge. It is recommended |
|
99 | current configuration, and attempt an automatic merge. It is recommended |
@@ -32,7 +32,7 b' overwrite an entire function, change a g' | |||||
32 |
|
32 | |||
33 | To generate a skeleton extensions package, run:: |
|
33 | To generate a skeleton extensions package, run:: | |
34 |
|
34 | |||
35 |
|
|
35 | gearbox make-rcext -c my.ini | |
36 |
|
36 | |||
37 | This will create an ``rcextensions`` package next to the specified ``ini`` file. |
|
37 | This will create an ``rcextensions`` package next to the specified ``ini`` file. | |
38 | See the ``__init__.py`` file inside the generated ``rcextensions`` package |
|
38 | See the ``__init__.py`` file inside the generated ``rcextensions`` package |
@@ -15,7 +15,7 b' or access the repository.' | |||||
15 |
|
15 | |||
16 | There is a special command for cleaning up such archived repositories:: |
|
16 | There is a special command for cleaning up such archived repositories:: | |
17 |
|
17 | |||
18 |
|
|
18 | gearbox cleanup-repos --older-than=30d -c my.ini | |
19 |
|
19 | |||
20 | This command scans for archived repositories that are older than |
|
20 | This command scans for archived repositories that are older than | |
21 | 30 days, displays them, and asks if you want to delete them (unless given |
|
21 | 30 days, displays them, and asks if you want to delete them (unless given |
@@ -28,10 +28,10 b' Web server with chunked encoding' | |||||
28 | Large Git pushes require an HTTP server with support for |
|
28 | Large Git pushes require an HTTP server with support for | |
29 | chunked encoding for POST. The Python web servers waitress_ and |
|
29 | chunked encoding for POST. The Python web servers waitress_ and | |
30 | gunicorn_ (Linux only) can be used. By default, Kallithea uses |
|
30 | gunicorn_ (Linux only) can be used. By default, Kallithea uses | |
31 |
waitress_ for ` |
|
31 | waitress_ for `gearbox serve` instead of the built-in `paste` WSGI | |
32 | server. |
|
32 | server. | |
33 |
|
33 | |||
34 |
The |
|
34 | The web server used by gearbox is controlled in the .ini file:: | |
35 |
|
35 | |||
36 | use = egg:waitress#main |
|
36 | use = egg:waitress#main | |
37 |
|
37 |
@@ -21,7 +21,7 b' env USER=hg' | |||||
21 | # env GROUP=hg |
|
21 | # env GROUP=hg | |
22 |
|
22 | |||
23 | script |
|
23 | script | |
24 |
COMMAND="/var/hg/.virtualenvs/kallithea/bin/ |
|
24 | COMMAND="/var/hg/.virtualenvs/kallithea/bin/gearbox celeryd -c $APPINI -- --pidfile=$PIDFILE" | |
25 | if [ -z "$GROUP" ]; then |
|
25 | if [ -z "$GROUP" ]; then | |
26 | exec sudo -u $USER $COMMAND |
|
26 | exec sudo -u $USER $COMMAND | |
27 | else |
|
27 | else |
@@ -12,7 +12,7 b' APP_PATH="$APP_HOMEDIR/$DAEMON"' | |||||
12 | CONF_NAME="production.ini" |
|
12 | CONF_NAME="production.ini" | |
13 | LOG_FILE="/var/log/$DAEMON.log" |
|
13 | LOG_FILE="/var/log/$DAEMON.log" | |
14 | PID_FILE="/run/daemons/$DAEMON" |
|
14 | PID_FILE="/run/daemons/$DAEMON" | |
15 |
APPL=/usr/bin/ |
|
15 | APPL=/usr/bin/gearbox | |
16 | RUN_AS="*****" |
|
16 | RUN_AS="*****" | |
17 |
|
17 | |||
18 | ARGS="serve --daemon \ |
|
18 | ARGS="serve --daemon \ | |
@@ -20,7 +20,7 b' ARGS="serve --daemon \\' | |||||
20 | --group=$RUN_AS \ |
|
20 | --group=$RUN_AS \ | |
21 | --pid-file=$PID_FILE \ |
|
21 | --pid-file=$PID_FILE \ | |
22 | --log-file=$LOG_FILE \ |
|
22 | --log-file=$LOG_FILE \ | |
23 | $APP_PATH/$CONF_NAME" |
|
23 | -c $APP_PATH/$CONF_NAME" | |
24 |
|
24 | |||
25 | [ -r /etc/conf.d/$DAEMON ] && . /etc/conf.d/$DAEMON |
|
25 | [ -r /etc/conf.d/$DAEMON ] && . /etc/conf.d/$DAEMON | |
26 |
|
26 |
@@ -26,13 +26,13 b' PYTHON_PATH="/$APP_HOMEDIR/$APP_NAME-ven' | |||||
26 |
|
26 | |||
27 | RUN_AS="root" |
|
27 | RUN_AS="root" | |
28 |
|
28 | |||
29 |
DAEMON="$PYTHON_PATH/bin/ |
|
29 | DAEMON="$PYTHON_PATH/bin/gearbox" | |
30 |
|
30 | |||
31 | DAEMON_OPTS="serve --daemon \ |
|
31 | DAEMON_OPTS="serve --daemon \ | |
32 | --user=$RUN_AS \ |
|
32 | --user=$RUN_AS \ | |
33 | --group=$RUN_AS \ |
|
33 | --group=$RUN_AS \ | |
34 | --pid-file=$PID_PATH \ |
|
34 | --pid-file=$PID_PATH \ | |
35 | --log-file=$LOG_PATH $APP_PATH/$CONF_NAME" |
|
35 | --log-file=$LOG_PATH -c $APP_PATH/$CONF_NAME" | |
36 |
|
36 | |||
37 |
|
37 | |||
38 | start() { |
|
38 | start() { |
@@ -16,13 +16,13 b' PYTHON_PATH="/home/$APP_HOMEDIR/v-env"' | |||||
16 |
|
16 | |||
17 | RUN_AS="username" |
|
17 | RUN_AS="username" | |
18 |
|
18 | |||
19 |
DAEMON="$PYTHON_PATH/bin/ |
|
19 | DAEMON="$PYTHON_PATH/bin/gearbox" | |
20 |
|
20 | |||
21 | DAEMON_OPTS="serve --daemon \ |
|
21 | DAEMON_OPTS="serve --daemon \ | |
22 | --user=$RUN_AS \ |
|
22 | --user=$RUN_AS \ | |
23 | --group=$RUN_AS \ |
|
23 | --group=$RUN_AS \ | |
24 | --pid-file=$PID_PATH \ |
|
24 | --pid-file=$PID_PATH \ | |
25 | --log-file=$LOG_PATH $APP_PATH/$CONF_NAME" |
|
25 | --log-file=$LOG_PATH -c $APP_PATH/$CONF_NAME" | |
26 |
|
26 | |||
27 | #extra options |
|
27 | #extra options | |
28 | opts="${opts} restartdelay" |
|
28 | opts="${opts} restartdelay" |
@@ -20,7 +20,7 b' APP_PATH="/var/www/$APP_NAME"' | |||||
20 | CONF_NAME="production.ini" |
|
20 | CONF_NAME="production.ini" | |
21 |
|
21 | |||
22 | # write to wherever the PID should be stored, just ensure |
|
22 | # write to wherever the PID should be stored, just ensure | |
23 |
# that the user you run |
|
23 | # that the user you run gearbox as has the appropriate permissions | |
24 | # same goes for the log file |
|
24 | # same goes for the log file | |
25 | PID_PATH="/var/run/kallithea/pid" |
|
25 | PID_PATH="/var/run/kallithea/pid" | |
26 | LOG_PATH="/var/log/kallithea/kallithea.log" |
|
26 | LOG_PATH="/var/log/kallithea/kallithea.log" | |
@@ -31,13 +31,13 b' PYTHON_PATH="/opt/python_virtualenvironm' | |||||
31 |
|
31 | |||
32 | RUN_AS="kallithea" |
|
32 | RUN_AS="kallithea" | |
33 |
|
33 | |||
34 |
DAEMON="$PYTHON_PATH/bin/ |
|
34 | DAEMON="$PYTHON_PATH/bin/gearbox" | |
35 |
|
35 | |||
36 | DAEMON_OPTS="serve --daemon \ |
|
36 | DAEMON_OPTS="serve --daemon \ | |
37 | --user=$RUN_AS \ |
|
37 | --user=$RUN_AS \ | |
38 | --group=$RUN_AS \ |
|
38 | --group=$RUN_AS \ | |
39 | --pid-file=$PID_PATH \ |
|
39 | --pid-file=$PID_PATH \ | |
40 | --log-file=$LOG_PATH $APP_PATH/$CONF_NAME" |
|
40 | --log-file=$LOG_PATH -c $APP_PATH/$CONF_NAME" | |
41 |
|
41 | |||
42 | DESC="kallithea-server" |
|
42 | DESC="kallithea-server" | |
43 | LOCK_FILE="/var/lock/subsys/$APP_NAME" |
|
43 | LOCK_FILE="/var/lock/subsys/$APP_NAME" |
@@ -19,7 +19,7 b' env HOME=/var/hg' | |||||
19 | env USER=hg |
|
19 | env USER=hg | |
20 | env GROUP=hg |
|
20 | env GROUP=hg | |
21 |
|
21 | |||
22 |
exec /var/hg/.virtualenvs/kallithea/bin/ |
|
22 | exec /var/hg/.virtualenvs/kallithea/bin/gearbox serve --user=$USER --group=$GROUP --pid-file=$PIDFILE --log-file=$LOGFILE -c $APPINI | |
23 |
|
23 | |||
24 | post-stop script |
|
24 | post-stop script | |
25 | rm -f $PIDFILE |
|
25 | rm -f $PIDFILE |
@@ -45,7 +45,7 b' serverurl=http://127.0.0.1:9001 ; use an' | |||||
45 | numprocs = 1 |
|
45 | numprocs = 1 | |
46 | numprocs_start = 5000 # possible should match ports |
|
46 | numprocs_start = 5000 # possible should match ports | |
47 | directory=/srv/kallithea |
|
47 | directory=/srv/kallithea | |
48 |
command = /srv/kallithea/venv/bin/ |
|
48 | command = /srv/kallithea/venv/bin/gearbox serve -c my.ini | |
49 | process_name = %(program_name)s_%(process_num)04d |
|
49 | process_name = %(program_name)s_%(process_num)04d | |
50 | redirect_stderr=true |
|
50 | redirect_stderr=true | |
51 | stdout_logfile=/%(here)s/kallithea.log |
|
51 | stdout_logfile=/%(here)s/kallithea.log |
@@ -40,7 +40,7 b" logging.getLogger('alembic').setLevel(lo" | |||||
40 |
|
40 | |||
41 | # Setup Python loggers based on the config file provided to the alembic |
|
41 | # Setup Python loggers based on the config file provided to the alembic | |
42 | # command. If we're being invoked via the Alembic API (presumably for |
|
42 | # command. If we're being invoked via the Alembic API (presumably for | |
43 |
# stamping during " |
|
43 | # stamping during "gearbox setup-db"), config_file_name is not available, | |
44 | # and loggers are assumed to already have been configured. |
|
44 | # and loggers are assumed to already have been configured. | |
45 | if config.config_file_name: |
|
45 | if config.config_file_name: | |
46 | fileConfig(config.config_file_name, disable_existing_loggers=False) |
|
46 | fileConfig(config.config_file_name, disable_existing_loggers=False) |
@@ -61,9 +61,9 b' pdebug = false' | |||||
61 | #smtp_use_tls = false |
|
61 | #smtp_use_tls = false | |
62 |
|
62 | |||
63 | [server:main] |
|
63 | [server:main] | |
64 |
%if http_server == ' |
|
64 | %if http_server == 'gearbox': | |
65 | <%text>## PASTE ##</%text> |
|
65 | <%text>## Gearbox default web server ##</%text> | |
66 | use = egg:Paste#http |
|
66 | use = egg:gearbox#wsgiref | |
67 | <%text>## nr of worker threads to spawn</%text> |
|
67 | <%text>## nr of worker threads to spawn</%text> | |
68 | threadpool_workers = 1 |
|
68 | threadpool_workers = 1 | |
69 | <%text>## max request before thread respawn</%text> |
|
69 | <%text>## max request before thread respawn</%text> | |
@@ -71,6 +71,10 b' threadpool_max_requests = 100' | |||||
71 | <%text>## option to use threads of process</%text> |
|
71 | <%text>## option to use threads of process</%text> | |
72 | use_threadpool = true |
|
72 | use_threadpool = true | |
73 |
|
73 | |||
|
74 | %elif http_server == 'gevent': | |||
|
75 | <%text>## Gearbox gevent web server ##</%text> | |||
|
76 | use = egg:gearbox#gevent | |||
|
77 | ||||
74 | %elif http_server == 'waitress': |
|
78 | %elif http_server == 'waitress': | |
75 | <%text>## WAITRESS ##</%text> |
|
79 | <%text>## WAITRESS ##</%text> | |
76 | use = egg:waitress#main |
|
80 | use = egg:waitress#main | |
@@ -512,7 +516,7 b' script_location = kallithea:alembic' | |||||
512 | <%text>################################</%text> |
|
516 | <%text>################################</%text> | |
513 |
|
517 | |||
514 | [loggers] |
|
518 | [loggers] | |
515 | keys = root, routes, kallithea, sqlalchemy, beaker, templates, whoosh_indexer |
|
519 | keys = root, routes, kallithea, sqlalchemy, gearbox, beaker, templates, whoosh_indexer | |
516 |
|
520 | |||
517 | [handlers] |
|
521 | [handlers] | |
518 | keys = console, console_sql |
|
522 | keys = console, console_sql | |
@@ -553,6 +557,12 b' handlers =' | |||||
553 | qualname = kallithea |
|
557 | qualname = kallithea | |
554 | propagate = 1 |
|
558 | propagate = 1 | |
555 |
|
559 | |||
|
560 | [logger_gearbox] | |||
|
561 | level = DEBUG | |||
|
562 | handlers = | |||
|
563 | qualname = gearbox | |||
|
564 | propagate = 1 | |||
|
565 | ||||
556 | [logger_sqlalchemy] |
|
566 | [logger_sqlalchemy] | |
557 | level = INFO |
|
567 | level = INFO | |
558 | handlers = console_sql |
|
568 | handlers = console_sql |
@@ -62,8 +62,8 b' pdebug = false' | |||||
62 | #smtp_use_tls = false |
|
62 | #smtp_use_tls = false | |
63 |
|
63 | |||
64 | [server:main] |
|
64 | [server:main] | |
65 | ## PASTE ## |
|
65 | ## Gearbox default web server ## | |
66 | #use = egg:Paste#http |
|
66 | #use = egg:gearbox#wsgiref | |
67 | ## nr of worker threads to spawn |
|
67 | ## nr of worker threads to spawn | |
68 | #threadpool_workers = 1 |
|
68 | #threadpool_workers = 1 | |
69 | ## max request before thread respawn |
|
69 | ## max request before thread respawn | |
@@ -71,6 +71,9 b' pdebug = false' | |||||
71 | ## option to use threads of process |
|
71 | ## option to use threads of process | |
72 | #use_threadpool = true |
|
72 | #use_threadpool = true | |
73 |
|
73 | |||
|
74 | ## Gearbox gevent web server ## | |||
|
75 | #use = egg:gearbox#gevent | |||
|
76 | ||||
74 | ## WAITRESS ## |
|
77 | ## WAITRESS ## | |
75 | use = egg:waitress#main |
|
78 | use = egg:waitress#main | |
76 | ## number of worker threads |
|
79 | ## number of worker threads | |
@@ -501,7 +504,7 b' script_location = kallithea:alembic' | |||||
501 | ################################ |
|
504 | ################################ | |
502 |
|
505 | |||
503 | [loggers] |
|
506 | [loggers] | |
504 | keys = root, routes, kallithea, sqlalchemy, beaker, templates, whoosh_indexer |
|
507 | keys = root, routes, kallithea, sqlalchemy, gearbox, beaker, templates, whoosh_indexer | |
505 |
|
508 | |||
506 | [handlers] |
|
509 | [handlers] | |
507 | keys = console, console_sql |
|
510 | keys = console, console_sql | |
@@ -542,6 +545,12 b' handlers =' | |||||
542 | qualname = kallithea |
|
545 | qualname = kallithea | |
543 | propagate = 1 |
|
546 | propagate = 1 | |
544 |
|
547 | |||
|
548 | [logger_gearbox] | |||
|
549 | level = DEBUG | |||
|
550 | handlers = | |||
|
551 | qualname = gearbox | |||
|
552 | propagate = 1 | |||
|
553 | ||||
545 | [logger_sqlalchemy] |
|
554 | [logger_sqlalchemy] | |
546 | level = INFO |
|
555 | level = INFO | |
547 | handlers = console_sql |
|
556 | handlers = console_sql |
@@ -1,8 +1,9 b'' | |||||
1 |
from |
|
1 | from gearbox.command import Command | |
2 |
|
2 | |||
3 | class UpgradeDb(Command): |
|
3 | class UpgradeDb(Command): | |
4 | hidden = True |
|
4 | '''(removed)''' | |
5 | summary = '(removed)' |
|
5 | ||
|
6 | deprecated = True | |||
6 |
|
7 | |||
7 | def run(self, args): |
|
8 | def run(self, args): | |
8 | raise SystemExit( |
|
9 | raise SystemExit( |
@@ -15,7 +15,7 b'' | |||||
15 | kallithea.lib.paster_commands.cache_keys |
|
15 | kallithea.lib.paster_commands.cache_keys | |
16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
17 |
|
17 | |||
18 |
cleanup-keys |
|
18 | cleanup-keys gearbox command for Kallithea | |
19 |
|
19 | |||
20 |
|
20 | |||
21 | This file was forked by the Kallithea project in July 2014. |
|
21 | This file was forked by the Kallithea project in July 2014. | |
@@ -37,25 +37,14 b' from kallithea.model.db import CacheInva' | |||||
37 |
|
37 | |||
38 |
|
38 | |||
39 | class Command(BasePasterCommand): |
|
39 | class Command(BasePasterCommand): | |
40 |
|
40 | "Kallithea: Utilities for managing caching of database content" | ||
41 | max_args = 1 |
|
|||
42 | min_args = 1 |
|
|||
43 |
|
41 | |||
44 | usage = "CONFIG_FILE" |
|
42 | def take_action(self, args): | |
45 | group_name = "Kallithea" |
|
|||
46 | takes_config_file = -1 |
|
|||
47 | parser = BasePasterCommand.standard_parser(verbose=True) |
|
|||
48 | summary = "Cache keys utils" |
|
|||
49 |
|
||||
50 | def command(self): |
|
|||
51 | #get SqlAlchemy session |
|
|||
52 | self._init_session() |
|
|||
53 |
|
||||
54 | _caches = CacheInvalidation.query().order_by(CacheInvalidation.cache_key).all() |
|
43 | _caches = CacheInvalidation.query().order_by(CacheInvalidation.cache_key).all() | |
55 |
if |
|
44 | if args.show: | |
56 | for c_obj in _caches: |
|
45 | for c_obj in _caches: | |
57 | print 'key:%s active:%s' % (safe_str(c_obj.cache_key), c_obj.cache_active) |
|
46 | print 'key:%s active:%s' % (safe_str(c_obj.cache_key), c_obj.cache_active) | |
58 |
elif |
|
47 | elif args.cleanup: | |
59 | for c_obj in _caches: |
|
48 | for c_obj in _caches: | |
60 | Session().delete(c_obj) |
|
49 | Session().delete(c_obj) | |
61 | print 'Removing key: %s' % (safe_str(c_obj.cache_key)) |
|
50 | print 'Removing key: %s' % (safe_str(c_obj.cache_key)) | |
@@ -63,17 +52,21 b' class Command(BasePasterCommand):' | |||||
63 | else: |
|
52 | else: | |
64 | print 'Nothing done, exiting...' |
|
53 | print 'Nothing done, exiting...' | |
65 |
|
54 | |||
66 |
def |
|
55 | def get_parser(self, prog_name): | |
67 | self.parser.add_option( |
|
56 | parser = super(Command, self).get_parser(prog_name) | |
|
57 | ||||
|
58 | parser.add_argument( | |||
68 | '--show', |
|
59 | '--show', | |
69 | action='store_true', |
|
60 | action='store_true', | |
70 | dest='show', |
|
61 | dest='show', | |
71 |
help= |
|
62 | help="show existing cache keys with together with status", | |
72 | ) |
|
63 | ) | |
73 |
|
64 | |||
74 |
|
|
65 | parser.add_argument( | |
75 | '--cleanup', |
|
66 | '--cleanup', | |
76 | action="store_true", |
|
67 | action="store_true", | |
77 | dest="cleanup", |
|
68 | dest="cleanup", | |
78 | help="cleanup existing cache keys" |
|
69 | help="cleanup existing cache keys", | |
79 | ) |
|
70 | ) | |
|
71 | ||||
|
72 | return parser |
@@ -1,5 +1,7 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 |
|
2 | |||
|
3 | import argparse | |||
|
4 | ||||
3 | import kallithea |
|
5 | import kallithea | |
4 | from kallithea.lib.paster_commands.common import BasePasterCommand |
|
6 | from kallithea.lib.paster_commands.common import BasePasterCommand | |
5 | from kallithea.lib.utils import load_rcextensions |
|
7 | from kallithea.lib.utils import load_rcextensions | |
@@ -9,26 +11,14 b' from kallithea.lib.utils2 import str2boo' | |||||
9 |
|
11 | |||
10 |
|
12 | |||
11 | class Command(BasePasterCommand): |
|
13 | class Command(BasePasterCommand): | |
12 | """Start the celery worker |
|
14 | """Kallithea: Celery worker for asynchronous tasks""" | |
13 |
|
||||
14 | Starts the celery worker that uses a paste.deploy configuration |
|
|||
15 | file. |
|
|||
16 | """ |
|
|||
17 |
|
15 | |||
18 | usage = 'CONFIG_FILE [celeryd options...]' |
|
16 | # Starts the celery worker using configuration from a paste.deploy | |
19 | summary = __doc__.splitlines()[0] |
|
17 | # configuration file. | |
20 | description = "".join(__doc__.splitlines()[2:]) |
|
|||
21 | group_name = "Kallithea" |
|
|||
22 |
|
||||
23 | parser = BasePasterCommand.standard_parser(quiet=True) |
|
|||
24 |
|
18 | |||
25 | def update_parser(self): |
|
19 | requires_db_session = False # will start session on demand | |
26 | from kallithea.lib import celerypylons |
|
|||
27 | cmd = celerypylons.worker.worker(celerypylons.app.app_or_default()) |
|
|||
28 | for x in cmd.get_options(): |
|
|||
29 | self.parser.add_option(x) |
|
|||
30 |
|
20 | |||
31 |
def co |
|
21 | def take_action(self, args): | |
32 | from kallithea.lib import celerypylons |
|
22 | from kallithea.lib import celerypylons | |
33 | from tg import config |
|
23 | from tg import config | |
34 | try: |
|
24 | try: | |
@@ -43,4 +33,18 b' class Command(BasePasterCommand):' | |||||
43 |
|
33 | |||
44 | load_rcextensions(config['here']) |
|
34 | load_rcextensions(config['here']) | |
45 | cmd = celerypylons.worker.worker(celerypylons.app.app_or_default()) |
|
35 | cmd = celerypylons.worker.worker(celerypylons.app.app_or_default()) | |
46 | return cmd.run(**vars(self.options)) |
|
36 | ||
|
37 | celery_args = args.celery_args | |||
|
38 | if '--' in celery_args: | |||
|
39 | celery_args.remove('--') | |||
|
40 | ||||
|
41 | return cmd.run_from_argv('kallithea celery worker', celery_args) | |||
|
42 | ||||
|
43 | def get_parser(self, prog_name): | |||
|
44 | parser = super(Command, self).get_parser(prog_name) | |||
|
45 | ||||
|
46 | parser.add_argument('celery_args', nargs=argparse.REMAINDER, | |||
|
47 | help="Pass extra options to Celery after a '--' separator", | |||
|
48 | ) | |||
|
49 | ||||
|
50 | return parser |
@@ -15,7 +15,7 b'' | |||||
15 | kallithea.lib.paster_commands.cleanup |
|
15 | kallithea.lib.paster_commands.cleanup | |
16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
17 |
|
17 | |||
18 |
cleanup-repos |
|
18 | cleanup-repos gearbox command for Kallithea | |
19 |
|
19 | |||
20 |
|
20 | |||
21 | This file was forked by the Kallithea project in July 2014. |
|
21 | This file was forked by the Kallithea project in July 2014. | |
@@ -40,15 +40,7 b' from kallithea.model.db import Ui' | |||||
40 |
|
40 | |||
41 |
|
41 | |||
42 | class Command(BasePasterCommand): |
|
42 | class Command(BasePasterCommand): | |
43 |
|
43 | """Kallithea: Cleanup of backup files of deleted repositories""" | ||
44 | max_args = 1 |
|
|||
45 | min_args = 1 |
|
|||
46 |
|
||||
47 | usage = "CONFIG_FILE" |
|
|||
48 | group_name = "Kallithea" |
|
|||
49 | takes_config_file = -1 |
|
|||
50 | parser = BasePasterCommand.standard_parser(verbose=True) |
|
|||
51 | summary = "Cleanup deleted repos" |
|
|||
52 |
|
44 | |||
53 | def _parse_older_than(self, val): |
|
45 | def _parse_older_than(self, val): | |
54 | regex = re.compile(r'((?P<days>\d+?)d)?((?P<hours>\d+?)h)?((?P<minutes>\d+?)m)?((?P<seconds>\d+?)s)?') |
|
46 | regex = re.compile(r'((?P<days>\d+?)d)?((?P<hours>\d+?)h)?((?P<minutes>\d+?)m)?((?P<seconds>\d+?)s)?') | |
@@ -72,10 +64,7 b' class Command(BasePasterCommand):' | |||||
72 | date_part = name[4:19] # 4:19 since we don't parse milliseconds |
|
64 | date_part = name[4:19] # 4:19 since we don't parse milliseconds | |
73 | return datetime.datetime.strptime(date_part, '%Y%m%d_%H%M%S') |
|
65 | return datetime.datetime.strptime(date_part, '%Y%m%d_%H%M%S') | |
74 |
|
66 | |||
75 |
def co |
|
67 | def take_action(self, args): | |
76 | #get SqlAlchemy session |
|
|||
77 | self._init_session() |
|
|||
78 |
|
||||
79 | repos_location = Ui.get_repos_location() |
|
68 | repos_location = Ui.get_repos_location() | |
80 | to_remove = [] |
|
69 | to_remove = [] | |
81 | for dn_, dirs, f in os.walk(safe_str(repos_location)): |
|
70 | for dn_, dirs, f in os.walk(safe_str(repos_location)): | |
@@ -97,7 +86,7 b' class Command(BasePasterCommand):' | |||||
97 |
|
86 | |||
98 | #filter older than (if present)! |
|
87 | #filter older than (if present)! | |
99 | now = datetime.datetime.now() |
|
88 | now = datetime.datetime.now() | |
100 |
older_than = |
|
89 | older_than = args.older_than | |
101 | if older_than: |
|
90 | if older_than: | |
102 | to_remove_filtered = [] |
|
91 | to_remove_filtered = [] | |
103 | older_than_date = self._parse_older_than(older_than) |
|
92 | older_than_date = self._parse_older_than(older_than) | |
@@ -111,7 +100,7 b' class Command(BasePasterCommand):' | |||||
111 | % (len(to_remove), older_than, older_than_date) |
|
100 | % (len(to_remove), older_than, older_than_date) | |
112 | else: |
|
101 | else: | |
113 | print 'Removing all %s deleted repos' % len(to_remove) |
|
102 | print 'Removing all %s deleted repos' % len(to_remove) | |
114 |
if |
|
103 | if args.dont_ask or not to_remove: | |
115 | # don't ask just remove ! |
|
104 | # don't ask just remove ! | |
116 | remove = True |
|
105 | remove = True | |
117 | else: |
|
106 | else: | |
@@ -127,8 +116,10 b' class Command(BasePasterCommand):' | |||||
127 | else: |
|
116 | else: | |
128 | print 'Nothing done, exiting...' |
|
117 | print 'Nothing done, exiting...' | |
129 |
|
118 | |||
130 |
def |
|
119 | def get_parser(self, prog_name): | |
131 | self.parser.add_option( |
|
120 | parser = super(Command, self).get_parser(prog_name) | |
|
121 | ||||
|
122 | parser.add_argument( | |||
132 | '--older-than', |
|
123 | '--older-than', | |
133 | action='store', |
|
124 | action='store', | |
134 | dest='older_than', |
|
125 | dest='older_than', | |
@@ -141,9 +132,11 b' class Command(BasePasterCommand):' | |||||
141 | "removed more than 30 days ago.") |
|
132 | "removed more than 30 days ago.") | |
142 | ) |
|
133 | ) | |
143 |
|
134 | |||
144 |
|
|
135 | parser.add_argument( | |
145 | '--dont-ask', |
|
136 | '--dont-ask', | |
146 | action="store_true", |
|
137 | action="store_true", | |
147 | dest="dont_ask", |
|
138 | dest="dont_ask", | |
148 | help="remove repositories without asking for confirmation." |
|
139 | help="remove repositories without asking for confirmation." | |
149 | ) |
|
140 | ) | |
|
141 | ||||
|
142 | return parser |
@@ -15,7 +15,7 b'' | |||||
15 | kallithea.lib.paster_commands.common |
|
15 | kallithea.lib.paster_commands.common | |
16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
17 |
|
17 | |||
18 |
Common code for |
|
18 | Common code for gearbox commands. | |
19 |
|
19 | |||
20 | This file was forked by the Kallithea project in July 2014. |
|
20 | This file was forked by the Kallithea project in July 2014. | |
21 | Original author and date, and relevant copyright and licensing information is below: |
|
21 | Original author and date, and relevant copyright and licensing information is below: | |
@@ -26,12 +26,11 b' Original author and date, and relevant c' | |||||
26 | """ |
|
26 | """ | |
27 |
|
27 | |||
28 | import os |
|
28 | import os | |
29 | import logging |
|
29 | import sys | |
|
30 | import logging.config | |||
30 |
|
31 | |||
31 | import paste |
|
32 | import paste.deploy | |
32 | from paste.script.command import Command, BadCommand |
|
33 | import gearbox.command | |
33 |
|
||||
34 | from kallithea.lib.utils import setup_cache_regions |
|
|||
35 |
|
34 | |||
36 |
|
35 | |||
37 | def ask_ok(prompt, retries=4, complaint='Yes or no please!'): |
|
36 | def ask_ok(prompt, retries=4, complaint='Yes or no please!'): | |
@@ -47,14 +46,14 b' def ask_ok(prompt, retries=4, complaint=' | |||||
47 | print complaint |
|
46 | print complaint | |
48 |
|
47 | |||
49 |
|
48 | |||
50 | class BasePasterCommand(Command): |
|
49 | class BasePasterCommand(gearbox.command.Command): | |
51 | """ |
|
50 | """ | |
52 |
Abstract Base Class for |
|
51 | Abstract Base Class for gearbox commands. | |
53 | """ |
|
52 | """ | |
54 | min_args = 1 |
|
53 | ||
55 | min_args_error = "Please provide a paster config file as an argument." |
|
54 | # override to control how much get_parser and run should do: | |
56 |
takes_config_file = |
|
55 | takes_config_file = True | |
57 |
requires_ |
|
56 | requires_db_session = True | |
58 |
|
57 | |||
59 | def run(self, args): |
|
58 | def run(self, args): | |
60 | """ |
|
59 | """ | |
@@ -62,46 +61,48 b' class BasePasterCommand(Command):' | |||||
62 |
|
61 | |||
63 | Checks for a config file argument and loads it. |
|
62 | Checks for a config file argument and loads it. | |
64 | """ |
|
63 | """ | |
65 | if len(args) < self.min_args: |
|
64 | if self.takes_config_file: | |
66 | raise BadCommand( |
|
65 | self._bootstrap_config(args.config_file) | |
67 | self.min_args_error % {'min_args': self.min_args, |
|
66 | if self.requires_db_session: | |
68 | 'actual_args': len(args)}) |
|
67 | self._init_session() | |
69 |
|
68 | |||
70 | # Decrement because we're going to lob off the first argument. |
|
69 | return super(BasePasterCommand, self).run(args) | |
71 | # @@ This is hacky |
|
70 | ||
72 | self.min_args -= 1 |
|
71 | def get_parser(self, prog_name): | |
73 | self.bootstrap_config(args[0]) |
|
72 | parser = super(BasePasterCommand, self).get_parser(prog_name) | |
74 | self.update_parser() |
|
|||
75 | return super(BasePasterCommand, self).run(args[1:]) |
|
|||
76 |
|
73 | |||
77 | def update_parser(self): |
|
74 | if self.takes_config_file: | |
|
75 | parser.add_argument("-c", "--config", | |||
|
76 | help='Kallithea .ini file with configuration of database etc', | |||
|
77 | dest='config_file', required=True) | |||
|
78 | ||||
|
79 | return parser | |||
|
80 | ||||
|
81 | def _bootstrap_config(self, config_file): | |||
78 | """ |
|
82 | """ | |
79 | Abstract method. Allows for the class's parser to be updated |
|
83 | Read the config file and initialize logging and the application. | |
80 | before the superclass's `run` method is called. Necessary to |
|
|||
81 | allow options/arguments to be passed through to the underlying |
|
|||
82 | celery command. |
|
|||
83 | """ |
|
|||
84 | raise NotImplementedError("Abstract Method.") |
|
|||
85 |
|
||||
86 | def bootstrap_config(self, conf): |
|
|||
87 | """ |
|
|||
88 | Loads the app configuration. |
|
|||
89 | """ |
|
84 | """ | |
90 | from tg import config as pylonsconfig |
|
85 | from tg import config as pylonsconfig | |
91 |
|
86 | |||
92 |
|
|
87 | path_to_ini_file = os.path.realpath(config_file) | |
93 |
conf = paste.deploy.appconfig('config:' + |
|
88 | conf = paste.deploy.appconfig('config:' + path_to_ini_file) | |
|
89 | logging.config.fileConfig(path_to_ini_file) | |||
94 | pylonsconfig.init_app(conf.global_conf, conf.local_conf) |
|
90 | pylonsconfig.init_app(conf.global_conf, conf.local_conf) | |
95 |
|
91 | |||
96 | def _init_session(self): |
|
92 | def _init_session(self): | |
97 | """ |
|
93 | """ | |
98 |
Init |
|
94 | Initialize SqlAlchemy Session from global config. | |
99 | """ |
|
95 | """ | |
100 | logging.config.fileConfig(self.path_to_ini_file) |
|
|||
101 |
|
96 | |||
102 | from tg import config |
|
97 | from tg import config | |
103 | from kallithea.model.base import init_model |
|
98 | from kallithea.model.base import init_model | |
104 | from kallithea.lib.utils2 import engine_from_config |
|
99 | from kallithea.lib.utils2 import engine_from_config | |
|
100 | from kallithea.lib.utils import setup_cache_regions | |||
105 | setup_cache_regions(config) |
|
101 | setup_cache_regions(config) | |
106 | engine = engine_from_config(config, 'sqlalchemy.') |
|
102 | engine = engine_from_config(config, 'sqlalchemy.') | |
107 | init_model(engine) |
|
103 | init_model(engine) | |
|
104 | ||||
|
105 | def error(self, msg, exitcode=1): | |||
|
106 | """Write error message and exit""" | |||
|
107 | sys.stderr.write('%s\n' % msg) | |||
|
108 | raise SystemExit(exitcode) |
@@ -22,37 +22,21 b' IIS installation tools for Kallithea' | |||||
22 | import os |
|
22 | import os | |
23 | import sys |
|
23 | import sys | |
24 | from paste.script.appinstall import AbstractInstallCommand |
|
24 | from paste.script.appinstall import AbstractInstallCommand | |
25 | from paste.script.command import BadCommand |
|
25 | ||
|
26 | from kallithea.lib.paster_commands.common import BasePasterCommand | |||
26 |
|
27 | |||
27 |
|
28 | |||
28 |
class Command( |
|
29 | class Command(BasePasterCommand): | |
29 | default_verbosity = 1 |
|
30 | '''Kallithea: Install into IIS using isapi-wsgi''' | |
30 | max_args = 1 |
|
|||
31 | min_args = 1 |
|
|||
32 | summary = 'Setup IIS given a config file' |
|
|||
33 | usage = 'CONFIG_FILE' |
|
|||
34 |
|
31 | |||
35 | description = ''' |
|
32 | requires_db_session = False | |
36 | Script for installing into IIS using isapi-wsgi. |
|
|||
37 | ''' |
|
|||
38 | parser = AbstractInstallCommand.standard_parser( |
|
|||
39 | simulate=True, quiet=True, interactive=True) |
|
|||
40 | parser.add_option('--virtualdir', |
|
|||
41 | action='store', |
|
|||
42 | dest='virtualdir', |
|
|||
43 | default='/', |
|
|||
44 | help='The virtual folder to install into on IIS') |
|
|||
45 |
|
33 | |||
46 |
def co |
|
34 | def take_action(self, args): | |
47 | config_spec = self.args[0] |
|
35 | config_file = os.path.abspath(args.config_file) | |
48 | if not config_spec.startswith('config:'): |
|
|||
49 | config_spec = 'config:' + config_spec |
|
|||
50 | config_file = config_spec[len('config:'):].split('#', 1)[0] |
|
|||
51 | config_file = os.path.join(os.getcwd(), config_file) |
|
|||
52 | try: |
|
36 | try: | |
53 | import isapi_wsgi |
|
37 | import isapi_wsgi | |
54 | except ImportError: |
|
38 | except ImportError: | |
55 |
|
|
39 | self.error('missing requirement: isapi-wsgi not installed') | |
56 |
|
40 | |||
57 | file = '''\ |
|
41 | file = '''\ | |
58 | # Created by Kallithea install_iis |
|
42 | # Created by Kallithea install_iis | |
@@ -92,7 +76,7 b" if __name__=='__main__':" | |||||
92 |
|
76 | |||
93 | outdata = file % { |
|
77 | outdata = file % { | |
94 | 'inifile': config_file.replace('\\', '\\\\'), |
|
78 | 'inifile': config_file.replace('\\', '\\\\'), | |
95 |
'virtualdir': |
|
79 | 'virtualdir': args.virtualdir, | |
96 | } |
|
80 | } | |
97 |
|
81 | |||
98 | dispatchfile = os.path.join(os.getcwd(), 'dispatch.py') |
|
82 | dispatchfile = os.path.join(os.getcwd(), 'dispatch.py') | |
@@ -102,3 +86,14 b" if __name__=='__main__':" | |||||
102 | print ('Run \'python "%s" install\' with administrative privileges ' |
|
86 | print ('Run \'python "%s" install\' with administrative privileges ' | |
103 | 'to generate the _dispatch.dll file and install it into the ' |
|
87 | 'to generate the _dispatch.dll file and install it into the ' | |
104 | 'default web site') % (dispatchfile,) |
|
88 | 'default web site') % (dispatchfile,) | |
|
89 | ||||
|
90 | def get_parser(self, prog_name): | |||
|
91 | parser = super(Command, self).get_parser(prog_name) | |||
|
92 | ||||
|
93 | parser.add_argument('--virtualdir', | |||
|
94 | action='store', | |||
|
95 | dest='virtualdir', | |||
|
96 | default='/', | |||
|
97 | help='The virtual folder to install into on IIS') | |||
|
98 | ||||
|
99 | return parser |
@@ -15,7 +15,7 b'' | |||||
15 | kallithea.lib.paster_commands.ishell |
|
15 | kallithea.lib.paster_commands.ishell | |
16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
17 |
|
17 | |||
18 |
interactive shell |
|
18 | interactive shell gearbox command for Kallithea | |
19 |
|
19 | |||
20 | This file was forked by the Kallithea project in July 2014. |
|
20 | This file was forked by the Kallithea project in July 2014. | |
21 | Original author and date, and relevant copyright and licensing information is below: |
|
21 | Original author and date, and relevant copyright and licensing information is below: | |
@@ -39,20 +39,9 b' from kallithea.lib.paster_commands.commo' | |||||
39 |
|
39 | |||
40 |
|
40 | |||
41 | class Command(BasePasterCommand): |
|
41 | class Command(BasePasterCommand): | |
42 |
|
42 | "Kallithea: Interactive Python shell" | ||
43 | max_args = 1 |
|
|||
44 | min_args = 1 |
|
|||
45 |
|
43 | |||
46 | usage = "CONFIG_FILE" |
|
44 | def take_action(self, args): | |
47 | group_name = "Kallithea" |
|
|||
48 | takes_config_file = -1 |
|
|||
49 | parser = BasePasterCommand.standard_parser(verbose=True) |
|
|||
50 | summary = "Interactive shell" |
|
|||
51 |
|
||||
52 | def command(self): |
|
|||
53 | #get SqlAlchemy session |
|
|||
54 | self._init_session() |
|
|||
55 |
|
||||
56 | try: |
|
45 | try: | |
57 | from IPython import embed |
|
46 | from IPython import embed | |
58 | from IPython.config.loader import Config |
|
47 | from IPython.config.loader import Config | |
@@ -62,6 +51,3 b' class Command(BasePasterCommand):' | |||||
62 | except ImportError: |
|
51 | except ImportError: | |
63 | print 'Kallithea ishell requires the IPython Python package' |
|
52 | print 'Kallithea ishell requires the IPython Python package' | |
64 | sys.exit(-1) |
|
53 | sys.exit(-1) | |
65 |
|
||||
66 | def update_parser(self): |
|
|||
67 | pass |
|
@@ -15,7 +15,7 b'' | |||||
15 | kallithea.lib.paster_commands.make_index |
|
15 | kallithea.lib.paster_commands.make_index | |
16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
17 |
|
17 | |||
18 |
make-index |
|
18 | make-index gearbox command for Kallithea | |
19 |
|
19 | |||
20 | This file was forked by the Kallithea project in July 2014. |
|
20 | This file was forked by the Kallithea project in July 2014. | |
21 | Original author and date, and relevant copyright and licensing information is below: |
|
21 | Original author and date, and relevant copyright and licensing information is below: | |
@@ -37,30 +37,20 b' from kallithea.lib.utils import load_rce' | |||||
37 |
|
37 | |||
38 |
|
38 | |||
39 | class Command(BasePasterCommand): |
|
39 | class Command(BasePasterCommand): | |
40 |
|
40 | "Kallithea: Create or update full text search index" | ||
41 | max_args = 1 |
|
|||
42 | min_args = 1 |
|
|||
43 |
|
41 | |||
44 | usage = "CONFIG_FILE" |
|
42 | def take_action(self, args): | |
45 | group_name = "Kallithea" |
|
43 | from pylons import config | |
46 | takes_config_file = -1 |
|
|||
47 | parser = BasePasterCommand.standard_parser(verbose=True) |
|
|||
48 | summary = "Creates or updates full text search index" |
|
|||
49 |
|
||||
50 | def command(self): |
|
|||
51 | #get SqlAlchemy session |
|
|||
52 | self._init_session() |
|
|||
53 | from tg import config |
|
|||
54 | index_location = config['index_dir'] |
|
44 | index_location = config['index_dir'] | |
55 | load_rcextensions(config['here']) |
|
45 | load_rcextensions(config['here']) | |
56 |
|
46 | |||
57 |
repo_location = |
|
47 | repo_location = args.repo_location \ | |
58 |
if |
|
48 | if args.repo_location else RepoModel().repos_path | |
59 |
repo_list = map(strip, |
|
49 | repo_list = map(strip, args.repo_list.split(',')) \ | |
60 |
if |
|
50 | if args.repo_list else None | |
61 |
|
51 | |||
62 |
repo_update_list = map(strip, |
|
52 | repo_update_list = map(strip, args.repo_update_list.split(',')) \ | |
63 |
if |
|
53 | if args.repo_update_list else None | |
64 |
|
54 | |||
65 | #====================================================================== |
|
55 | #====================================================================== | |
66 | # WHOOSH DAEMON |
|
56 | # WHOOSH DAEMON | |
@@ -74,33 +64,37 b' class Command(BasePasterCommand):' | |||||
74 | repo_location=repo_location, |
|
64 | repo_location=repo_location, | |
75 | repo_list=repo_list, |
|
65 | repo_list=repo_list, | |
76 | repo_update_list=repo_update_list) \ |
|
66 | repo_update_list=repo_update_list) \ | |
77 |
.run(full_index= |
|
67 | .run(full_index=args.full_index) | |
78 | l.release() |
|
68 | l.release() | |
79 | except LockHeld: |
|
69 | except LockHeld: | |
80 | sys.exit(1) |
|
70 | sys.exit(1) | |
81 |
|
71 | |||
82 |
def |
|
72 | def get_parser(self, prog_name): | |
83 | self.parser.add_option('--repo-location', |
|
73 | parser = super(Command, self).get_parser(prog_name) | |
|
74 | ||||
|
75 | parser.add_argument('--repo-location', | |||
84 | action='store', |
|
76 | action='store', | |
85 | dest='repo_location', |
|
77 | dest='repo_location', | |
86 | help="Specifies repositories location to index OPTIONAL", |
|
78 | help="Specifies repositories location to index OPTIONAL", | |
87 | ) |
|
79 | ) | |
88 |
|
|
80 | parser.add_argument('--index-only', | |
89 | action='store', |
|
81 | action='store', | |
90 | dest='repo_list', |
|
82 | dest='repo_list', | |
91 | help="Specifies a comma separated list of repositories " |
|
83 | help="Specifies a comma separated list of repositories " | |
92 | "to build index on. If not given all repositories " |
|
84 | "to build index on. If not given all repositories " | |
93 | "are scanned for indexing. OPTIONAL", |
|
85 | "are scanned for indexing. OPTIONAL", | |
94 | ) |
|
86 | ) | |
95 |
|
|
87 | parser.add_argument('--update-only', | |
96 | action='store', |
|
88 | action='store', | |
97 | dest='repo_update_list', |
|
89 | dest='repo_update_list', | |
98 | help="Specifies a comma separated list of repositories " |
|
90 | help="Specifies a comma separated list of repositories " | |
99 | "to re-build index on. OPTIONAL", |
|
91 | "to re-build index on. OPTIONAL", | |
100 | ) |
|
92 | ) | |
101 |
|
|
93 | parser.add_argument('-f', | |
102 | action='store_true', |
|
94 | action='store_true', | |
103 | dest='full_index', |
|
95 | dest='full_index', | |
104 | help="Specifies that index should be made full i.e" |
|
96 | help="Specifies that index should be made full i.e" | |
105 | " destroy old and build from scratch", |
|
97 | " destroy old and build from scratch", | |
106 | default=False) |
|
98 | default=False) | |
|
99 | ||||
|
100 | return parser |
@@ -15,7 +15,7 b'' | |||||
15 | kallithea.lib.paster_commands.make_rcextensions |
|
15 | kallithea.lib.paster_commands.make_rcextensions | |
16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
17 |
|
17 | |||
18 |
make-rcext |
|
18 | make-rcext gearbox command for Kallithea | |
19 |
|
19 | |||
20 | This file was forked by the Kallithea project in July 2014. |
|
20 | This file was forked by the Kallithea project in July 2014. | |
21 | Original author and date, and relevant copyright and licensing information is below: |
|
21 | Original author and date, and relevant copyright and licensing information is below: | |
@@ -34,23 +34,17 b' from kallithea.lib.paster_commands.commo' | |||||
34 |
|
34 | |||
35 |
|
35 | |||
36 | class Command(BasePasterCommand): |
|
36 | class Command(BasePasterCommand): | |
37 |
|
37 | """Kallithea: Write template file for extending Kallithea in Python | ||
38 | max_args = 1 |
|
|||
39 | min_args = 1 |
|
|||
40 |
|
|
38 | ||
41 | group_name = "Kallithea" |
|
39 | A rcextensions directory with a __init__.py file will be created next to | |
42 | takes_config_file = -1 |
|
40 | the ini file. Local customizations in that file will survive upgrades. | |
43 | parser = BasePasterCommand.standard_parser(verbose=True) |
|
41 | The file contains instructions on how it can be customized. | |
44 | summary = "Write template file for extending Kallithea in Python." |
|
42 | """ | |
45 | usage = "CONFIG_FILE" |
|
|||
46 | description = '''\ |
|
|||
47 | A rcextensions directory with a __init__.py file will be created next to |
|
|||
48 | the ini file. Local customizations in that file will survive upgrades. |
|
|||
49 | The file contains instructions on how it can be customized. |
|
|||
50 | ''' |
|
|||
51 |
|
43 | |||
52 | def command(self): |
|
44 | takes_config_file = False | |
53 | from tg import config |
|
45 | ||
|
46 | def take_action(self, args): | |||
|
47 | from pylons import config | |||
54 |
|
48 | |||
55 | here = config['here'] |
|
49 | here = config['here'] | |
56 | content = pkg_resources.resource_string( |
|
50 | content = pkg_resources.resource_string( | |
@@ -70,6 +64,3 b' class Command(BasePasterCommand):' | |||||
70 | with open(ext_file, 'wb') as f: |
|
64 | with open(ext_file, 'wb') as f: | |
71 | f.write(content) |
|
65 | f.write(content) | |
72 | print 'Wrote new extensions file to %s' % ext_file |
|
66 | print 'Wrote new extensions file to %s' % ext_file | |
73 |
|
||||
74 | def update_parser(self): |
|
|||
75 | pass |
|
@@ -15,7 +15,7 b'' | |||||
15 | kallithea.lib.paster_commands.repo_scan |
|
15 | kallithea.lib.paster_commands.repo_scan | |
16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
17 |
|
17 | |||
18 |
repo-scan |
|
18 | repo-scan gearbox command for Kallithea | |
19 |
|
19 | |||
20 | This file was forked by the Kallithea project in July 2014. |
|
20 | This file was forked by the Kallithea project in July 2014. | |
21 | Original author and date, and relevant copyright and licensing information is below: |
|
21 | Original author and date, and relevant copyright and licensing information is below: | |
@@ -35,20 +35,14 b' from kallithea.lib.utils import repo2db_' | |||||
35 |
|
35 | |||
36 |
|
36 | |||
37 | class Command(BasePasterCommand): |
|
37 | class Command(BasePasterCommand): | |
38 |
|
38 | """Kallithea: Scan file system for repositories | ||
39 | max_args = 1 |
|
|||
40 | min_args = 1 |
|
|||
41 |
|
|
39 | ||
42 | usage = "CONFIG_FILE" |
|
40 | Search under the repository root configured in the database, | |
43 | group_name = "Kallithea" |
|
41 | all new repositories, and report missing ones with an option of removing them. | |
44 | takes_config_file = -1 |
|
42 | """ | |
45 | parser = BasePasterCommand.standard_parser(verbose=True) |
|
|||
46 | summary = "Rescan default location for new repositories" |
|
|||
47 |
|
43 | |||
48 |
def co |
|
44 | def take_action(self, args): | |
49 | #get SqlAlchemy session |
|
45 | rm_obsolete = args.delete_obsolete | |
50 | self._init_session() |
|
|||
51 | rm_obsolete = self.options.delete_obsolete |
|
|||
52 | print 'Now scanning root location for new repos ...' |
|
46 | print 'Now scanning root location for new repos ...' | |
53 | added, removed = repo2db_mapper(ScmModel().repo_scan(), |
|
47 | added, removed = repo2db_mapper(ScmModel().repo_scan(), | |
54 | remove_obsolete=rm_obsolete) |
|
48 | remove_obsolete=rm_obsolete) | |
@@ -61,10 +55,14 b' class Command(BasePasterCommand):' | |||||
61 | else: |
|
55 | else: | |
62 | print 'Missing: %s' % removed |
|
56 | print 'Missing: %s' % removed | |
63 |
|
57 | |||
64 |
def |
|
58 | def get_parser(self, prog_name): | |
65 | self.parser.add_option( |
|
59 | parser = super(Command, self).get_parser(prog_name) | |
|
60 | ||||
|
61 | parser.add_argument( | |||
66 | '--delete-obsolete', |
|
62 | '--delete-obsolete', | |
67 | action='store_true', |
|
63 | action='store_true', | |
68 | help="Use this flag do delete repositories that are " |
|
64 | help="Use this flag do delete repositories that are " | |
69 | "present in Kallithea database but not on the filesystem", |
|
65 | "present in Kallithea database but not on the filesystem", | |
70 | ) |
|
66 | ) | |
|
67 | ||||
|
68 | return parser |
@@ -15,112 +15,93 b'' | |||||
15 | kallithea.lib.paster_commands.setup_db |
|
15 | kallithea.lib.paster_commands.setup_db | |
16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
17 |
|
17 | |||
18 |
Databaset setup |
|
18 | Databaset setup gearbox command for Kallithea | |
19 | """ |
|
19 | """ | |
20 |
|
20 | |||
21 |
|
21 | |||
22 | import os |
|
22 | import os | |
23 | import sys |
|
23 | import sys | |
24 | from paste.script.appinstall import AbstractInstallCommand |
|
24 | import paste.deploy | |
25 | from paste.script.command import BadCommand |
|
25 | ||
26 | from paste.deploy import appconfig |
|
26 | from kallithea.lib.db_manage import DbManage | |
|
27 | from kallithea.lib.paster_commands.common import BasePasterCommand | |||
|
28 | from kallithea.model.meta import Session | |||
27 |
|
29 | |||
28 |
|
30 | |||
29 | class Command(AbstractInstallCommand): |
|
31 | # This is almost like SetupAppCommand ... but we have to pass options and it is | |
|
32 | # thus simpler to drop websetup and reimplement everything | |||
|
33 | class Command(BasePasterCommand): | |||
|
34 | """Kallithea: Configure the database specified in the .ini file | |||
30 |
|
|
35 | ||
31 | default_verbosity = 1 |
|
36 | Setup Kallithea according to its configuration file. This is | |
32 | max_args = 1 |
|
37 | the second part of a two-phase web application installation | |
33 | min_args = 1 |
|
38 | process (the first phase is prepare-app). The setup process | |
34 | summary = "Setup an application, given a config file" |
|
39 | consist of things like setting up databases and creating the admin user | |
35 | usage = "CONFIG_FILE" |
|
|||
36 | group_name = "Kallithea" |
|
|||
37 |
|
||||
38 | description = """\ |
|
|||
39 | Setup Kallithea according to its configuration file. This is |
|
|||
40 | the second part of a two-phase web application installation |
|
|||
41 | process (the first phase is prepare-app). The setup process |
|
|||
42 | consist of things like setting up databases, creating super user |
|
|||
43 |
|
|
40 | """ | |
44 |
|
41 | |||
45 | parser = AbstractInstallCommand.standard_parser( |
|
42 | def get_description(self): | |
46 | simulate=True, quiet=True, interactive=True) |
|
43 | return self.__doc__.splitlines()[0] | |
47 | parser.add_option('--user', |
|
44 | ||
48 | action='store', |
|
45 | requires_db_session = False # only available after this command has been run | |
49 | dest='username', |
|
46 | ||
50 | default=None, |
|
47 | def get_parser(self, prog_name): | |
51 | help='Admin Username') |
|
48 | parser = super(Command, self).get_parser(prog_name) | |
52 | parser.add_option('--email', |
|
|||
53 | action='store', |
|
|||
54 | dest='email', |
|
|||
55 | default=None, |
|
|||
56 | help='Admin Email') |
|
|||
57 | parser.add_option('--password', |
|
|||
58 | action='store', |
|
|||
59 | dest='password', |
|
|||
60 | default=None, |
|
|||
61 | help='Admin password min 6 chars') |
|
|||
62 | parser.add_option('--repos', |
|
|||
63 | action='store', |
|
|||
64 | dest='repos_location', |
|
|||
65 | default=None, |
|
|||
66 | help='Absolute path to repositories location') |
|
|||
67 | parser.add_option('--name', |
|
|||
68 | action='store', |
|
|||
69 | dest='section_name', |
|
|||
70 | default=None, |
|
|||
71 | help='The name of the section to set up (default: app:main)') |
|
|||
72 | parser.add_option('--force-yes', |
|
|||
73 | action='store_true', |
|
|||
74 | dest='force_ask', |
|
|||
75 | default=None, |
|
|||
76 | help='Force yes to every question') |
|
|||
77 | parser.add_option('--force-no', |
|
|||
78 | action='store_false', |
|
|||
79 | dest='force_ask', |
|
|||
80 | default=None, |
|
|||
81 | help='Force no to every question') |
|
|||
82 | parser.add_option('--public-access', |
|
|||
83 | action='store_true', |
|
|||
84 | dest='public_access', |
|
|||
85 | default=None, |
|
|||
86 | help='Enable public access on this installation (default)') |
|
|||
87 | parser.add_option('--no-public-access', |
|
|||
88 | action='store_false', |
|
|||
89 | dest='public_access', |
|
|||
90 | default=None, |
|
|||
91 | help='Disable public access on this installation ') |
|
|||
92 |
|
49 | |||
93 | def command(self): |
|
50 | parser.add_argument('--user', | |
94 | config_spec = self.args[0] |
|
51 | action='store', | |
95 | section = self.options.section_name |
|
52 | dest='username', | |
96 | if section is None: |
|
53 | default=None, | |
97 | if '#' in config_spec: |
|
54 | help='Admin Username') | |
98 | config_spec, section = config_spec.split('#', 1) |
|
55 | parser.add_argument('--email', | |
99 | else: |
|
56 | action='store', | |
100 |
|
|
57 | dest='email', | |
101 | if not ':' in section: |
|
58 | default=None, | |
102 | plain_section = section |
|
59 | help='Admin Email') | |
103 | section = 'app:' + section |
|
60 | parser.add_argument('--password', | |
104 | else: |
|
61 | action='store', | |
105 | plain_section = section.split(':', 1)[0] |
|
62 | dest='password', | |
106 | if not config_spec.startswith('config:'): |
|
63 | default=None, | |
107 | config_spec = 'config:' + config_spec |
|
64 | help='Admin password min 6 chars') | |
108 | if plain_section != 'main': |
|
65 | parser.add_argument('--repos', | |
109 | config_spec += '#' + plain_section |
|
66 | action='store', | |
110 | config_file = config_spec[len('config:'):].split('#', 1)[0] |
|
67 | dest='repos_location', | |
111 | config_file = os.path.join(os.getcwd(), config_file) |
|
68 | default=None, | |
112 | self.logging_file_config(config_file) |
|
69 | help='Absolute path to repositories location') | |
113 | conf = appconfig(config_spec, relative_to=os.getcwd()) |
|
70 | parser.add_argument('--force-yes', | |
114 | ep_name = conf.context.entry_point_name |
|
71 | action='store_true', | |
115 | ep_group = conf.context.protocol |
|
72 | dest='force_ask', | |
116 | dist = conf.context.distribution |
|
73 | default=None, | |
117 | if dist is None: |
|
74 | help='Force yes to every question') | |
118 | raise BadCommand( |
|
75 | parser.add_argument('--force-no', | |
119 | "The section %r is not the application (probably a filter). " |
|
76 | action='store_false', | |
120 | "You should add #section_name, where section_name is the " |
|
77 | dest='force_ask', | |
121 | "section that configures your application" % plain_section) |
|
78 | default=None, | |
122 | installer = self.get_installer(dist, ep_group, ep_name) |
|
79 | help='Force no to every question') | |
123 | installer.setup_config( |
|
80 | parser.add_argument('--public-access', | |
124 | self, config_file, section, self.sysconfig_install_vars(installer)) |
|
81 | action='store_true', | |
125 | self.call_sysconfig_functions( |
|
82 | dest='public_access', | |
126 | 'post_setup_hook', installer, config_file) |
|
83 | default=None, | |
|
84 | help='Enable public access on this installation (default)') | |||
|
85 | parser.add_argument('--no-public-access', | |||
|
86 | action='store_false', | |||
|
87 | dest='public_access', | |||
|
88 | default=None, | |||
|
89 | help='Disable public access on this installation ') | |||
|
90 | ||||
|
91 | return parser | |||
|
92 | ||||
|
93 | def take_action(self, opts): | |||
|
94 | path_to_ini_file = os.path.realpath(opts.config_file) | |||
|
95 | conf = paste.deploy.appconfig('config:' + path_to_ini_file) | |||
|
96 | ||||
|
97 | dbconf = conf['sqlalchemy.url'] | |||
|
98 | dbmanage = DbManage(log_sql=True, dbconf=dbconf, root=conf['here'], | |||
|
99 | tests=False, cli_args=vars(opts)) | |||
|
100 | dbmanage.create_tables(override=True) | |||
|
101 | opts = dbmanage.config_prompt(None) | |||
|
102 | dbmanage.create_settings(opts) | |||
|
103 | dbmanage.create_default_user() | |||
|
104 | dbmanage.admin_prompt() | |||
|
105 | dbmanage.create_permissions() | |||
|
106 | dbmanage.populate_default_permissions() | |||
|
107 | Session().commit() |
@@ -15,7 +15,7 b'' | |||||
15 | kallithea.lib.paster_commands.update_repoinfo |
|
15 | kallithea.lib.paster_commands.update_repoinfo | |
16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
17 |
|
17 | |||
18 |
update-repoinfo |
|
18 | update-repoinfo gearbox command for Kallithea | |
19 |
|
19 | |||
20 | This file was forked by the Kallithea project in July 2014. |
|
20 | This file was forked by the Kallithea project in July 2014. | |
21 | Original author and date, and relevant copyright and licensing information is below: |
|
21 | Original author and date, and relevant copyright and licensing information is below: | |
@@ -38,47 +38,39 b' from kallithea.model.meta import Session' | |||||
38 |
|
38 | |||
39 |
|
39 | |||
40 | class Command(BasePasterCommand): |
|
40 | class Command(BasePasterCommand): | |
41 |
|
41 | "Kallithea: Update database cache of repository data" | ||
42 | max_args = 1 |
|
|||
43 | min_args = 1 |
|
|||
44 |
|
42 | |||
45 | usage = "CONFIG_FILE" |
|
43 | def take_action(self, args): | |
46 | group_name = "Kallithea" |
|
44 | if args.repo_update_list is None: | |
47 | takes_config_file = -1 |
|
|||
48 | parser = BasePasterCommand.standard_parser(verbose=True) |
|
|||
49 | summary = "Updates repositories caches for last changeset" |
|
|||
50 |
|
||||
51 | def command(self): |
|
|||
52 | #get SqlAlchemy session |
|
|||
53 | self._init_session() |
|
|||
54 |
|
||||
55 |
|
||||
56 | if self.options.repo_update_list is None: |
|
|||
57 | repo_list = Repository.query().all() |
|
45 | repo_list = Repository.query().all() | |
58 | else: |
|
46 | else: | |
59 | repo_names = [safe_unicode(n.strip()) |
|
47 | repo_names = [safe_unicode(n.strip()) | |
60 |
for n in |
|
48 | for n in args.repo_update_list.split(',')] | |
61 | repo_list = list(Repository.query() |
|
49 | repo_list = list(Repository.query() | |
62 | .filter(Repository.repo_name.in_(repo_names))) |
|
50 | .filter(Repository.repo_name.in_(repo_names))) | |
63 | for repo in repo_list: |
|
51 | for repo in repo_list: | |
64 | repo.update_changeset_cache() |
|
52 | repo.update_changeset_cache() | |
65 | Session().commit() |
|
53 | Session().commit() | |
66 |
|
54 | |||
67 |
if |
|
55 | if args.invalidate_cache: | |
68 | for r in repo_list: |
|
56 | for r in repo_list: | |
69 | r.set_invalidate() |
|
57 | r.set_invalidate() | |
70 | print 'Updated repo info and invalidated cache for %s repositories' % (len(repo_list)) |
|
58 | print 'Updated repo info and invalidated cache for %s repositories' % (len(repo_list)) | |
71 | else: |
|
59 | else: | |
72 | print 'Updated repo info for %s repositories' % (len(repo_list)) |
|
60 | print 'Updated repo info for %s repositories' % (len(repo_list)) | |
73 |
|
61 | |||
74 |
def |
|
62 | def get_parser(self, prog_name): | |
75 | self.parser.add_option('--update-only', |
|
63 | parser = super(Command, self).get_parser(prog_name) | |
|
64 | ||||
|
65 | parser.add_argument('--update-only', | |||
76 | action='store', |
|
66 | action='store', | |
77 | dest='repo_update_list', |
|
67 | dest='repo_update_list', | |
78 | help="Specifies a comma separated list of repositories " |
|
68 | help="Specifies a comma separated list of repositories " | |
79 | "to update last commit info for. OPTIONAL") |
|
69 | "to update last commit info for. OPTIONAL") | |
80 |
|
|
70 | parser.add_argument('--invalidate-cache', | |
81 | action='store_true', |
|
71 | action='store_true', | |
82 | dest='invalidate_cache', |
|
72 | dest='invalidate_cache', | |
83 | help="Trigger cache invalidation event for repos. " |
|
73 | help="Trigger cache invalidation event for repos. " | |
84 | "OPTIONAL") |
|
74 | "OPTIONAL") | |
|
75 | ||||
|
76 | return parser |
@@ -18,7 +18,7 b' kallithea.tests.other.manual_test_vcs_op' | |||||
18 | Test suite for making push/pull operations. |
|
18 | Test suite for making push/pull operations. | |
19 |
|
19 | |||
20 | Run it in two terminals:: |
|
20 | Run it in two terminals:: | |
21 |
|
|
21 | gearbox serve -c kallithea/tests/test.ini | |
22 | KALLITHEA_WHOOSH_TEST_DISABLE=1 KALLITHEA_NO_TMP_PATH=1 py.test kallithea/tests/other/manual_test_vcs_operations.py |
|
22 | KALLITHEA_WHOOSH_TEST_DISABLE=1 KALLITHEA_NO_TMP_PATH=1 py.test kallithea/tests/other/manual_test_vcs_operations.py | |
23 |
|
23 | |||
24 | You must have git > 1.8.1 for tests to work fine |
|
24 | You must have git > 1.8.1 for tests to work fine |
@@ -1,10 +1,10 b'' | |||||
1 | #!/bin/sh |
|
1 | #!/bin/sh | |
2 | psql -U postgres -h localhost -c 'drop database if exists kallithea;' |
|
2 | psql -U postgres -h localhost -c 'drop database if exists kallithea;' | |
3 | psql -U postgres -h localhost -c 'create database kallithea;' |
|
3 | psql -U postgres -h localhost -c 'create database kallithea;' | |
4 |
|
|
4 | gearbox setup-db -c server.ini --force-yes --user=username --password=qweqwe --email=username@example.com --repos=/home/username/repos --no-public-access | |
5 | API_KEY=`psql -R " " -A -U postgres -h localhost -c "select api_key from users where admin=TRUE" -d kallithea | awk '{print $2}'` |
|
5 | API_KEY=`psql -R " " -A -U postgres -h localhost -c "select api_key from users where admin=TRUE" -d kallithea | awk '{print $2}'` | |
6 | echo "run those after running server" |
|
6 | echo "run those after running server" | |
7 |
|
|
7 | gearbox serve -c server.ini --pid-file=server.pid --daemon | |
8 | sleep 3 |
|
8 | sleep 3 | |
9 | kallithea-api --apikey=$API_KEY --apihost=http://127.0.0.1:5001 create_user username:demo1 password:qweqwe email:demo1@example.com |
|
9 | kallithea-api --apikey=$API_KEY --apihost=http://127.0.0.1:5001 create_user username:demo1 password:qweqwe email:demo1@example.com | |
10 | kallithea-api --apikey=$API_KEY --apihost=http://127.0.0.1:5001 create_user username:demo2 password:qweqwe email:demo2@example.com |
|
10 | kallithea-api --apikey=$API_KEY --apihost=http://127.0.0.1:5001 create_user username:demo2 password:qweqwe email:demo2@example.com |
@@ -65,8 +65,8 b' pdebug = false' | |||||
65 | #smtp_use_tls = false |
|
65 | #smtp_use_tls = false | |
66 |
|
66 | |||
67 | [server:main] |
|
67 | [server:main] | |
68 | ## PASTE ## |
|
68 | ## Gearbox default web server ## | |
69 | #use = egg:Paste#http |
|
69 | #use = egg:gearbox#wsgiref | |
70 | ## nr of worker threads to spawn |
|
70 | ## nr of worker threads to spawn | |
71 | #threadpool_workers = 1 |
|
71 | #threadpool_workers = 1 | |
72 | ## max request before thread respawn |
|
72 | ## max request before thread respawn | |
@@ -74,6 +74,9 b' pdebug = false' | |||||
74 | ## option to use threads of process |
|
74 | ## option to use threads of process | |
75 | #use_threadpool = true |
|
75 | #use_threadpool = true | |
76 |
|
76 | |||
|
77 | ## Gearbox gevent web server ## | |||
|
78 | #use = egg:gearbox#gevent | |||
|
79 | ||||
77 | ## WAITRESS ## |
|
80 | ## WAITRESS ## | |
78 | use = egg:waitress#main |
|
81 | use = egg:waitress#main | |
79 | ## number of worker threads |
|
82 | ## number of worker threads | |
@@ -514,7 +517,7 b' script_location = kallithea:alembic' | |||||
514 | ################################ |
|
517 | ################################ | |
515 |
|
518 | |||
516 | [loggers] |
|
519 | [loggers] | |
517 | keys = root, routes, kallithea, sqlalchemy, beaker, templates, whoosh_indexer |
|
520 | keys = root, routes, kallithea, sqlalchemy, gearbox, beaker, templates, whoosh_indexer | |
518 |
|
521 | |||
519 | [handlers] |
|
522 | [handlers] | |
520 | keys = console, console_sql |
|
523 | keys = console, console_sql | |
@@ -555,6 +558,12 b' handlers =' | |||||
555 | qualname = kallithea |
|
558 | qualname = kallithea | |
556 | propagate = 1 |
|
559 | propagate = 1 | |
557 |
|
560 | |||
|
561 | [logger_gearbox] | |||
|
562 | level = DEBUG | |||
|
563 | handlers = | |||
|
564 | qualname = gearbox | |||
|
565 | propagate = 1 | |||
|
566 | ||||
558 | [logger_sqlalchemy] |
|
567 | [logger_sqlalchemy] | |
559 | level = INFO |
|
568 | level = INFO | |
560 | handlers = console_sql |
|
569 | handlers = console_sql |
@@ -104,7 +104,7 b' install_kallithea "$temp/from" "$from_re' | |||||
104 | cd "$temp/from" |
|
104 | cd "$temp/from" | |
105 | . "$temp/from-env/bin/activate" |
|
105 | . "$temp/from-env/bin/activate" | |
106 | announce "Initializing database..." |
|
106 | announce "Initializing database..." | |
107 |
quiet_if_ok |
|
107 | quiet_if_ok gearbox setup-db -c "$config_file" --repos="$temp/repos" --user=doe --email=doe@example.com --password=123456 --no-public-access --force-yes | |
108 | alembic -c "$config_file" current -v |
|
108 | alembic -c "$config_file" current -v | |
109 | ) |
|
109 | ) | |
110 |
|
110 |
@@ -36,6 +36,7 b" is_windows = __platform__ in ['Windows']" | |||||
36 |
|
36 | |||
37 | requirements = [ |
|
37 | requirements = [ | |
38 | "alembic>=0.8.0,<0.9", |
|
38 | "alembic>=0.8.0,<0.9", | |
|
39 | "GearBox<1", | |||
39 | "waitress>=0.8.8,<1.0", |
|
40 | "waitress>=0.8.8,<1.0", | |
40 | "webob>=1.7,<2", |
|
41 | "webob>=1.7,<2", | |
41 | "Pylons>=1.0.0,<=1.0.2", |
|
42 | "Pylons>=1.0.0,<=1.0.2", | |
@@ -132,7 +133,6 b' setuptools.setup(' | |||||
132 | url=__url__, |
|
133 | url=__url__, | |
133 | install_requires=requirements, |
|
134 | install_requires=requirements, | |
134 | classifiers=classifiers, |
|
135 | classifiers=classifiers, | |
135 | setup_requires=['PasteScript>=1.6.3'], |
|
|||
136 | data_files=data_files, |
|
136 | data_files=data_files, | |
137 | packages=packages, |
|
137 | packages=packages, | |
138 | include_package_data=True, |
|
138 | include_package_data=True, | |
@@ -142,7 +142,6 b' setuptools.setup(' | |||||
142 | ('templates/**.html', 'mako', {'input_encoding': 'utf-8'}), |
|
142 | ('templates/**.html', 'mako', {'input_encoding': 'utf-8'}), | |
143 | ('public/**', 'ignore', None)]}, |
|
143 | ('public/**', 'ignore', None)]}, | |
144 | zip_safe=False, |
|
144 | zip_safe=False, | |
145 | paster_plugins=['PasteScript', 'Pylons'], |
|
|||
146 | entry_points=""" |
|
145 | entry_points=""" | |
147 | [console_scripts] |
|
146 | [console_scripts] | |
148 | kallithea-api = kallithea.bin.kallithea_api:main |
|
147 | kallithea-api = kallithea.bin.kallithea_api:main | |
@@ -155,7 +154,7 b' setuptools.setup(' | |||||
155 | [paste.app_install] |
|
154 | [paste.app_install] | |
156 | main = pylons.util:PylonsInstaller |
|
155 | main = pylons.util:PylonsInstaller | |
157 |
|
156 | |||
158 | [paste.global_paster_command] |
|
157 | [gearbox.commands] | |
159 | setup-db=kallithea.lib.paster_commands.setup_db:Command |
|
158 | setup-db=kallithea.lib.paster_commands.setup_db:Command | |
160 | cleanup-repos=kallithea.lib.paster_commands.cleanup:Command |
|
159 | cleanup-repos=kallithea.lib.paster_commands.cleanup:Command | |
161 | update-repoinfo=kallithea.lib.paster_commands.update_repoinfo:Command |
|
160 | update-repoinfo=kallithea.lib.paster_commands.update_repoinfo:Command |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now