##// END OF EJS Templates
docs: updated documentation structure
marcink -
r3693:f470fd2e new-ui
parent child Browse files
Show More
@@ -0,0 +1,28 b''
1 .. _repo-admin-set:
2 .. _permissions-info-add-group-ref:
3
4 Repository Administration
5 =========================
6
7 Repository permissions in |RCE| can be managed in a number of different ways.
8 This overview should give you an insight into how you could adopt particular
9 settings for your needs:
10
11 * Global |repo| permissions: This allows you to set the default permissions
12 for each new |repo| created within |RCE|, see :ref:`repo-default-ref`. All
13 |repos| created will inherit these permissions unless explicitly configured.
14 * Individual |repo| permissions: To set individual |repo| permissions,
15 see :ref:`set-repo-perms`.
16 * Repository Group permissions: This allows you to define the permissions for
17 a group, and all |repos| created within that group will inherit the same
18 permissions.
19
20 .. toctree::
21
22 repo_admin/repo-perm-steps
23 repo_admin/repo-extra-fields
24 repo_admin/repo-hooks
25 repo_admin/repo-issue-tracker
26 repo_admin/repo-vcs
27 repo_admin/restore-deleted-repositories
28 repo_admin/repo-admin-tasks No newline at end of file
@@ -0,0 +1,24 b''
1 .. _repo-admin-tasks:
2
3 Common Admin Tasks for Repositories
4 -----------------------------------
5
6
7 Manually Force Delete Repository
8 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
9
10 In case of attached forks or pull-requests repositories should be archived.
11 Here is how to force delete a repository and remove all dependent objects
12
13
14 .. code-block:: bash
15
16 # starts the ishell interactive prompt
17 $ rccontrol ishell enterprise-1
18
19 .. code-block:: python
20
21 In [4]: from rhodecode.model.repo import RepoModel
22 In [3]: repo = Repository.get_by_repo_name('test_repos/repo_with_prs')
23 In [5]: RepoModel().delete(repo, forks='detach', pull_requests='delete')
24 In [6]: Session().commit()
@@ -0,0 +1,35 b''
1 .. _search-methods-ref:
2
3 search methods
4 ==============
5
6 search
7 ------
8
9 .. py:function:: search(apiuser, search_query, search_type, page_limit=<Optional:10>, page=<Optional:1>, search_sort=<Optional:'newfirst'>, repo_name=<Optional:None>, repo_group_name=<Optional:None>)
10
11 Fetch Full Text Search results using API.
12
13 :param apiuser: This is filled automatically from the |authtoken|.
14 :type apiuser: AuthUser
15 :param search_query: Search query.
16 :type search_query: str
17 :param search_type: Search type. The following are valid options:
18 * commit
19 * content
20 * path
21 :type search_type: str
22 :param page_limit: Page item limit, from 1 to 500. Default 10 items.
23 :type page_limit: Optional(int)
24 :param page: Page number. Default first page.
25 :type page: Optional(int)
26 :param search_sort: Search sort order. Default newfirst. The following are valid options:
27 * newfirst
28 * oldfirst
29 :type search_sort: Optional(str)
30 :param repo_name: Filter by one repo. Default is all.
31 :type repo_name: Optional(str)
32 :param repo_group_name: Filter by one repo group. Default is all.
33 :type repo_group_name: Optional(str)
34
35
@@ -1,77 +1,77 b''
1 .. _repo-xtra:
1 .. _repo-xtra:
2
2
3 Repository Extra Fields
3 Repository Extra Fields
4 =======================
4 =======================
5
5
6 Extra fields attached to a |repo| allow you to configure additional fields for
6 Extra fields attached to a |repo| allow you to configure additional fields for
7 each repository. This allows storing custom data per-repository.
7 each repository. This allows storing custom data per-repository.
8
8
9 It can be used in :ref:`integrations-webhook` or in |RCX|.
9 It can be used in :ref:`integrations-webhook` or in |RCX|.
10 To read more about |RCX|, see the :ref:`integrations-rcextensions` section.
10 To read more about |RCX|, see the :ref:`integrations-rcextensions` section.
11
11
12
12
13 Enabling Extra Fields
13 Enabling Extra Fields
14 ---------------------
14 ---------------------
15
15
16 To enable extra fields on |repos|, use the following steps:
16 To enable extra fields on |repos|, use the following steps:
17
17
18 1. Go to the :menuselection:`Admin --> Settings --> Visual` page.
18 1. Go to the :menuselection:`Admin --> Settings --> Visual` page.
19 2. Check the :guilabel:`Use repository extra fields` box.
19 2. Check the :guilabel:`Use repository extra fields` box.
20 3. Save your changes.
20 3. Save your changes.
21
21
22
22
23 Configuring Extra Fields
23 Configuring Extra Fields
24 ------------------------
24 ------------------------
25
25
26 To configure extra fields per repository, use the following steps:
26 To configure extra fields per repository, use the following steps:
27
27
28 1. Go to :menuselection:`Admin --> Repositories` and select :guilabel:`Edit`
28 1. Go to :menuselection:`Admin --> Repositories` and select :guilabel:`Edit`
29 beside the |repo| to which you wish to add extra fields.
29 beside the |repo| to which you wish to add extra fields.
30 2. On the |repo| settings page, select the :guilabel:`Extra fields` tab.
30 2. On the |repo| settings page, select the :guilabel:`Extra fields` tab.
31
31
32 .. image:: ../images/extra-repo-fields.png
32 .. image:: ../../images/extra-repo-fields.png
33
33
34 The most important is the `New field key` variable which under the value will
34 The most important is the `New field key` variable which under the value will
35 be stored. It needs to be unique for each repository. The label and description
35 be stored. It needs to be unique for each repository. The label and description
36 will be generated in repository settings where users can actually save some
36 will be generated in repository settings where users can actually save some
37 values inside generated extra fields.
37 values inside generated extra fields.
38
38
39
39
40 Example Usage in extensions
40 Example Usage in extensions
41 ---------------------------
41 ---------------------------
42
42
43 To use the extra fields in an extension, see the example below. For more
43 To use the extra fields in an extension, see the example below. For more
44 information and examples, see the :ref:`extensions-hooks-ref` section.
44 information and examples, see the :ref:`extensions-hooks-ref` section.
45
45
46 .. code-block:: python
46 .. code-block:: python
47
47
48 call = load_extension('http_notify.py')
48 call = load_extension('http_notify.py')
49 if call:
49 if call:
50 url = 'http://default.url' # <url for post data>
50 url = 'http://default.url' # <url for post data>
51
51
52 # possibly extract the URL from extra fields
52 # possibly extract the URL from extra fields
53 call = load_extension('extra_fields.py')
53 call = load_extension('extra_fields.py')
54 if call:
54 if call:
55 repo_extra_fields = call(**kwargs)
55 repo_extra_fields = call(**kwargs)
56 # now update if we have extra fields, they have precedence
56 # now update if we have extra fields, they have precedence
57 # this way users can store any configuration inside the database per
57 # this way users can store any configuration inside the database per
58 # repo
58 # repo
59 for key, data in repo_extra_fields.items():
59 for key, data in repo_extra_fields.items():
60 kwargs[key] = data['field_value']
60 kwargs[key] = data['field_value']
61
61
62 # an endpoint url data will be sent to, fetched from extra fields
62 # an endpoint url data will be sent to, fetched from extra fields
63 # if exists, or fallback to default
63 # if exists, or fallback to default
64 kwargs['URL'] = kwargs.pop('webhook_url', None) or url
64 kwargs['URL'] = kwargs.pop('webhook_url', None) or url
65
65
66 # fetch pushed commits, from commit_ids list
66 # fetch pushed commits, from commit_ids list
67 call = load_extension('extract_commits.py')
67 call = load_extension('extract_commits.py')
68 extracted_commits = {}
68 extracted_commits = {}
69 if call:
69 if call:
70 extracted_commits = call(**kwargs)
70 extracted_commits = call(**kwargs)
71 # store the commits for the next call chain
71 # store the commits for the next call chain
72 kwargs['COMMITS'] = extracted_commits
72 kwargs['COMMITS'] = extracted_commits
73
73
74 # set additional keys and values to be sent via POST to given URL
74 # set additional keys and values to be sent via POST to given URL
75 kwargs['caller_type'] = 'rhodecode'
75 kwargs['caller_type'] = 'rhodecode'
76 kwargs['date'] = time.time() # import time before
76 kwargs['date'] = time.time() # import time before
77 call(**kwargs)
77 call(**kwargs)
1 NO CONTENT: file renamed from docs/admin/repo-hooks.rst to docs/admin/repo_admin/repo-hooks.rst
NO CONTENT: file renamed from docs/admin/repo-hooks.rst to docs/admin/repo_admin/repo-hooks.rst
1 NO CONTENT: file renamed from docs/admin/repo-issue-tracker.rst to docs/admin/repo_admin/repo-issue-tracker.rst
NO CONTENT: file renamed from docs/admin/repo-issue-tracker.rst to docs/admin/repo_admin/repo-issue-tracker.rst
1 NO CONTENT: file renamed from docs/admin/repo-perm-steps.rst to docs/admin/repo_admin/repo-perm-steps.rst
NO CONTENT: file renamed from docs/admin/repo-perm-steps.rst to docs/admin/repo_admin/repo-perm-steps.rst
1 NO CONTENT: file renamed from docs/admin/repo-vcs.rst to docs/admin/repo_admin/repo-vcs.rst
NO CONTENT: file renamed from docs/admin/repo-vcs.rst to docs/admin/repo_admin/repo-vcs.rst
1 NO CONTENT: file renamed from docs/admin/restore-deleted-repositories.rst to docs/admin/repo_admin/restore-deleted-repositories.rst
NO CONTENT: file renamed from docs/admin/restore-deleted-repositories.rst to docs/admin/repo_admin/restore-deleted-repositories.rst
@@ -1,34 +1,32 b''
1 .. _rhodecode-admin-ref:
1 .. _rhodecode-admin-ref:
2
2
3 System Administration
3 System Administration
4 =====================
4 =====================
5
5
6 The following are the most common system administration tasks.
6 The following are the most common system administration tasks.
7
7
8 .. only:: latex
8 .. only:: latex
9
9
10 * :ref:`vcs-server`
10 * :ref:`vcs-server`
11 * :ref:`apache-ws-ref`
11 * :ref:`apache-ws-ref`
12 * :ref:`nginx-ws-ref`
12 * :ref:`nginx-ws-ref`
13 * :ref:`rhodecode-tuning-ref`
13 * :ref:`rhodecode-tuning-ref`
14 * :ref:`indexing-ref`
14 * :ref:`indexing-ref`
15 * :ref:`rhodecode-reset-ref`
15 * :ref:`rhodecode-reset-ref`
16
16
17 .. toctree::
17 .. toctree::
18
18
19 config-files-overview
19 system_admin/config-files-overview
20 vcs-server
20 system_admin/vcs-server
21 svn-http
21 system_admin/svn-http
22 svn-path-permissions
22 system_admin/svn-path-permissions
23 gunicorn-ssl-support
23 system_admin/gunicorn-ssl-support
24 apache-config
24 system_admin/apache-config
25 nginx-config
25 system_admin/nginx-config
26 backup-restore
26 system_admin/backup-restore
27 tuning-rhodecode
27 system_admin/tuning-rhodecode
28 indexing
28 system_admin/indexing
29 reset-information
29 system_admin/reset-information
30 enable-debug
30 system_admin/enable-debug
31 admin-tricks
31 system_admin/admin-tricks
32 cleanup-cmds
32 system_admin/cleanup-cmds
33 restore-deleted-repositories
34
@@ -1,264 +1,264 b''
1 .. _admin-tricks:
1 .. _admin-tricks:
2
2
3 One-time Admin Tasks
3 One-time Admin Tasks
4 --------------------
4 --------------------
5
5
6 * :ref:`web-analytics`
6 * :ref:`web-analytics`
7 * :ref:`admin-tricks-license`
7 * :ref:`admin-tricks-license`
8 * :ref:`announcements`
8 * :ref:`announcements`
9 * :ref:`md-rst`
9 * :ref:`md-rst`
10 * :ref:`repo-stats`
10 * :ref:`repo-stats`
11 * :ref:`server-side-merge`
11 * :ref:`server-side-merge`
12 * :ref:`remap-rescan`
12 * :ref:`remap-rescan`
13 * :ref:`custom-hooks`
13 * :ref:`custom-hooks`
14 * :ref:`clear-repo-cache`
14 * :ref:`clear-repo-cache`
15 * :ref:`set-repo-pub`
15 * :ref:`set-repo-pub`
16 * :ref:`ping`
16 * :ref:`ping`
17
17
18 .. _web-analytics:
18 .. _web-analytics:
19
19
20 Adding Web Analytics
20 Adding Web Analytics
21 ^^^^^^^^^^^^^^^^^^^^
21 ^^^^^^^^^^^^^^^^^^^^
22
22
23 If you wish to add a Google Analytics, or any other kind of tracker to your
23 If you wish to add a Google Analytics, or any other kind of tracker to your
24 |RCE| instance you can add the necessary codes to the header or footer
24 |RCE| instance you can add the necessary codes to the header or footer
25 section of each instance using the following steps:
25 section of each instance using the following steps:
26
26
27 1. From the |RCE| interface, select
27 1. From the |RCE| interface, select
28 :menuselection:`Admin --> Settings --> Global`
28 :menuselection:`Admin --> Settings --> Global`
29 2. To add a tracking code to you instance, enter it in the header or footer
29 2. To add a tracking code to you instance, enter it in the header or footer
30 section and select **Save**
30 section and select **Save**
31
31
32 Use the example templates in the drop-down menu to set up your configuration.
32 Use the example templates in the drop-down menu to set up your configuration.
33
33
34 .. _admin-tricks-license:
34 .. _admin-tricks-license:
35
35
36 Licence Key Management
36 Licence Key Management
37 ^^^^^^^^^^^^^^^^^^^^^^
37 ^^^^^^^^^^^^^^^^^^^^^^
38
38
39 To manage your license key, go to
39 To manage your license key, go to
40 :menuselection:`Admin --> Settings --> License`.
40 :menuselection:`Admin --> Settings --> License`.
41 On this page you can see the license key details. If you need a new license,
41 On this page you can see the license key details. If you need a new license,
42 or have questions about your current one, contact support@rhodecode.com
42 or have questions about your current one, contact support@rhodecode.com
43
43
44 .. _announcements:
44 .. _announcements:
45
45
46 Server-wide Announcements
46 Server-wide Announcements
47 ^^^^^^^^^^^^^^^^^^^^^^^^^
47 ^^^^^^^^^^^^^^^^^^^^^^^^^
48
48
49 If you need to make a server-wide announcement to all users,
49 If you need to make a server-wide announcement to all users,
50 you can add a message to be displayed using the following steps:
50 you can add a message to be displayed using the following steps:
51
51
52 1. From the |RCE| interface, select
52 1. From the |RCE| interface, select
53 :menuselection:`Admin --> Settings --> Global`
53 :menuselection:`Admin --> Settings --> Global`
54 2. To add a message that will be displayed to all users,
54 2. To add a message that will be displayed to all users,
55 select :guilabel:`Server Announcement` from the drop-down menu and
55 select :guilabel:`Server Announcement` from the drop-down menu and
56 change the ``var message = "TYPE YOUR MESSAGE HERE";`` example line.
56 change the ``var message = "TYPE YOUR MESSAGE HERE";`` example line.
57 3. Select :guilabel:`Save`, and you will see the message once your page
57 3. Select :guilabel:`Save`, and you will see the message once your page
58 refreshes.
58 refreshes.
59
59
60 .. image:: ../images/server-wide-announcement.png
60 .. image:: ../../images/server-wide-announcement.png
61 :alt: Server Wide Announcement
61 :alt: Server Wide Announcement
62
62
63 .. _md-rst:
63 .. _md-rst:
64
64
65
65
66 Suppress license warnings or errors
66 Suppress license warnings or errors
67 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
67 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
68
68
69 In case you're running on maximum allowed users, RhodeCode will display a
69 In case you're running on maximum allowed users, RhodeCode will display a
70 warning message on pages that you're close to the license limits.
70 warning message on pages that you're close to the license limits.
71 It's often not desired to show that all the time. Here's how you can suppress
71 It's often not desired to show that all the time. Here's how you can suppress
72 the license messages.
72 the license messages.
73
73
74 1. From the |RCE| interface, select
74 1. From the |RCE| interface, select
75 :menuselection:`Admin --> Settings --> Global`
75 :menuselection:`Admin --> Settings --> Global`
76 2. Select :guilabel:`Flash message filtering` from the drop-down menu.
76 2. Select :guilabel:`Flash message filtering` from the drop-down menu.
77 3. Select :guilabel:`Save`, and you will no longer see the license message
77 3. Select :guilabel:`Save`, and you will no longer see the license message
78 once your page refreshes.
78 once your page refreshes.
79
79
80 .. _admin-tricks-suppress-license-messages:
80 .. _admin-tricks-suppress-license-messages:
81
81
82
82
83 Markdown or RST Rendering
83 Markdown or RST Rendering
84 ^^^^^^^^^^^^^^^^^^^^^^^^^
84 ^^^^^^^^^^^^^^^^^^^^^^^^^
85
85
86 |RCE| can use `Markdown`_ or `reStructured Text`_ in commit message,
86 |RCE| can use `Markdown`_ or `reStructured Text`_ in commit message,
87 code review messages, and inline comments. To set the default to either,
87 code review messages, and inline comments. To set the default to either,
88 select your preference from the drop-down menu on the
88 select your preference from the drop-down menu on the
89 :menuselection:`Admin --> Settings --> Visual` page and select
89 :menuselection:`Admin --> Settings --> Visual` page and select
90 :guilabel:`Save settings`.
90 :guilabel:`Save settings`.
91
91
92 .. _repo-stats:
92 .. _repo-stats:
93
93
94 Enabling Repository Statistics
94 Enabling Repository Statistics
95 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
95 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
96
96
97 To enable |repo| statistics, use the following steps:
97 To enable |repo| statistics, use the following steps:
98
98
99 1. From the |RCE| interface, open
99 1. From the |RCE| interface, open
100 :menuselection:`Admin --> Repositories` and select
100 :menuselection:`Admin --> Repositories` and select
101 :guilabel:`Edit` beside the |repo| for which you wish to enable statistics.
101 :guilabel:`Edit` beside the |repo| for which you wish to enable statistics.
102 2. Check the :guilabel:`Enable statistics` box, and select :guilabel:`Save`
102 2. Check the :guilabel:`Enable statistics` box, and select :guilabel:`Save`
103
103
104 .. _server-side-merge:
104 .. _server-side-merge:
105
105
106 Enabling Server-side Merging
106 Enabling Server-side Merging
107 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
107 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
108
108
109 To enable server-side merging, use the following steps:
109 To enable server-side merging, use the following steps:
110
110
111 1. From the |RCE| interface, open :menuselection:`Admin --> Settings --> VCS`
111 1. From the |RCE| interface, open :menuselection:`Admin --> Settings --> VCS`
112 2. Check the :guilabel:`Server-side merge` box, and select
112 2. Check the :guilabel:`Server-side merge` box, and select
113 :guilabel:`Save Settings`
113 :guilabel:`Save Settings`
114
114
115 If you encounter slow performance with server-side merging enabled, check the
115 If you encounter slow performance with server-side merging enabled, check the
116 speed at which your server is performing actions. When server-side merging is
116 speed at which your server is performing actions. When server-side merging is
117 enabled, the following actions occurs on the server.
117 enabled, the following actions occurs on the server.
118
118
119 * A |pr| is created in the database.
119 * A |pr| is created in the database.
120 * A shadow |repo| is created as a working environment for the |pr|.
120 * A shadow |repo| is created as a working environment for the |pr|.
121 * On display, |RCE| checks if the |pr| can be merged.
121 * On display, |RCE| checks if the |pr| can be merged.
122
122
123 To check how fast the shadow |repo| creation is occurring on your server, use
123 To check how fast the shadow |repo| creation is occurring on your server, use
124 the following steps:
124 the following steps:
125
125
126 1. Log into your server and create a directory in your |repos| folder.
126 1. Log into your server and create a directory in your |repos| folder.
127 2. Clone a |repo| that is showing slow performance and time the action.
127 2. Clone a |repo| that is showing slow performance and time the action.
128
128
129 .. code-block:: bash
129 .. code-block:: bash
130
130
131 # One option is to use the time command
131 # One option is to use the time command
132 $ time hg clone SOURCE_REPO TARGET
132 $ time hg clone SOURCE_REPO TARGET
133
133
134 .. _remap-rescan:
134 .. _remap-rescan:
135
135
136 Remap and Rescan Repositories
136 Remap and Rescan Repositories
137 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
137 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
138
138
139 You may want to Remap and rescan the |repos| that |RCE| is managing to ensure
139 You may want to Remap and rescan the |repos| that |RCE| is managing to ensure
140 the system is always up-to-date. This is useful after importing, deleting,
140 the system is always up-to-date. This is useful after importing, deleting,
141 or carrying out general cleaning up operations. To do this use the
141 or carrying out general cleaning up operations. To do this use the
142 following steps:
142 following steps:
143
143
144 1. From the |RCE|, open
144 1. From the |RCE|, open
145 :menuselection:`Admin --> Settings --> Remap and rescan`
145 :menuselection:`Admin --> Settings --> Remap and rescan`
146 2. Click :guilabel:`Rescan Repositories`
146 2. Click :guilabel:`Rescan Repositories`
147
147
148 Check the additional options if needed:
148 Check the additional options if needed:
149
149
150 * :guilabel:`Destroy old data`: Useful for purging deleted repository
150 * :guilabel:`Destroy old data`: Useful for purging deleted repository
151 information from the database.
151 information from the database.
152 * :guilabel:`Invalidate cache for all repositories`: Use this to completely
152 * :guilabel:`Invalidate cache for all repositories`: Use this to completely
153 remap all |repos|. Useful when importing or migrating |repos| to ensure all
153 remap all |repos|. Useful when importing or migrating |repos| to ensure all
154 new information is picked up.
154 new information is picked up.
155
155
156 .. _custom-hooks:
156 .. _custom-hooks:
157
157
158 Adding Custom Hooks
158 Adding Custom Hooks
159 ^^^^^^^^^^^^^^^^^^^
159 ^^^^^^^^^^^^^^^^^^^
160
160
161 To add custom hooks to your instance, use the following steps:
161 To add custom hooks to your instance, use the following steps:
162
162
163 1. Open :menuselection:`Admin --> Settings --> Hooks`
163 1. Open :menuselection:`Admin --> Settings --> Hooks`
164 2. Add your custom hook details, you can use a file path to specify custom
164 2. Add your custom hook details, you can use a file path to specify custom
165 hook scripts, for example:
165 hook scripts, for example:
166 ``pretxnchangegroup.example`` with value ``python:/path/to/custom_hook.py:my_func_name``
166 ``pretxnchangegroup.example`` with value ``python:/path/to/custom_hook.py:my_func_name``
167 3. Select :guilabel:`Save`
167 3. Select :guilabel:`Save`
168
168
169 Also, see the RhodeCode Extensions section of the :ref:`rc-tools` guide. RhodeCode
169 Also, see the RhodeCode Extensions section of the :ref:`rc-tools` guide. RhodeCode
170 Extensions can be used to add additional hooks to your instance and comes
170 Extensions can be used to add additional hooks to your instance and comes
171 with a number of pre-built plugins if you chose to install them.
171 with a number of pre-built plugins if you chose to install them.
172
172
173 .. _clear-repo-cache:
173 .. _clear-repo-cache:
174
174
175 Clearing |repo| cache
175 Clearing |repo| cache
176 ^^^^^^^^^^^^^^^^^^^^^
176 ^^^^^^^^^^^^^^^^^^^^^
177
177
178 If you need to clear the cache for a particular |repo|, use the following steps:
178 If you need to clear the cache for a particular |repo|, use the following steps:
179
179
180 1. Open :menuselection:`Admin --> Repositories` and select :guilabel:`Edit`
180 1. Open :menuselection:`Admin --> Repositories` and select :guilabel:`Edit`
181 beside the |repo| whose cache you wish to clear.
181 beside the |repo| whose cache you wish to clear.
182 2. On the |repo| settings page, go to the :guilabel:`Caches` tab and select
182 2. On the |repo| settings page, go to the :guilabel:`Caches` tab and select
183 :guilabel:`Invalidate repository cache`.
183 :guilabel:`Invalidate repository cache`.
184
184
185 .. _set-lang:
185 .. _set-lang:
186
186
187 Changing Default Language
187 Changing Default Language
188 ^^^^^^^^^^^^^^^^^^^^^^^^^
188 ^^^^^^^^^^^^^^^^^^^^^^^^^
189
189
190 To change the default language of a |RCE| instance, change the language code
190 To change the default language of a |RCE| instance, change the language code
191 in the :file:`/home/{user}/.rccontrol/{instance-id}/rhodecode.ini` file. To
191 in the :file:`/home/{user}/.rccontrol/{instance-id}/rhodecode.ini` file. To
192 do this, use the following steps.
192 do this, use the following steps.
193
193
194 1. Open the :file:`rhodecode.ini` file and set the required language code.
194 1. Open the :file:`rhodecode.ini` file and set the required language code.
195
195
196 .. code-block:: ini
196 .. code-block:: ini
197
197
198 ## Optional Languages
198 ## Optional Languages
199 ## en(default), de, fr, it, ja, pl, pt, ru, zh
199 ## en(default), de, fr, it, ja, pl, pt, ru, zh
200 lang = de
200 lang = de
201
201
202 2. Restart the |RCE| instance and check that the language has been updated.
202 2. Restart the |RCE| instance and check that the language has been updated.
203
203
204 .. code-block:: bash
204 .. code-block:: bash
205
205
206 $ rccontrol restart enterprise-2
206 $ rccontrol restart enterprise-2
207 Instance "enterprise-2" successfully stopped.
207 Instance "enterprise-2" successfully stopped.
208 Instance "enterprise-2" successfully started.
208 Instance "enterprise-2" successfully started.
209
209
210 .. image:: ../images/language.png
210 .. image:: ../../images/language.png
211
211
212 .. _set-repo-pub:
212 .. _set-repo-pub:
213
213
214 Setting Repositories to Publish
214 Setting Repositories to Publish
215 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
215 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
216
216
217 To automatically promote your local |repos| to public after pushing to |RCE|,
217 To automatically promote your local |repos| to public after pushing to |RCE|,
218 enable the :guilabel:`Set repositories as publishing` option on the
218 enable the :guilabel:`Set repositories as publishing` option on the
219 :menuselection:`Admin --> Settings --> VCS` page.
219 :menuselection:`Admin --> Settings --> VCS` page.
220
220
221 .. note::
221 .. note::
222
222
223 This option is enabled by default on most |RCE| versions, but if upgrading
223 This option is enabled by default on most |RCE| versions, but if upgrading
224 from a 1.7.x version it could be disabled on upgrade due to inheriting
224 from a 1.7.x version it could be disabled on upgrade due to inheriting
225 older default settings.
225 older default settings.
226
226
227 .. _ping:
227 .. _ping:
228
228
229 Pinging the |RCE| Server
229 Pinging the |RCE| Server
230 ^^^^^^^^^^^^^^^^^^^^^^^^
230 ^^^^^^^^^^^^^^^^^^^^^^^^
231
231
232 You can check the IP Address of your |RCE| instance using the
232 You can check the IP Address of your |RCE| instance using the
233 following URL: ``{instance-URL}/_admin/ping``.
233 following URL: ``{instance-URL}/_admin/ping``.
234
234
235 .. code-block:: bash
235 .. code-block:: bash
236
236
237 $ curl https://your.rhodecode.url/_admin/ping
237 $ curl https://your.rhodecode.url/_admin/ping
238 pong[rce-7880] => 203.0.113.23
238 pong[rce-7880] => 203.0.113.23
239
239
240 .. _Markdown: http://daringfireball.net/projects/markdown/
240 .. _Markdown: http://daringfireball.net/projects/markdown/
241 .. _reStructured Text: http://docutils.sourceforge.net/docs/index.html
241 .. _reStructured Text: http://docutils.sourceforge.net/docs/index.html
242
242
243
243
244 Unarchiving a repository
244 Unarchiving a repository
245 ^^^^^^^^^^^^^^^^^^^^^^^^^
245 ^^^^^^^^^^^^^^^^^^^^^^^^^
246
246
247 Archive operation for the repository is similar as delete. Archive keeps the data for future references
247 Archive operation for the repository is similar as delete. Archive keeps the data for future references
248 but makes the repository read-only. After archiving the repository it shouldn't be modified in any way.
248 but makes the repository read-only. After archiving the repository it shouldn't be modified in any way.
249 This is why repository settings are disabled for an archived repository.
249 This is why repository settings are disabled for an archived repository.
250
250
251 If there's a need for unarchiving a repository for some reasons, the interactive
251 If there's a need for unarchiving a repository for some reasons, the interactive
252 ishell interface should be used.
252 ishell interface should be used.
253
253
254 .. code-block:: bash
254 .. code-block:: bash
255
255
256 # Open iShell from the terminal
256 # Open iShell from the terminal
257 $ rccontrol ishell enterprise-1/community-1
257 $ rccontrol ishell enterprise-1/community-1
258
258
259 .. code-block:: python
259 .. code-block:: python
260
260
261 # Set repository as un-archived
261 # Set repository as un-archived
262 In [1]: repo = Repository.get_by_repo_name('SOME_REPO_NAME')
262 In [1]: repo = Repository.get_by_repo_name('SOME_REPO_NAME')
263 In [2]: repo.archived = False
263 In [2]: repo.archived = False
264 In [3]: Session().add(repo);Session().commit()
264 In [3]: Session().add(repo);Session().commit()
@@ -1,14 +1,14 b''
1 .. _apache-ws-ref:
1 .. _apache-ws-ref:
2
2
3 Apache HTTP Server Configuration
3 Apache HTTP Server Configuration
4 --------------------------------
4 --------------------------------
5
5
6 To set up your Apache Web Server for optimal performance and security, use
6 To set up your Apache Web Server for optimal performance and security, use
7 the information in the following sections.
7 the information in the following sections.
8
8
9 .. toctree::
9 .. toctree::
10
10
11 apache-conf-example
11 apache/apache-conf-example
12 apache-diffie-hellman
12 apache/apache-diffie-hellman
13 apache-subdirectory
13 apache/apache-subdirectory
14 apache-wsgi-coding
14 apache/apache-wsgi-coding
1 NO CONTENT: file renamed from docs/admin/apache-conf-example.rst to docs/admin/system_admin/apache/apache-conf-example.rst
NO CONTENT: file renamed from docs/admin/apache-conf-example.rst to docs/admin/system_admin/apache/apache-conf-example.rst
1 NO CONTENT: file renamed from docs/admin/apache-diffie-hellman.rst to docs/admin/system_admin/apache/apache-diffie-hellman.rst
NO CONTENT: file renamed from docs/admin/apache-diffie-hellman.rst to docs/admin/system_admin/apache/apache-diffie-hellman.rst
1 NO CONTENT: file renamed from docs/admin/apache-subdirectory.rst to docs/admin/system_admin/apache/apache-subdirectory.rst
NO CONTENT: file renamed from docs/admin/apache-subdirectory.rst to docs/admin/system_admin/apache/apache-subdirectory.rst
1 NO CONTENT: file renamed from docs/admin/apache-wsgi-coding.rst to docs/admin/system_admin/apache/apache-wsgi-coding.rst
NO CONTENT: file renamed from docs/admin/apache-wsgi-coding.rst to docs/admin/system_admin/apache/apache-wsgi-coding.rst
1 NO CONTENT: file renamed from docs/admin/backup-restore.rst to docs/admin/system_admin/backup-restore.rst
NO CONTENT: file renamed from docs/admin/backup-restore.rst to docs/admin/system_admin/backup-restore.rst
1 NO CONTENT: file renamed from docs/admin/cleanup-cmds.rst to docs/admin/system_admin/cleanup-cmds.rst
NO CONTENT: file renamed from docs/admin/cleanup-cmds.rst to docs/admin/system_admin/cleanup-cmds.rst
1 NO CONTENT: file renamed from docs/admin/config-files-overview.rst to docs/admin/system_admin/config-files-overview.rst
NO CONTENT: file renamed from docs/admin/config-files-overview.rst to docs/admin/system_admin/config-files-overview.rst
1 NO CONTENT: file renamed from docs/admin/enable-debug.rst to docs/admin/system_admin/enable-debug.rst
NO CONTENT: file renamed from docs/admin/enable-debug.rst to docs/admin/system_admin/enable-debug.rst
1 NO CONTENT: file renamed from docs/admin/gunicorn-ssl-support.rst to docs/admin/system_admin/gunicorn-ssl-support.rst
NO CONTENT: file renamed from docs/admin/gunicorn-ssl-support.rst to docs/admin/system_admin/gunicorn-ssl-support.rst
1 NO CONTENT: file renamed from docs/admin/indexing.rst to docs/admin/system_admin/indexing.rst
NO CONTENT: file renamed from docs/admin/indexing.rst to docs/admin/system_admin/indexing.rst
@@ -1,14 +1,14 b''
1 .. _nginx-ws-ref:
1 .. _nginx-ws-ref:
2
2
3 Nginx HTTP Server Configuration
3 Nginx HTTP Server Configuration
4 -------------------------------
4 -------------------------------
5
5
6 To set up your Nginx Web Server for optimal performance and security, use
6 To set up your Nginx Web Server for optimal performance and security, use
7 the information in the following sections.
7 the information in the following sections.
8
8
9 .. toctree::
9 .. toctree::
10
10
11 nginx-config-example
11 nginx/nginx-config-example
12 nginx-diffie-hellman
12 nginx/nginx-diffie-hellman
13 nginx-proxy-conf
13 nginx/nginx-proxy-conf
14 nginx-url-prefix
14 nginx/nginx-url-prefix
1 NO CONTENT: file renamed from docs/admin/nginx-config-example.rst to docs/admin/system_admin/nginx/nginx-config-example.rst
NO CONTENT: file renamed from docs/admin/nginx-config-example.rst to docs/admin/system_admin/nginx/nginx-config-example.rst
1 NO CONTENT: file renamed from docs/admin/nginx-diffie-hellman.rst to docs/admin/system_admin/nginx/nginx-diffie-hellman.rst
NO CONTENT: file renamed from docs/admin/nginx-diffie-hellman.rst to docs/admin/system_admin/nginx/nginx-diffie-hellman.rst
1 NO CONTENT: file renamed from docs/admin/nginx-proxy-conf.rst to docs/admin/system_admin/nginx/nginx-proxy-conf.rst
NO CONTENT: file renamed from docs/admin/nginx-proxy-conf.rst to docs/admin/system_admin/nginx/nginx-proxy-conf.rst
1 NO CONTENT: file renamed from docs/admin/nginx-url-prefix.rst to docs/admin/system_admin/nginx/nginx-url-prefix.rst
NO CONTENT: file renamed from docs/admin/nginx-url-prefix.rst to docs/admin/system_admin/nginx/nginx-url-prefix.rst
1 NO CONTENT: file renamed from docs/admin/reset-information.rst to docs/admin/system_admin/reset-information.rst
NO CONTENT: file renamed from docs/admin/reset-information.rst to docs/admin/system_admin/reset-information.rst
1 NO CONTENT: file renamed from docs/admin/svn-http.rst to docs/admin/system_admin/svn-http.rst
NO CONTENT: file renamed from docs/admin/svn-http.rst to docs/admin/system_admin/svn-http.rst
1 NO CONTENT: file renamed from docs/admin/svn-path-permissions.rst to docs/admin/system_admin/svn-path-permissions.rst
NO CONTENT: file renamed from docs/admin/svn-path-permissions.rst to docs/admin/system_admin/svn-path-permissions.rst
@@ -1,21 +1,21 b''
1 .. _rhodecode-tuning-ref:
1 .. _rhodecode-tuning-ref:
2
2
3 Tuning |RCE|
3 Tuning |RCE|
4 ============
4 ============
5
5
6 To customize your |RCE| |version| installation for maximum performance you
6 To customize your |RCE| |version| installation for maximum performance you
7 may find some of the following methods useful.
7 may find some of the following methods useful.
8
8
9 .. toctree::
9 .. toctree::
10
10
11 tuning-gunicorn
11 tuning/tuning-gunicorn
12 tuning-vcs-memory-cache
12 tuning/tuning-vcs-memory-cache
13 tuning-user-sessions-performance
13 tuning/tuning-user-sessions-performance
14 tuning-increase-db-performance
14 tuning/tuning-increase-db-performance
15 tuning-scale-horizontally-cluster
15 tuning/tuning-scale-horizontally-cluster
16 tuning-mount-cache-memory
16 tuning/tuning-mount-cache-memory
17 tuning-change-encoding
17 tuning/tuning-change-encoding
18 tuning-change-large-file-dir
18 tuning/tuning-change-large-file-dir
19 tuning-change-lfs-dir
19 tuning/tuning-change-lfs-dir
20 tuning-hg-auth-loop
20 tuning/tuning-hg-auth-loop
21
21
1 NO CONTENT: file renamed from docs/admin/tuning-change-encoding.rst to docs/admin/system_admin/tuning/tuning-change-encoding.rst
NO CONTENT: file renamed from docs/admin/tuning-change-encoding.rst to docs/admin/system_admin/tuning/tuning-change-encoding.rst
1 NO CONTENT: file renamed from docs/admin/tuning-change-large-file-dir.rst to docs/admin/system_admin/tuning/tuning-change-large-file-dir.rst
NO CONTENT: file renamed from docs/admin/tuning-change-large-file-dir.rst to docs/admin/system_admin/tuning/tuning-change-large-file-dir.rst
1 NO CONTENT: file renamed from docs/admin/tuning-change-lfs-dir.rst to docs/admin/system_admin/tuning/tuning-change-lfs-dir.rst
NO CONTENT: file renamed from docs/admin/tuning-change-lfs-dir.rst to docs/admin/system_admin/tuning/tuning-change-lfs-dir.rst
@@ -1,126 +1,126 b''
1 .. _increase-gunicorn:
1 .. _increase-gunicorn:
2
2
3 Configure Gunicorn Workers
3 Configure Gunicorn Workers
4 --------------------------
4 --------------------------
5
5
6
6
7 |RCE| comes with `Gunicorn`_ which is a Python WSGI HTTP Server for UNIX.
7 |RCE| comes with `Gunicorn`_ which is a Python WSGI HTTP Server for UNIX.
8
8
9 To improve |RCE| performance you can increase the number of `Gunicorn`_ workers.
9 To improve |RCE| performance you can increase the number of `Gunicorn`_ workers.
10 This allows to handle more connections concurrently, and provide better
10 This allows to handle more connections concurrently, and provide better
11 responsiveness and performance.
11 responsiveness and performance.
12
12
13 By default during installation |RCC| tries to detect how many CPUs are
13 By default during installation |RCC| tries to detect how many CPUs are
14 available in the system, and set the number workers based on that information.
14 available in the system, and set the number workers based on that information.
15 However sometimes it's better to manually set the number of workers.
15 However sometimes it's better to manually set the number of workers.
16
16
17 To do this, use the following steps:
17 To do this, use the following steps:
18
18
19 1. Open the :file:`home/{user}/.rccontrol/{instance-id}/rhodecode.ini` file.
19 1. Open the :file:`home/{user}/.rccontrol/{instance-id}/rhodecode.ini` file.
20 2. In the ``[server:main]`` section, change the number of Gunicorn
20 2. In the ``[server:main]`` section, change the number of Gunicorn
21 ``workers`` using the following default formula :math:`(2 * Cores) + 1`.
21 ``workers`` using the following default formula :math:`(2 * Cores) + 1`.
22 We however not recommend using more than 8-12 workers per server. It's better
22 We however not recommend using more than 8-12 workers per server. It's better
23 to start using the :ref:`scale-horizontal-cluster` in case that performance
23 to start using the :ref:`scale-horizontal-cluster` in case that performance
24 with 8-12 workers is not enough.
24 with 8-12 workers is not enough.
25
25
26 .. code-block:: ini
26 .. code-block:: ini
27
27
28 use = egg:gunicorn#main
28 use = egg:gunicorn#main
29 ## Sets the number of process workers. You must set `instance_id = *`
29 ## Sets the number of process workers. You must set `instance_id = *`
30 ## when this option is set to more than one worker, recommended
30 ## when this option is set to more than one worker, recommended
31 ## value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers
31 ## value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers
32 ## The `instance_id = *` must be set in the [app:main] section below
32 ## The `instance_id = *` must be set in the [app:main] section below
33 workers = 4
33 workers = 4
34 ## process name
34 ## process name
35 proc_name = rhodecode
35 proc_name = rhodecode
36 ## type of worker class, one of sync, gevent
36 ## type of worker class, one of sync, gevent
37 ## recommended for bigger setup is using of of other than sync one
37 ## recommended for bigger setup is using of of other than sync one
38 worker_class = sync
38 worker_class = sync
39 ## The maximum number of simultaneous clients. Valid only for Gevent
39 ## The maximum number of simultaneous clients. Valid only for Gevent
40 #worker_connections = 10
40 #worker_connections = 10
41 ## max number of requests that worker will handle before being gracefully
41 ## max number of requests that worker will handle before being gracefully
42 ## restarted, could prevent memory leaks
42 ## restarted, could prevent memory leaks
43 max_requests = 1000
43 max_requests = 1000
44 max_requests_jitter = 30
44 max_requests_jitter = 30
45 ## amount of time a worker can spend with handling a request before it
45 ## amount of time a worker can spend with handling a request tuning-change-lfs-dir.before it
46 ## gets killed and restarted. Set to 6hrs
46 ## gets killed and restarted. Set to 6hrs
47 timeout = 21600
47 timeout = 21600
48
48
49 3. In the ``[app:main]`` section, set the ``instance_id`` property to ``*``.
49 3. In the ``[app:main]`` section, set the ``instance_id`` property to ``*``.
50
50
51 .. code-block:: ini
51 .. code-block:: ini
52
52
53 # In the [app:main] section
53 # In the [app:main] section
54 [app:main]
54 [app:main]
55 # You must set `instance_id = *`
55 # You must set `instance_id = *`
56 instance_id = *
56 instance_id = *
57
57
58 4. Change the VCSServer workers too. Open the
58 4. Change the VCSServer workers too. Open the
59 :file:`home/{user}/.rccontrol/{instance-id}/vcsserver.ini` file.
59 :file:`home/{user}/.rccontrol/{instance-id}/vcsserver.ini` file.
60
60
61 5. In the ``[server:main]`` section, increase the number of Gunicorn
61 5. In the ``[server:main]`` section, increase the number of Gunicorn
62 ``workers`` using the following formula :math:`(2 * Cores) + 1`.
62 ``workers`` using the following formula :math:`(2 * Cores) + 1`.
63
63
64 .. code-block:: ini
64 .. code-block:: ini
65
65
66 ## run with gunicorn --log-config vcsserver.ini --paste vcsserver.ini
66 ## run with gunicorn --log-config vcsserver.ini --paste vcsserver.ini
67 use = egg:gunicorn#main
67 use = egg:gunicorn#main
68 ## Sets the number of process workers. Recommended
68 ## Sets the number of process workers. Recommended
69 ## value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers
69 ## value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers
70 workers = 4
70 workers = 4
71 ## process name
71 ## process name
72 proc_name = rhodecode_vcsserver
72 proc_name = rhodecode_vcsserver
73 ## type of worker class, currently `sync` is the only option allowed.
73 ## type of worker class, currently `sync` is the only option allowed.
74 worker_class = sync
74 worker_class = sync
75 ## The maximum number of simultaneous clients. Valid only for Gevent
75 ## The maximum number of simultaneous clients. Valid only for Gevent
76 #worker_connections = 10
76 #worker_connections = 10
77 ## max number of requests that worker will handle before being gracefully
77 ## max number of requests that worker will handle before being gracefully
78 ## restarted, could prevent memory leaks
78 ## restarted, could prevent memory leaks
79 max_requests = 1000
79 max_requests = 1000
80 max_requests_jitter = 30
80 max_requests_jitter = 30
81 ## amount of time a worker can spend with handling a request before it
81 ## amount of time a worker can spend with handling a request before it
82 ## gets killed and restarted. Set to 6hrs
82 ## gets killed and restarted. Set to 6hrs
83 timeout = 21600
83 timeout = 21600
84
84
85 6. Save your changes.
85 6. Save your changes.
86 7. Restart your |RCE| instances, using the following command:
86 7. Restart your |RCE| instances, using the following command:
87
87
88 .. code-block:: bash
88 .. code-block:: bash
89
89
90 $ rccontrol restart '*'
90 $ rccontrol restart '*'
91
91
92
92
93 Gunicorn Gevent Backend
93 Gunicorn Gevent Backend
94 -----------------------
94 -----------------------
95
95
96 Gevent is an asynchronous worker type for Gunicorn. It allows accepting multiple
96 Gevent is an asynchronous worker type for Gunicorn. It allows accepting multiple
97 connections on a single `Gunicorn`_ worker. This means you can handle 100s
97 connections on a single `Gunicorn`_ worker. This means you can handle 100s
98 of concurrent clones, or API calls using just few workers. A setting called
98 of concurrent clones, or API calls using just few workers. A setting called
99 `worker_connections` defines on how many connections each worker can
99 `worker_connections` defines on how many connections each worker can
100 handle using `Gevent`.
100 handle using `Gevent`.
101
101
102
102
103 To enable `Gevent` on |RCE| do the following:
103 To enable `Gevent` on |RCE| do the following:
104
104
105
105
106 1. Open the :file:`home/{user}/.rccontrol/{instance-id}/rhodecode.ini` file.
106 1. Open the :file:`home/{user}/.rccontrol/{instance-id}/rhodecode.ini` file.
107 2. In the ``[server:main]`` section, change `worker_class` for Gunicorn.
107 2. In the ``[server:main]`` section, change `worker_class` for Gunicorn.
108
108
109
109
110 .. code-block:: ini
110 .. code-block:: ini
111
111
112 ## type of worker class, one of sync, gevent
112 ## type of worker class, one of sync, gevent
113 ## recommended for bigger setup is using of of other than sync one
113 ## recommended for bigger setup is using of of other than sync one
114 worker_class = gevent
114 worker_class = gevent
115 ## The maximum number of simultaneous clients. Valid only for Gevent
115 ## The maximum number of simultaneous clients. Valid only for Gevent
116 worker_connections = 30
116 worker_connections = 30
117
117
118
118
119 .. note::
119 .. note::
120
120
121 `Gevent` is currently only supported for Enterprise/Community instances.
121 `Gevent` is currently only supported for Enterprise/Community instances.
122 VCSServer doesn't yet support gevent.
122 VCSServer doesn't yet support gevent.
123
123
124
124
125
125
126 .. _Gunicorn: http://gunicorn.org/
126 .. _Gunicorn: http://gunicorn.org/
1 NO CONTENT: file renamed from docs/admin/tuning-hg-auth-loop.rst to docs/admin/system_admin/tuning/tuning-hg-auth-loop.rst
NO CONTENT: file renamed from docs/admin/tuning-hg-auth-loop.rst to docs/admin/system_admin/tuning/tuning-hg-auth-loop.rst
1 NO CONTENT: file renamed from docs/admin/tuning-increase-db-performance.rst to docs/admin/system_admin/tuning/tuning-increase-db-performance.rst
NO CONTENT: file renamed from docs/admin/tuning-increase-db-performance.rst to docs/admin/system_admin/tuning/tuning-increase-db-performance.rst
1 NO CONTENT: file renamed from docs/admin/tuning-mount-cache-memory.rst to docs/admin/system_admin/tuning/tuning-mount-cache-memory.rst
NO CONTENT: file renamed from docs/admin/tuning-mount-cache-memory.rst to docs/admin/system_admin/tuning/tuning-mount-cache-memory.rst
1 NO CONTENT: file renamed from docs/admin/tuning-scale-horizontally-cluster.rst to docs/admin/system_admin/tuning/tuning-scale-horizontally-cluster.rst
NO CONTENT: file renamed from docs/admin/tuning-scale-horizontally-cluster.rst to docs/admin/system_admin/tuning/tuning-scale-horizontally-cluster.rst
1 NO CONTENT: file renamed from docs/admin/tuning-user-sessions-performance.rst to docs/admin/system_admin/tuning/tuning-user-sessions-performance.rst
NO CONTENT: file renamed from docs/admin/tuning-user-sessions-performance.rst to docs/admin/system_admin/tuning/tuning-user-sessions-performance.rst
1 NO CONTENT: file renamed from docs/admin/tuning-vcs-memory-cache.rst to docs/admin/system_admin/tuning/tuning-vcs-memory-cache.rst
NO CONTENT: file renamed from docs/admin/tuning-vcs-memory-cache.rst to docs/admin/system_admin/tuning/tuning-vcs-memory-cache.rst
1 NO CONTENT: file renamed from docs/admin/vcs-server.rst to docs/admin/system_admin/vcs-server.rst
NO CONTENT: file renamed from docs/admin/vcs-server.rst to docs/admin/system_admin/vcs-server.rst
@@ -1,209 +1,210 b''
1 .. _api:
1 .. _api:
2
2
3 API Documentation
3 API Documentation
4 =================
4 =================
5
5
6 The |RCE| API uses a single scheme for calling all API methods. The API is
6 The |RCE| API uses a single scheme for calling all API methods. The API is
7 implemented with JSON protocol in both directions. To send API requests to
7 implemented with JSON protocol in both directions. To send API requests to
8 your instance of |RCE|, use the following URL format
8 your instance of |RCE|, use the following URL format
9 ``<your_server>/_admin``
9 ``<your_server>/_admin``
10
10
11 .. note::
11 .. note::
12
12
13 To use the API, you should configure the :file:`~/.rhoderc` file with
13 To use the API, you should configure the :file:`~/.rhoderc` file with
14 access details per instance. For more information, see
14 access details per instance. For more information, see
15 :ref:`config-rhoderc`.
15 :ref:`config-rhoderc`.
16
16
17
17
18 API ACCESS FOR WEB VIEWS
18 API ACCESS FOR WEB VIEWS
19 ------------------------
19 ------------------------
20
20
21 API access can also be turned on for each web view in |RCE| that is
21 API access can also be turned on for each web view in |RCE| that is
22 decorated with a `@LoginRequired` decorator. To enable API access, change
22 decorated with a `@LoginRequired` decorator. To enable API access, change
23 the standard login decorator to `@LoginRequired(api_access=True)`.
23 the standard login decorator to `@LoginRequired(api_access=True)`.
24
24
25 From |RCE| version 1.7.0 you can configure a white list
25 From |RCE| version 1.7.0 you can configure a white list
26 of views that have API access enabled by default. To enable these,
26 of views that have API access enabled by default. To enable these,
27 edit the |RCE| configuration ``.ini`` file. The default location is:
27 edit the |RCE| configuration ``.ini`` file. The default location is:
28
28
29 * |RCE| Pre-2.2.7 :file:`root/rhodecode/data/production.ini`
29 * |RCE| Pre-2.2.7 :file:`root/rhodecode/data/production.ini`
30 * |RCE| 3.0 :file:`/home/{user}/.rccontrol/{instance-id}/rhodecode.ini`
30 * |RCE| 3.0 :file:`/home/{user}/.rccontrol/{instance-id}/rhodecode.ini`
31
31
32 To configure the white list, edit this section of the file. In this
32 To configure the white list, edit this section of the file. In this
33 configuration example, API access is granted to the patch/diff raw file and
33 configuration example, API access is granted to the patch/diff raw file and
34 archive.
34 archive.
35
35
36 .. code-block:: ini
36 .. code-block:: ini
37
37
38 ## List of controllers (using glob syntax) that AUTH TOKENS could be used for access.
38 ## List of controllers (using glob syntax) that AUTH TOKENS could be used for access.
39 ## Adding ?auth_token = <token> to the url authenticates this request as if it
39 ## Adding ?auth_token = <token> to the url authenticates this request as if it
40 ## came from the the logged in user who own this authentication token.
40 ## came from the the logged in user who own this authentication token.
41 ##
41 ##
42 ## Syntax is <ControllerClass>:<function_pattern>.
42 ## Syntax is <ControllerClass>:<function_pattern>.
43 ## The list should be "," separated and on a single line.
43 ## The list should be "," separated and on a single line.
44 ##
44 ##
45 api_access_controllers_whitelist = RepoCommitsView:repo_commit_raw,RepoCommitsView:repo_commit_patch,RepoCommitsView:repo_commit_download
45 api_access_controllers_whitelist = RepoCommitsView:repo_commit_raw,RepoCommitsView:repo_commit_patch,RepoCommitsView:repo_commit_download
46
46
47 After this change, a |RCE| view can be accessed without login by adding a
47 After this change, a |RCE| view can be accessed without login by adding a
48 GET parameter ``?auth_token=<auth_token>`` to a url. For example to
48 GET parameter ``?auth_token=<auth_token>`` to a url. For example to
49 access the raw diff.
49 access the raw diff.
50
50
51 .. code-block:: html
51 .. code-block:: html
52
52
53 http://<server>/<repo>/changeset-diff/<sha>?auth_token=<auth_token>
53 http://<server>/<repo>/changeset-diff/<sha>?auth_token=<auth_token>
54
54
55 By default this is only enabled on RSS/ATOM feed views. Exposing raw diffs is a
55 By default this is only enabled on RSS/ATOM feed views. Exposing raw diffs is a
56 good way to integrate with 3rd party services like code review, or build farms
56 good way to integrate with 3rd party services like code review, or build farms
57 that could download archives.
57 that could download archives.
58
58
59 API ACCESS
59 API ACCESS
60 ----------
60 ----------
61
61
62 All clients are required to send JSON-RPC spec JSON data.
62 All clients are required to send JSON-RPC spec JSON data.
63
63
64 .. code-block:: bash
64 .. code-block:: bash
65
65
66 {
66 {
67 "id:"<id>",
67 "id:"<id>",
68 "auth_token":"<auth_token>",
68 "auth_token":"<auth_token>",
69 "method":"<method_name>",
69 "method":"<method_name>",
70 "args":{"<arg_key>":"<arg_val>"}
70 "args":{"<arg_key>":"<arg_val>"}
71 }
71 }
72
72
73 Example call for auto pulling from remote repositories using curl:
73 Example call for auto pulling from remote repositories using curl:
74
74
75 .. code-block:: bash
75 .. code-block:: bash
76
76
77 curl https://server.com/_admin/api -X POST -H 'content-type:text/plain' --data-binary '{"id":1,
77 curl https://server.com/_admin/api -X POST -H 'content-type:text/plain' --data-binary '{"id":1,
78 "auth_token":"xe7cdb2v278e4evbdf5vs04v832v0efvcbcve4a3","method":"pull", "args":{"repoid":"CPython"}}'
78 "auth_token":"xe7cdb2v278e4evbdf5vs04v832v0efvcbcve4a3","method":"pull", "args":{"repoid":"CPython"}}'
79
79
80 Provide those parameters:
80 Provide those parameters:
81 - **id** A value of any type, which is used to match the response with the
81 - **id** A value of any type, which is used to match the response with the
82 request that it is replying to.
82 request that it is replying to.
83 - **auth_token** for access and permission validation.
83 - **auth_token** for access and permission validation.
84 - **method** is name of method to call
84 - **method** is name of method to call
85 - **args** is an ``key:value`` list of arguments to pass to method
85 - **args** is an ``key:value`` list of arguments to pass to method
86
86
87 .. note::
87 .. note::
88
88
89 To get your |authtoken|, from the |RCE| interface,
89 To get your |authtoken|, from the |RCE| interface,
90 go to:
90 go to:
91 :menuselection:`username --> My account --> Auth tokens`
91 :menuselection:`username --> My account --> Auth tokens`
92
92
93 For security reasons you should always create a dedicated |authtoken| for
93 For security reasons you should always create a dedicated |authtoken| for
94 API use only.
94 API use only.
95
95
96
96
97 The |RCE| API will always return a JSON-RPC response:
97 The |RCE| API will always return a JSON-RPC response:
98
98
99 .. code-block:: bash
99 .. code-block:: bash
100
100
101 {
101 {
102 "id": <id>, # matching id sent by request
102 "id": <id>, # matching id sent by request
103 "result": "<result>"|null, # JSON formatted result, null if any errors
103 "result": "<result>"|null, # JSON formatted result, null if any errors
104 "error": "null"|<error_message> # JSON formatted error (if any)
104 "error": "null"|<error_message> # JSON formatted error (if any)
105 }
105 }
106
106
107 All responses from API will be with `HTTP/1.0 200 OK` status code.
107 All responses from API will be with `HTTP/1.0 200 OK` status code.
108 If there is an error when calling the API, the *error* key will contain a
108 If there is an error when calling the API, the *error* key will contain a
109 failure description and the *result* will be `null`.
109 failure description and the *result* will be `null`.
110
110
111 API CLIENT
111 API CLIENT
112 ----------
112 ----------
113
113
114 To install the |RCE| API, see :ref:`install-tools`. To configure the API per
114 To install the |RCE| API, see :ref:`install-tools`. To configure the API per
115 instance, see the :ref:`rc-tools` section as you need to configure a
115 instance, see the :ref:`rc-tools` section as you need to configure a
116 :file:`~/.rhoderc` file with your |authtokens|.
116 :file:`~/.rhoderc` file with your |authtokens|.
117
117
118 Once you have set up your instance API access, use the following examples to
118 Once you have set up your instance API access, use the following examples to
119 get started.
119 get started.
120
120
121 .. code-block:: bash
121 .. code-block:: bash
122
122
123 # Getting the 'rhodecode' repository
123 # Getting the 'rhodecode' repository
124 # from a RhodeCode Enterprise instance
124 # from a RhodeCode Enterprise instance
125 rhodecode-api --instance-name=enterprise-1 get_repo repoid:rhodecode
125 rhodecode-api --instance-name=enterprise-1 get_repo repoid:rhodecode
126
126
127 Calling method get_repo => http://127.0.0.1:5000
127 Calling method get_repo => http://127.0.0.1:5000
128 Server response
128 Server response
129 {
129 {
130 <json data>
130 <json data>
131 }
131 }
132
132
133 # Creating a new mercurial repository called 'brand-new'
133 # Creating a new mercurial repository called 'brand-new'
134 # with a description 'Repo-description'
134 # with a description 'Repo-description'
135 rhodecode-api --instance-name=enterprise-1 create_repo repo_name:brand-new repo_type:hg description:Repo-description
135 rhodecode-api --instance-name=enterprise-1 create_repo repo_name:brand-new repo_type:hg description:Repo-description
136 {
136 {
137 "error": null,
137 "error": null,
138 "id": 1110,
138 "id": 1110,
139 "result": {
139 "result": {
140 "msg": "Created new repository `brand-new`",
140 "msg": "Created new repository `brand-new`",
141 "success": true,
141 "success": true,
142 "task": null
142 "task": null
143 }
143 }
144 }
144 }
145
145
146 A broken example, what not to do.
146 A broken example, what not to do.
147
147
148 .. code-block:: bash
148 .. code-block:: bash
149
149
150 # A call missing the required arguments
150 # A call missing the required arguments
151 # and not specifying the instance
151 # and not specifying the instance
152 rhodecode-api get_repo
152 rhodecode-api get_repo
153
153
154 Calling method get_repo => http://127.0.0.1:5000
154 Calling method get_repo => http://127.0.0.1:5000
155 Server response
155 Server response
156 "Missing non optional `repoid` arg in JSON DATA"
156 "Missing non optional `repoid` arg in JSON DATA"
157
157
158 You can specify pure JSON using the ``--format`` parameter.
158 You can specify pure JSON using the ``--format`` parameter.
159
159
160 .. code-block:: bash
160 .. code-block:: bash
161
161
162 rhodecode-api --format=json get_repo repoid:rhodecode
162 rhodecode-api --format=json get_repo repoid:rhodecode
163
163
164 In such case only output that this function shows is pure JSON, we can use that
164 In such case only output that this function shows is pure JSON, we can use that
165 and pipe output to some json formatter.
165 and pipe output to some json formatter.
166
166
167 If output is in pure JSON format, you can pipe output to a JSON formatter.
167 If output is in pure JSON format, you can pipe output to a JSON formatter.
168
168
169 .. code-block:: bash
169 .. code-block:: bash
170
170
171 rhodecode-api --instance-name=enterprise-1 --format=json get_repo repoid:rhodecode | python -m json.tool
171 rhodecode-api --instance-name=enterprise-1 --format=json get_repo repoid:rhodecode | python -m json.tool
172
172
173 API METHODS
173 API METHODS
174 -----------
174 -----------
175
175
176 Each method by default required following arguments.
176 Each method by default required following arguments.
177
177
178 .. code-block:: bash
178 .. code-block:: bash
179
179
180 id : "<id_for_response>"
180 id : "<id_for_response>"
181 auth_token : "<auth_token>"
181 auth_token : "<auth_token>"
182 method : "<method name>"
182 method : "<method name>"
183 args : {}
183 args : {}
184
184
185 Use each **param** from docs and put it in args, Optional parameters
185 Use each **param** from docs and put it in args, Optional parameters
186 are not required in args.
186 are not required in args.
187
187
188 .. code-block:: bash
188 .. code-block:: bash
189
189
190 args: {"repoid": "rhodecode"}
190 args: {"repoid": "rhodecode"}
191
191
192 .. Note: From this point on things are generated by the script in
192 .. Note: From this point on things are generated by the script in
193 `scripts/fabfile.py`. To change things below, update the docstrings in the
193 `scripts/fabfile.py`. To change things below, update the docstrings in the
194 ApiController.
194 ApiController.
195
195
196 .. --- API DEFS MARKER ---
196 .. --- API DEFS MARKER ---
197 .. toctree::
197 .. toctree::
198
198
199 methods/repo-methods
199 methods/repo-methods
200 methods/store-methods
200 methods/store-methods
201 methods/license-methods
201 methods/license-methods
202 methods/deprecated-methods
202 methods/deprecated-methods
203 methods/gist-methods
203 methods/gist-methods
204 methods/pull-request-methods
204 methods/pull-request-methods
205 methods/repo-methods
205 methods/repo-methods
206 methods/repo-group-methods
206 methods/repo-group-methods
207 methods/search-methods
207 methods/server-methods
208 methods/server-methods
208 methods/user-methods
209 methods/user-methods
209 methods/user-group-methods
210 methods/user-group-methods
@@ -1,1134 +1,1133 b''
1 .. _repo-methods-ref:
1 .. _repo-methods-ref:
2
2
3 repo methods
3 repo methods
4 ============
4 ============
5
5
6 add_field_to_repo
6 add_field_to_repo
7 -----------------
7 -----------------
8
8
9 .. py:function:: add_field_to_repo(apiuser, repoid, key, label=<Optional:''>, description=<Optional:''>)
9 .. py:function:: add_field_to_repo(apiuser, repoid, key, label=<Optional:''>, description=<Optional:''>)
10
10
11 Adds an extra field to a repository.
11 Adds an extra field to a repository.
12
12
13 This command can only be run using an |authtoken| with at least
13 This command can only be run using an |authtoken| with at least
14 write permissions to the |repo|.
14 write permissions to the |repo|.
15
15
16 :param apiuser: This is filled automatically from the |authtoken|.
16 :param apiuser: This is filled automatically from the |authtoken|.
17 :type apiuser: AuthUser
17 :type apiuser: AuthUser
18 :param repoid: Set the repository name or repository id.
18 :param repoid: Set the repository name or repository id.
19 :type repoid: str or int
19 :type repoid: str or int
20 :param key: Create a unique field key for this repository.
20 :param key: Create a unique field key for this repository.
21 :type key: str
21 :type key: str
22 :param label:
22 :param label:
23 :type label: Optional(str)
23 :type label: Optional(str)
24 :param description:
24 :param description:
25 :type description: Optional(str)
25 :type description: Optional(str)
26
26
27
27
28 comment_commit
28 comment_commit
29 --------------
29 --------------
30
30
31 .. py:function:: comment_commit(apiuser, repoid, commit_id, message, status=<Optional:None>, comment_type=<Optional:u'note'>, resolves_comment_id=<Optional:None>, userid=<Optional:<OptionalAttr:apiuser>>)
31 .. py:function:: comment_commit(apiuser, repoid, commit_id, message, status=<Optional:None>, comment_type=<Optional:u'note'>, resolves_comment_id=<Optional:None>, userid=<Optional:<OptionalAttr:apiuser>>)
32
32
33 Set a commit comment, and optionally change the status of the commit.
33 Set a commit comment, and optionally change the status of the commit.
34
34
35 :param apiuser: This is filled automatically from the |authtoken|.
35 :param apiuser: This is filled automatically from the |authtoken|.
36 :type apiuser: AuthUser
36 :type apiuser: AuthUser
37 :param repoid: Set the repository name or repository ID.
37 :param repoid: Set the repository name or repository ID.
38 :type repoid: str or int
38 :type repoid: str or int
39 :param commit_id: Specify the commit_id for which to set a comment.
39 :param commit_id: Specify the commit_id for which to set a comment.
40 :type commit_id: str
40 :type commit_id: str
41 :param message: The comment text.
41 :param message: The comment text.
42 :type message: str
42 :type message: str
43 :param status: (**Optional**) status of commit, one of: 'not_reviewed',
43 :param status: (**Optional**) status of commit, one of: 'not_reviewed',
44 'approved', 'rejected', 'under_review'
44 'approved', 'rejected', 'under_review'
45 :type status: str
45 :type status: str
46 :param comment_type: Comment type, one of: 'note', 'todo'
46 :param comment_type: Comment type, one of: 'note', 'todo'
47 :type comment_type: Optional(str), default: 'note'
47 :type comment_type: Optional(str), default: 'note'
48 :param userid: Set the user name of the comment creator.
48 :param userid: Set the user name of the comment creator.
49 :type userid: Optional(str or int)
49 :type userid: Optional(str or int)
50
50
51 Example error output:
51 Example error output:
52
52
53 .. code-block:: bash
53 .. code-block:: bash
54
54
55 {
55 {
56 "id" : <id_given_in_input>,
56 "id" : <id_given_in_input>,
57 "result" : {
57 "result" : {
58 "msg": "Commented on commit `<commit_id>` for repository `<repoid>`",
58 "msg": "Commented on commit `<commit_id>` for repository `<repoid>`",
59 "status_change": null or <status>,
59 "status_change": null or <status>,
60 "success": true
60 "success": true
61 },
61 },
62 "error" : null
62 "error" : null
63 }
63 }
64
64
65
65
66 create_repo
66 create_repo
67 -----------
67 -----------
68
68
69 .. py:function:: create_repo(apiuser, repo_name, repo_type, owner=<Optional:<OptionalAttr:apiuser>>, description=<Optional:''>, private=<Optional:False>, clone_uri=<Optional:None>, push_uri=<Optional:None>, landing_rev=<Optional:'rev:tip'>, enable_statistics=<Optional:False>, enable_locking=<Optional:False>, enable_downloads=<Optional:False>, copy_permissions=<Optional:False>)
69 .. py:function:: create_repo(apiuser, repo_name, repo_type, owner=<Optional:<OptionalAttr:apiuser>>, description=<Optional:''>, private=<Optional:False>, clone_uri=<Optional:None>, push_uri=<Optional:None>, landing_rev=<Optional:'rev:tip'>, enable_statistics=<Optional:False>, enable_locking=<Optional:False>, enable_downloads=<Optional:False>, copy_permissions=<Optional:False>)
70
70
71 Creates a repository.
71 Creates a repository.
72
72
73 * If the repository name contains "/", repository will be created inside
73 * If the repository name contains "/", repository will be created inside
74 a repository group or nested repository groups
74 a repository group or nested repository groups
75
75
76 For example "foo/bar/repo1" will create |repo| called "repo1" inside
76 For example "foo/bar/repo1" will create |repo| called "repo1" inside
77 group "foo/bar". You have to have permissions to access and write to
77 group "foo/bar". You have to have permissions to access and write to
78 the last repository group ("bar" in this example)
78 the last repository group ("bar" in this example)
79
79
80 This command can only be run using an |authtoken| with at least
80 This command can only be run using an |authtoken| with at least
81 permissions to create repositories, or write permissions to
81 permissions to create repositories, or write permissions to
82 parent repository groups.
82 parent repository groups.
83
83
84 :param apiuser: This is filled automatically from the |authtoken|.
84 :param apiuser: This is filled automatically from the |authtoken|.
85 :type apiuser: AuthUser
85 :type apiuser: AuthUser
86 :param repo_name: Set the repository name.
86 :param repo_name: Set the repository name.
87 :type repo_name: str
87 :type repo_name: str
88 :param repo_type: Set the repository type; 'hg','git', or 'svn'.
88 :param repo_type: Set the repository type; 'hg','git', or 'svn'.
89 :type repo_type: str
89 :type repo_type: str
90 :param owner: user_id or username
90 :param owner: user_id or username
91 :type owner: Optional(str)
91 :type owner: Optional(str)
92 :param description: Set the repository description.
92 :param description: Set the repository description.
93 :type description: Optional(str)
93 :type description: Optional(str)
94 :param private: set repository as private
94 :param private: set repository as private
95 :type private: bool
95 :type private: bool
96 :param clone_uri: set clone_uri
96 :param clone_uri: set clone_uri
97 :type clone_uri: str
97 :type clone_uri: str
98 :param push_uri: set push_uri
98 :param push_uri: set push_uri
99 :type push_uri: str
99 :type push_uri: str
100 :param landing_rev: <rev_type>:<rev>
100 :param landing_rev: <rev_type>:<rev>
101 :type landing_rev: str
101 :type landing_rev: str
102 :param enable_locking:
102 :param enable_locking:
103 :type enable_locking: bool
103 :type enable_locking: bool
104 :param enable_downloads:
104 :param enable_downloads:
105 :type enable_downloads: bool
105 :type enable_downloads: bool
106 :param enable_statistics:
106 :param enable_statistics:
107 :type enable_statistics: bool
107 :type enable_statistics: bool
108 :param copy_permissions: Copy permission from group in which the
108 :param copy_permissions: Copy permission from group in which the
109 repository is being created.
109 repository is being created.
110 :type copy_permissions: bool
110 :type copy_permissions: bool
111
111
112
112
113 Example output:
113 Example output:
114
114
115 .. code-block:: bash
115 .. code-block:: bash
116
116
117 id : <id_given_in_input>
117 id : <id_given_in_input>
118 result: {
118 result: {
119 "msg": "Created new repository `<reponame>`",
119 "msg": "Created new repository `<reponame>`",
120 "success": true,
120 "success": true,
121 "task": "<celery task id or None if done sync>"
121 "task": "<celery task id or None if done sync>"
122 }
122 }
123 error: null
123 error: null
124
124
125
125
126 Example error output:
126 Example error output:
127
127
128 .. code-block:: bash
128 .. code-block:: bash
129
129
130 id : <id_given_in_input>
130 id : <id_given_in_input>
131 result : null
131 result : null
132 error : {
132 error : {
133 'failed to create repository `<repo_name>`'
133 'failed to create repository `<repo_name>`'
134 }
134 }
135
135
136
136
137 delete_repo
137 delete_repo
138 -----------
138 -----------
139
139
140 .. py:function:: delete_repo(apiuser, repoid, forks=<Optional:''>)
140 .. py:function:: delete_repo(apiuser, repoid, forks=<Optional:''>)
141
141
142 Deletes a repository.
142 Deletes a repository.
143
143
144 * When the `forks` parameter is set it's possible to detach or delete
144 * When the `forks` parameter is set it's possible to detach or delete
145 forks of deleted repository.
145 forks of deleted repository.
146
146
147 This command can only be run using an |authtoken| with admin
147 This command can only be run using an |authtoken| with admin
148 permissions on the |repo|.
148 permissions on the |repo|.
149
149
150 :param apiuser: This is filled automatically from the |authtoken|.
150 :param apiuser: This is filled automatically from the |authtoken|.
151 :type apiuser: AuthUser
151 :type apiuser: AuthUser
152 :param repoid: Set the repository name or repository ID.
152 :param repoid: Set the repository name or repository ID.
153 :type repoid: str or int
153 :type repoid: str or int
154 :param forks: Set to `detach` or `delete` forks from the |repo|.
154 :param forks: Set to `detach` or `delete` forks from the |repo|.
155 :type forks: Optional(str)
155 :type forks: Optional(str)
156
156
157 Example error output:
157 Example error output:
158
158
159 .. code-block:: bash
159 .. code-block:: bash
160
160
161 id : <id_given_in_input>
161 id : <id_given_in_input>
162 result: {
162 result: {
163 "msg": "Deleted repository `<reponame>`",
163 "msg": "Deleted repository `<reponame>`",
164 "success": true
164 "success": true
165 }
165 }
166 error: null
166 error: null
167
167
168
168
169 fork_repo
169 fork_repo
170 ---------
170 ---------
171
171
172 .. py:function:: fork_repo(apiuser, repoid, fork_name, owner=<Optional:<OptionalAttr:apiuser>>, description=<Optional:''>, private=<Optional:False>, clone_uri=<Optional:None>, landing_rev=<Optional:'rev:tip'>, copy_permissions=<Optional:False>)
172 .. py:function:: fork_repo(apiuser, repoid, fork_name, owner=<Optional:<OptionalAttr:apiuser>>, description=<Optional:''>, private=<Optional:False>, clone_uri=<Optional:None>, landing_rev=<Optional:'rev:tip'>, copy_permissions=<Optional:False>)
173
173
174 Creates a fork of the specified |repo|.
174 Creates a fork of the specified |repo|.
175
175
176 * If the fork_name contains "/", fork will be created inside
176 * If the fork_name contains "/", fork will be created inside
177 a repository group or nested repository groups
177 a repository group or nested repository groups
178
178
179 For example "foo/bar/fork-repo" will create fork called "fork-repo"
179 For example "foo/bar/fork-repo" will create fork called "fork-repo"
180 inside group "foo/bar". You have to have permissions to access and
180 inside group "foo/bar". You have to have permissions to access and
181 write to the last repository group ("bar" in this example)
181 write to the last repository group ("bar" in this example)
182
182
183 This command can only be run using an |authtoken| with minimum
183 This command can only be run using an |authtoken| with minimum
184 read permissions of the forked repo, create fork permissions for an user.
184 read permissions of the forked repo, create fork permissions for an user.
185
185
186 :param apiuser: This is filled automatically from the |authtoken|.
186 :param apiuser: This is filled automatically from the |authtoken|.
187 :type apiuser: AuthUser
187 :type apiuser: AuthUser
188 :param repoid: Set repository name or repository ID.
188 :param repoid: Set repository name or repository ID.
189 :type repoid: str or int
189 :type repoid: str or int
190 :param fork_name: Set the fork name, including it's repository group membership.
190 :param fork_name: Set the fork name, including it's repository group membership.
191 :type fork_name: str
191 :type fork_name: str
192 :param owner: Set the fork owner.
192 :param owner: Set the fork owner.
193 :type owner: str
193 :type owner: str
194 :param description: Set the fork description.
194 :param description: Set the fork description.
195 :type description: str
195 :type description: str
196 :param copy_permissions: Copy permissions from parent |repo|. The
196 :param copy_permissions: Copy permissions from parent |repo|. The
197 default is False.
197 default is False.
198 :type copy_permissions: bool
198 :type copy_permissions: bool
199 :param private: Make the fork private. The default is False.
199 :param private: Make the fork private. The default is False.
200 :type private: bool
200 :type private: bool
201 :param landing_rev: Set the landing revision. The default is tip.
201 :param landing_rev: Set the landing revision. The default is tip.
202
202
203 Example output:
203 Example output:
204
204
205 .. code-block:: bash
205 .. code-block:: bash
206
206
207 id : <id_for_response>
207 id : <id_for_response>
208 api_key : "<api_key>"
208 api_key : "<api_key>"
209 args: {
209 args: {
210 "repoid" : "<reponame or repo_id>",
210 "repoid" : "<reponame or repo_id>",
211 "fork_name": "<forkname>",
211 "fork_name": "<forkname>",
212 "owner": "<username or user_id = Optional(=apiuser)>",
212 "owner": "<username or user_id = Optional(=apiuser)>",
213 "description": "<description>",
213 "description": "<description>",
214 "copy_permissions": "<bool>",
214 "copy_permissions": "<bool>",
215 "private": "<bool>",
215 "private": "<bool>",
216 "landing_rev": "<landing_rev>"
216 "landing_rev": "<landing_rev>"
217 }
217 }
218
218
219 Example error output:
219 Example error output:
220
220
221 .. code-block:: bash
221 .. code-block:: bash
222
222
223 id : <id_given_in_input>
223 id : <id_given_in_input>
224 result: {
224 result: {
225 "msg": "Created fork of `<reponame>` as `<forkname>`",
225 "msg": "Created fork of `<reponame>` as `<forkname>`",
226 "success": true,
226 "success": true,
227 "task": "<celery task id or None if done sync>"
227 "task": "<celery task id or None if done sync>"
228 }
228 }
229 error: null
229 error: null
230
230
231
231
232 get_repo
232 get_repo
233 --------
233 --------
234
234
235 .. py:function:: get_repo(apiuser, repoid, cache=<Optional:True>)
235 .. py:function:: get_repo(apiuser, repoid, cache=<Optional:True>)
236
236
237 Gets an existing repository by its name or repository_id.
237 Gets an existing repository by its name or repository_id.
238
238
239 The members section so the output returns users groups or users
239 The members section so the output returns users groups or users
240 associated with that repository.
240 associated with that repository.
241
241
242 This command can only be run using an |authtoken| with admin rights,
242 This command can only be run using an |authtoken| with admin rights,
243 or users with at least read rights to the |repo|.
243 or users with at least read rights to the |repo|.
244
244
245 :param apiuser: This is filled automatically from the |authtoken|.
245 :param apiuser: This is filled automatically from the |authtoken|.
246 :type apiuser: AuthUser
246 :type apiuser: AuthUser
247 :param repoid: The repository name or repository id.
247 :param repoid: The repository name or repository id.
248 :type repoid: str or int
248 :type repoid: str or int
249 :param cache: use the cached value for last changeset
249 :param cache: use the cached value for last changeset
250 :type: cache: Optional(bool)
250 :type: cache: Optional(bool)
251
251
252 Example output:
252 Example output:
253
253
254 .. code-block:: bash
254 .. code-block:: bash
255
255
256 {
256 {
257 "error": null,
257 "error": null,
258 "id": <repo_id>,
258 "id": <repo_id>,
259 "result": {
259 "result": {
260 "clone_uri": null,
260 "clone_uri": null,
261 "created_on": "timestamp",
261 "created_on": "timestamp",
262 "description": "repo description",
262 "description": "repo description",
263 "enable_downloads": false,
263 "enable_downloads": false,
264 "enable_locking": false,
264 "enable_locking": false,
265 "enable_statistics": false,
265 "enable_statistics": false,
266 "followers": [
266 "followers": [
267 {
267 {
268 "active": true,
268 "active": true,
269 "admin": false,
269 "admin": false,
270 "api_key": "****************************************",
270 "api_key": "****************************************",
271 "api_keys": [
271 "api_keys": [
272 "****************************************"
272 "****************************************"
273 ],
273 ],
274 "email": "user@example.com",
274 "email": "user@example.com",
275 "emails": [
275 "emails": [
276 "user@example.com"
276 "user@example.com"
277 ],
277 ],
278 "extern_name": "rhodecode",
278 "extern_name": "rhodecode",
279 "extern_type": "rhodecode",
279 "extern_type": "rhodecode",
280 "firstname": "username",
280 "firstname": "username",
281 "ip_addresses": [],
281 "ip_addresses": [],
282 "language": null,
282 "language": null,
283 "last_login": "2015-09-16T17:16:35.854",
283 "last_login": "2015-09-16T17:16:35.854",
284 "lastname": "surname",
284 "lastname": "surname",
285 "user_id": <user_id>,
285 "user_id": <user_id>,
286 "username": "name"
286 "username": "name"
287 }
287 }
288 ],
288 ],
289 "fork_of": "parent-repo",
289 "fork_of": "parent-repo",
290 "landing_rev": [
290 "landing_rev": [
291 "rev",
291 "rev",
292 "tip"
292 "tip"
293 ],
293 ],
294 "last_changeset": {
294 "last_changeset": {
295 "author": "User <user@example.com>",
295 "author": "User <user@example.com>",
296 "branch": "default",
296 "branch": "default",
297 "date": "timestamp",
297 "date": "timestamp",
298 "message": "last commit message",
298 "message": "last commit message",
299 "parents": [
299 "parents": [
300 {
300 {
301 "raw_id": "commit-id"
301 "raw_id": "commit-id"
302 }
302 }
303 ],
303 ],
304 "raw_id": "commit-id",
304 "raw_id": "commit-id",
305 "revision": <revision number>,
305 "revision": <revision number>,
306 "short_id": "short id"
306 "short_id": "short id"
307 },
307 },
308 "lock_reason": null,
308 "lock_reason": null,
309 "locked_by": null,
309 "locked_by": null,
310 "locked_date": null,
310 "locked_date": null,
311 "owner": "owner-name",
311 "owner": "owner-name",
312 "permissions": [
312 "permissions": [
313 {
313 {
314 "name": "super-admin-name",
314 "name": "super-admin-name",
315 "origin": "super-admin",
315 "origin": "super-admin",
316 "permission": "repository.admin",
316 "permission": "repository.admin",
317 "type": "user"
317 "type": "user"
318 },
318 },
319 {
319 {
320 "name": "owner-name",
320 "name": "owner-name",
321 "origin": "owner",
321 "origin": "owner",
322 "permission": "repository.admin",
322 "permission": "repository.admin",
323 "type": "user"
323 "type": "user"
324 },
324 },
325 {
325 {
326 "name": "user-group-name",
326 "name": "user-group-name",
327 "origin": "permission",
327 "origin": "permission",
328 "permission": "repository.write",
328 "permission": "repository.write",
329 "type": "user_group"
329 "type": "user_group"
330 }
330 }
331 ],
331 ],
332 "private": true,
332 "private": true,
333 "repo_id": 676,
333 "repo_id": 676,
334 "repo_name": "user-group/repo-name",
334 "repo_name": "user-group/repo-name",
335 "repo_type": "hg"
335 "repo_type": "hg"
336 }
336 }
337 }
337 }
338
338
339
339
340 get_repo_changeset
340 get_repo_changeset
341 ------------------
341 ------------------
342
342
343 .. py:function:: get_repo_changeset(apiuser, repoid, revision, details=<Optional:'basic'>)
343 .. py:function:: get_repo_changeset(apiuser, repoid, revision, details=<Optional:'basic'>)
344
344
345 Returns information about a changeset.
345 Returns information about a changeset.
346
346
347 Additionally parameters define the amount of details returned by
347 Additionally parameters define the amount of details returned by
348 this function.
348 this function.
349
349
350 This command can only be run using an |authtoken| with admin rights,
350 This command can only be run using an |authtoken| with admin rights,
351 or users with at least read rights to the |repo|.
351 or users with at least read rights to the |repo|.
352
352
353 :param apiuser: This is filled automatically from the |authtoken|.
353 :param apiuser: This is filled automatically from the |authtoken|.
354 :type apiuser: AuthUser
354 :type apiuser: AuthUser
355 :param repoid: The repository name or repository id
355 :param repoid: The repository name or repository id
356 :type repoid: str or int
356 :type repoid: str or int
357 :param revision: revision for which listing should be done
357 :param revision: revision for which listing should be done
358 :type revision: str
358 :type revision: str
359 :param details: details can be 'basic|extended|full' full gives diff
359 :param details: details can be 'basic|extended|full' full gives diff
360 info details like the diff itself, and number of changed files etc.
360 info details like the diff itself, and number of changed files etc.
361 :type details: Optional(str)
361 :type details: Optional(str)
362
362
363
363
364 get_repo_changesets
364 get_repo_changesets
365 -------------------
365 -------------------
366
366
367 .. py:function:: get_repo_changesets(apiuser, repoid, start_rev, limit, details=<Optional:'basic'>)
367 .. py:function:: get_repo_changesets(apiuser, repoid, start_rev, limit, details=<Optional:'basic'>)
368
368
369 Returns a set of commits limited by the number starting
369 Returns a set of commits limited by the number starting
370 from the `start_rev` option.
370 from the `start_rev` option.
371
371
372 Additional parameters define the amount of details returned by this
372 Additional parameters define the amount of details returned by this
373 function.
373 function.
374
374
375 This command can only be run using an |authtoken| with admin rights,
375 This command can only be run using an |authtoken| with admin rights,
376 or users with at least read rights to |repos|.
376 or users with at least read rights to |repos|.
377
377
378 :param apiuser: This is filled automatically from the |authtoken|.
378 :param apiuser: This is filled automatically from the |authtoken|.
379 :type apiuser: AuthUser
379 :type apiuser: AuthUser
380 :param repoid: The repository name or repository ID.
380 :param repoid: The repository name or repository ID.
381 :type repoid: str or int
381 :type repoid: str or int
382 :param start_rev: The starting revision from where to get changesets.
382 :param start_rev: The starting revision from where to get changesets.
383 :type start_rev: str
383 :type start_rev: str
384 :param limit: Limit the number of commits to this amount
384 :param limit: Limit the number of commits to this amount
385 :type limit: str or int
385 :type limit: str or int
386 :param details: Set the level of detail returned. Valid option are:
386 :param details: Set the level of detail returned. Valid option are:
387 ``basic``, ``extended`` and ``full``.
387 ``basic``, ``extended`` and ``full``.
388 :type details: Optional(str)
388 :type details: Optional(str)
389
389
390 .. note::
390 .. note::
391
391
392 Setting the parameter `details` to the value ``full`` is extensive
392 Setting the parameter `details` to the value ``full`` is extensive
393 and returns details like the diff itself, and the number
393 and returns details like the diff itself, and the number
394 of changed files.
394 of changed files.
395
395
396
396
397 get_repo_comments
397 get_repo_comments
398 -----------------
398 -----------------
399
399
400 .. py:function:: get_repo_comments(apiuser, repoid, commit_id=<Optional:None>, comment_type=<Optional:None>, userid=<Optional:None>)
400 .. py:function:: get_repo_comments(apiuser, repoid, commit_id=<Optional:None>, comment_type=<Optional:None>, userid=<Optional:None>)
401
401
402 Get all comments for a repository
402 Get all comments for a repository
403
403
404 :param apiuser: This is filled automatically from the |authtoken|.
404 :param apiuser: This is filled automatically from the |authtoken|.
405 :type apiuser: AuthUser
405 :type apiuser: AuthUser
406 :param repoid: Set the repository name or repository ID.
406 :param repoid: Set the repository name or repository ID.
407 :type repoid: str or int
407 :type repoid: str or int
408 :param commit_id: Optionally filter the comments by the commit_id
408 :param commit_id: Optionally filter the comments by the commit_id
409 :type commit_id: Optional(str), default: None
409 :type commit_id: Optional(str), default: None
410 :param comment_type: Optionally filter the comments by the comment_type
410 :param comment_type: Optionally filter the comments by the comment_type
411 one of: 'note', 'todo'
411 one of: 'note', 'todo'
412 :type comment_type: Optional(str), default: None
412 :type comment_type: Optional(str), default: None
413 :param userid: Optionally filter the comments by the author of comment
413 :param userid: Optionally filter the comments by the author of comment
414 :type userid: Optional(str or int), Default: None
414 :type userid: Optional(str or int), Default: None
415
415
416 Example error output:
416 Example error output:
417
417
418 .. code-block:: bash
418 .. code-block:: bash
419
419
420 {
420 {
421 "id" : <id_given_in_input>,
421 "id" : <id_given_in_input>,
422 "result" : [
422 "result" : [
423 {
423 {
424 "comment_author": <USER_DETAILS>,
424 "comment_author": <USER_DETAILS>,
425 "comment_created_on": "2017-02-01T14:38:16.309",
425 "comment_created_on": "2017-02-01T14:38:16.309",
426 "comment_f_path": "file.txt",
426 "comment_f_path": "file.txt",
427 "comment_id": 282,
427 "comment_id": 282,
428 "comment_lineno": "n1",
428 "comment_lineno": "n1",
429 "comment_resolved_by": null,
429 "comment_resolved_by": null,
430 "comment_status": [],
430 "comment_status": [],
431 "comment_text": "This file needs a header",
431 "comment_text": "This file needs a header",
432 "comment_type": "todo"
432 "comment_type": "todo"
433 }
433 }
434 ],
434 ],
435 "error" : null
435 "error" : null
436 }
436 }
437
437
438
438
439 get_repo_file
439 get_repo_file
440 -------------
440 -------------
441
441
442 .. py:function:: get_repo_file(apiuser, repoid, commit_id, file_path, max_file_bytes=<Optional:None>, details=<Optional:'basic'>, cache=<Optional:True>)
442 .. py:function:: get_repo_file(apiuser, repoid, commit_id, file_path, max_file_bytes=<Optional:None>, details=<Optional:'basic'>, cache=<Optional:True>)
443
443
444 Returns a single file from repository at given revision.
444 Returns a single file from repository at given revision.
445
445
446 This command can only be run using an |authtoken| with admin rights,
446 This command can only be run using an |authtoken| with admin rights,
447 or users with at least read rights to |repos|.
447 or users with at least read rights to |repos|.
448
448
449 :param apiuser: This is filled automatically from the |authtoken|.
449 :param apiuser: This is filled automatically from the |authtoken|.
450 :type apiuser: AuthUser
450 :type apiuser: AuthUser
451 :param repoid: The repository name or repository ID.
451 :param repoid: The repository name or repository ID.
452 :type repoid: str or int
452 :type repoid: str or int
453 :param commit_id: The revision for which listing should be done.
453 :param commit_id: The revision for which listing should be done.
454 :type commit_id: str
454 :type commit_id: str
455 :param file_path: The path from which to start displaying.
455 :param file_path: The path from which to start displaying.
456 :type file_path: str
456 :type file_path: str
457 :param details: Returns different set of information about nodes.
457 :param details: Returns different set of information about nodes.
458 The valid options are ``minimal`` ``basic`` and ``full``.
458 The valid options are ``minimal`` ``basic`` and ``full``.
459 :type details: Optional(str)
459 :type details: Optional(str)
460 :param max_file_bytes: Only return file content under this file size bytes
460 :param max_file_bytes: Only return file content under this file size bytes
461 :type max_file_bytes: Optional(int)
461 :type max_file_bytes: Optional(int)
462 :param cache: Use internal caches for fetching files. If disabled fetching
462 :param cache: Use internal caches for fetching files. If disabled fetching
463 files is slower but more memory efficient
463 files is slower but more memory efficient
464 :type cache: Optional(bool)
464 :type cache: Optional(bool)
465
465 Example output:
466 Example output:
466
467
467 .. code-block:: bash
468 .. code-block:: bash
468
469
469 id : <id_given_in_input>
470 id : <id_given_in_input>
470 result: {
471 result: {
471 "binary": false,
472 "binary": false,
472 "extension": "py",
473 "extension": "py",
473 "lines": 35,
474 "lines": 35,
474 "content": "....",
475 "content": "....",
475 "md5": "76318336366b0f17ee249e11b0c99c41",
476 "md5": "76318336366b0f17ee249e11b0c99c41",
476 "mimetype": "text/x-python",
477 "mimetype": "text/x-python",
477 "name": "python.py",
478 "name": "python.py",
478 "size": 817,
479 "size": 817,
479 "type": "file",
480 "type": "file",
480 }
481 }
481 error: null
482 error: null
482
483
483
484
484 get_repo_fts_tree
485 get_repo_fts_tree
485 -----------------
486 -----------------
486
487
487 .. py:function:: get_repo_fts_tree(apiuser, repoid, commit_id, root_path)
488 .. py:function:: get_repo_fts_tree(apiuser, repoid, commit_id, root_path)
488
489
489 Returns a list of tree nodes for path at given revision. This api is built
490 Returns a list of tree nodes for path at given revision. This api is built
490 strictly for usage in full text search building, and shouldn't be consumed
491 strictly for usage in full text search building, and shouldn't be consumed
491
492
492 This command can only be run using an |authtoken| with admin rights,
493 This command can only be run using an |authtoken| with admin rights,
493 or users with at least read rights to |repos|.
494 or users with at least read rights to |repos|.
494
495
495
496
496 get_repo_nodes
497 get_repo_nodes
497 --------------
498 --------------
498
499
499 .. py:function:: get_repo_nodes(apiuser, repoid, revision, root_path, ret_type=<Optional:'all'>, details=<Optional:'basic'>, max_file_bytes=<Optional:None>)
500 .. py:function:: get_repo_nodes(apiuser, repoid, revision, root_path, ret_type=<Optional:'all'>, details=<Optional:'basic'>, max_file_bytes=<Optional:None>)
500
501
501 Returns a list of nodes and children in a flat list for a given
502 Returns a list of nodes and children in a flat list for a given
502 path at given revision.
503 path at given revision.
503
504
504 It's possible to specify ret_type to show only `files` or `dirs`.
505 It's possible to specify ret_type to show only `files` or `dirs`.
505
506
506 This command can only be run using an |authtoken| with admin rights,
507 This command can only be run using an |authtoken| with admin rights,
507 or users with at least read rights to |repos|.
508 or users with at least read rights to |repos|.
508
509
509 :param apiuser: This is filled automatically from the |authtoken|.
510 :param apiuser: This is filled automatically from the |authtoken|.
510 :type apiuser: AuthUser
511 :type apiuser: AuthUser
511 :param repoid: The repository name or repository ID.
512 :param repoid: The repository name or repository ID.
512 :type repoid: str or int
513 :type repoid: str or int
513 :param revision: The revision for which listing should be done.
514 :param revision: The revision for which listing should be done.
514 :type revision: str
515 :type revision: str
515 :param root_path: The path from which to start displaying.
516 :param root_path: The path from which to start displaying.
516 :type root_path: str
517 :type root_path: str
517 :param ret_type: Set the return type. Valid options are
518 :param ret_type: Set the return type. Valid options are
518 ``all`` (default), ``files`` and ``dirs``.
519 ``all`` (default), ``files`` and ``dirs``.
519 :type ret_type: Optional(str)
520 :type ret_type: Optional(str)
520 :param details: Returns extended information about nodes, such as
521 :param details: Returns extended information about nodes, such as
521 md5, binary, and or content.
522 md5, binary, and or content.
522 The valid options are ``basic`` and ``full``.
523 The valid options are ``basic`` and ``full``.
523 :type details: Optional(str)
524 :type details: Optional(str)
524 :param max_file_bytes: Only return file content under this file size bytes
525 :param max_file_bytes: Only return file content under this file size bytes
525 :type details: Optional(int)
526 :type details: Optional(int)
526
527 Example output:
528
527
529 .. code-block:: bash
528 Example output:
529
530 .. code-block:: bash
530
531
531 id : <id_given_in_input>
532 id : <id_given_in_input>
532 result: [
533 result: [
533 {
534 {
534 "binary": false,
535 "binary": false,
535 "content": "File line
536 "content": "File line",
536 Line2
537 "extension": "md",
537 ",
538 "lines": 2,
538 "extension": "md",
539 "md5": "059fa5d29b19c0657e384749480f6422",
539 "lines": 2,
540 "mimetype": "text/x-minidsrc",
540 "md5": "059fa5d29b19c0657e384749480f6422",
541 "name": "file.md",
541 "mimetype": "text/x-minidsrc",
542 "size": 580,
542 "name": "file.md",
543 "type": "file"
543 "size": 580,
544 },
544 "type": "file"
545 ...
545 },
546 ]
546 ...
547 error: null
547 ]
548 error: null
549
548
550
549
551 get_repo_refs
550 get_repo_refs
552 -------------
551 -------------
553
552
554 .. py:function:: get_repo_refs(apiuser, repoid)
553 .. py:function:: get_repo_refs(apiuser, repoid)
555
554
556 Returns a dictionary of current references. It returns
555 Returns a dictionary of current references. It returns
557 bookmarks, branches, closed_branches, and tags for given repository
556 bookmarks, branches, closed_branches, and tags for given repository
558
557
559 It's possible to specify ret_type to show only `files` or `dirs`.
558 It's possible to specify ret_type to show only `files` or `dirs`.
560
559
561 This command can only be run using an |authtoken| with admin rights,
560 This command can only be run using an |authtoken| with admin rights,
562 or users with at least read rights to |repos|.
561 or users with at least read rights to |repos|.
563
562
564 :param apiuser: This is filled automatically from the |authtoken|.
563 :param apiuser: This is filled automatically from the |authtoken|.
565 :type apiuser: AuthUser
564 :type apiuser: AuthUser
566 :param repoid: The repository name or repository ID.
565 :param repoid: The repository name or repository ID.
567 :type repoid: str or int
566 :type repoid: str or int
568
567
569 Example output:
568 Example output:
570
569
571 .. code-block:: bash
570 .. code-block:: bash
572
571
573 id : <id_given_in_input>
572 id : <id_given_in_input>
574 "result": {
573 "result": {
575 "bookmarks": {
574 "bookmarks": {
576 "dev": "5611d30200f4040ba2ab4f3d64e5b06408a02188",
575 "dev": "5611d30200f4040ba2ab4f3d64e5b06408a02188",
577 "master": "367f590445081d8ec8c2ea0456e73ae1f1c3d6cf"
576 "master": "367f590445081d8ec8c2ea0456e73ae1f1c3d6cf"
578 },
577 },
579 "branches": {
578 "branches": {
580 "default": "5611d30200f4040ba2ab4f3d64e5b06408a02188",
579 "default": "5611d30200f4040ba2ab4f3d64e5b06408a02188",
581 "stable": "367f590445081d8ec8c2ea0456e73ae1f1c3d6cf"
580 "stable": "367f590445081d8ec8c2ea0456e73ae1f1c3d6cf"
582 },
581 },
583 "branches_closed": {},
582 "branches_closed": {},
584 "tags": {
583 "tags": {
585 "tip": "5611d30200f4040ba2ab4f3d64e5b06408a02188",
584 "tip": "5611d30200f4040ba2ab4f3d64e5b06408a02188",
586 "v4.4.0": "1232313f9e6adac5ce5399c2a891dc1e72b79022",
585 "v4.4.0": "1232313f9e6adac5ce5399c2a891dc1e72b79022",
587 "v4.4.1": "cbb9f1d329ae5768379cdec55a62ebdd546c4e27",
586 "v4.4.1": "cbb9f1d329ae5768379cdec55a62ebdd546c4e27",
588 "v4.4.2": "24ffe44a27fcd1c5b6936144e176b9f6dd2f3a17",
587 "v4.4.2": "24ffe44a27fcd1c5b6936144e176b9f6dd2f3a17",
589 }
588 }
590 }
589 }
591 error: null
590 error: null
592
591
593
592
594 get_repo_settings
593 get_repo_settings
595 -----------------
594 -----------------
596
595
597 .. py:function:: get_repo_settings(apiuser, repoid, key=<Optional:None>)
596 .. py:function:: get_repo_settings(apiuser, repoid, key=<Optional:None>)
598
597
599 Returns all settings for a repository. If key is given it only returns the
598 Returns all settings for a repository. If key is given it only returns the
600 setting identified by the key or null.
599 setting identified by the key or null.
601
600
602 :param apiuser: This is filled automatically from the |authtoken|.
601 :param apiuser: This is filled automatically from the |authtoken|.
603 :type apiuser: AuthUser
602 :type apiuser: AuthUser
604 :param repoid: The repository name or repository id.
603 :param repoid: The repository name or repository id.
605 :type repoid: str or int
604 :type repoid: str or int
606 :param key: Key of the setting to return.
605 :param key: Key of the setting to return.
607 :type: key: Optional(str)
606 :type: key: Optional(str)
608
607
609 Example output:
608 Example output:
610
609
611 .. code-block:: bash
610 .. code-block:: bash
612
611
613 {
612 {
614 "error": null,
613 "error": null,
615 "id": 237,
614 "id": 237,
616 "result": {
615 "result": {
617 "extensions_largefiles": true,
616 "extensions_largefiles": true,
618 "extensions_evolve": true,
617 "extensions_evolve": true,
619 "hooks_changegroup_push_logger": true,
618 "hooks_changegroup_push_logger": true,
620 "hooks_changegroup_repo_size": false,
619 "hooks_changegroup_repo_size": false,
621 "hooks_outgoing_pull_logger": true,
620 "hooks_outgoing_pull_logger": true,
622 "phases_publish": "True",
621 "phases_publish": "True",
623 "rhodecode_hg_use_rebase_for_merging": true,
622 "rhodecode_hg_use_rebase_for_merging": true,
624 "rhodecode_pr_merge_enabled": true,
623 "rhodecode_pr_merge_enabled": true,
625 "rhodecode_use_outdated_comments": true
624 "rhodecode_use_outdated_comments": true
626 }
625 }
627 }
626 }
628
627
629
628
630 get_repos
629 get_repos
631 ---------
630 ---------
632
631
633 .. py:function:: get_repos(apiuser, root=<Optional:None>, traverse=<Optional:True>)
632 .. py:function:: get_repos(apiuser, root=<Optional:None>, traverse=<Optional:True>)
634
633
635 Lists all existing repositories.
634 Lists all existing repositories.
636
635
637 This command can only be run using an |authtoken| with admin rights,
636 This command can only be run using an |authtoken| with admin rights,
638 or users with at least read rights to |repos|.
637 or users with at least read rights to |repos|.
639
638
640 :param apiuser: This is filled automatically from the |authtoken|.
639 :param apiuser: This is filled automatically from the |authtoken|.
641 :type apiuser: AuthUser
640 :type apiuser: AuthUser
642 :param root: specify root repository group to fetch repositories.
641 :param root: specify root repository group to fetch repositories.
643 filters the returned repositories to be members of given root group.
642 filters the returned repositories to be members of given root group.
644 :type root: Optional(None)
643 :type root: Optional(None)
645 :param traverse: traverse given root into subrepositories. With this flag
644 :param traverse: traverse given root into subrepositories. With this flag
646 set to False, it will only return top-level repositories from `root`.
645 set to False, it will only return top-level repositories from `root`.
647 if root is empty it will return just top-level repositories.
646 if root is empty it will return just top-level repositories.
648 :type traverse: Optional(True)
647 :type traverse: Optional(True)
649
648
650
649
651 Example output:
650 Example output:
652
651
653 .. code-block:: bash
652 .. code-block:: bash
654
653
655 id : <id_given_in_input>
654 id : <id_given_in_input>
656 result: [
655 result: [
657 {
656 {
658 "repo_id" : "<repo_id>",
657 "repo_id" : "<repo_id>",
659 "repo_name" : "<reponame>"
658 "repo_name" : "<reponame>"
660 "repo_type" : "<repo_type>",
659 "repo_type" : "<repo_type>",
661 "clone_uri" : "<clone_uri>",
660 "clone_uri" : "<clone_uri>",
662 "private": : "<bool>",
661 "private": : "<bool>",
663 "created_on" : "<datetimecreated>",
662 "created_on" : "<datetimecreated>",
664 "description" : "<description>",
663 "description" : "<description>",
665 "landing_rev": "<landing_rev>",
664 "landing_rev": "<landing_rev>",
666 "owner": "<repo_owner>",
665 "owner": "<repo_owner>",
667 "fork_of": "<name_of_fork_parent>",
666 "fork_of": "<name_of_fork_parent>",
668 "enable_downloads": "<bool>",
667 "enable_downloads": "<bool>",
669 "enable_locking": "<bool>",
668 "enable_locking": "<bool>",
670 "enable_statistics": "<bool>",
669 "enable_statistics": "<bool>",
671 },
670 },
672 ...
671 ...
673 ]
672 ]
674 error: null
673 error: null
675
674
676
675
677 grant_user_group_permission
676 grant_user_group_permission
678 ---------------------------
677 ---------------------------
679
678
680 .. py:function:: grant_user_group_permission(apiuser, repoid, usergroupid, perm)
679 .. py:function:: grant_user_group_permission(apiuser, repoid, usergroupid, perm)
681
680
682 Grant permission for a user group on the specified repository,
681 Grant permission for a user group on the specified repository,
683 or update existing permissions.
682 or update existing permissions.
684
683
685 This command can only be run using an |authtoken| with admin
684 This command can only be run using an |authtoken| with admin
686 permissions on the |repo|.
685 permissions on the |repo|.
687
686
688 :param apiuser: This is filled automatically from the |authtoken|.
687 :param apiuser: This is filled automatically from the |authtoken|.
689 :type apiuser: AuthUser
688 :type apiuser: AuthUser
690 :param repoid: Set the repository name or repository ID.
689 :param repoid: Set the repository name or repository ID.
691 :type repoid: str or int
690 :type repoid: str or int
692 :param usergroupid: Specify the ID of the user group.
691 :param usergroupid: Specify the ID of the user group.
693 :type usergroupid: str or int
692 :type usergroupid: str or int
694 :param perm: Set the user group permissions using the following
693 :param perm: Set the user group permissions using the following
695 format: (repository.(none|read|write|admin))
694 format: (repository.(none|read|write|admin))
696 :type perm: str
695 :type perm: str
697
696
698 Example output:
697 Example output:
699
698
700 .. code-block:: bash
699 .. code-block:: bash
701
700
702 id : <id_given_in_input>
701 id : <id_given_in_input>
703 result : {
702 result : {
704 "msg" : "Granted perm: `<perm>` for group: `<usersgroupname>` in repo: `<reponame>`",
703 "msg" : "Granted perm: `<perm>` for group: `<usersgroupname>` in repo: `<reponame>`",
705 "success": true
704 "success": true
706
705
707 }
706 }
708 error : null
707 error : null
709
708
710 Example error output:
709 Example error output:
711
710
712 .. code-block:: bash
711 .. code-block:: bash
713
712
714 id : <id_given_in_input>
713 id : <id_given_in_input>
715 result : null
714 result : null
716 error : {
715 error : {
717 "failed to edit permission for user group: `<usergroup>` in repo `<repo>`'
716 "failed to edit permission for user group: `<usergroup>` in repo `<repo>`'
718 }
717 }
719
718
720
719
721 grant_user_permission
720 grant_user_permission
722 ---------------------
721 ---------------------
723
722
724 .. py:function:: grant_user_permission(apiuser, repoid, userid, perm)
723 .. py:function:: grant_user_permission(apiuser, repoid, userid, perm)
725
724
726 Grant permissions for the specified user on the given repository,
725 Grant permissions for the specified user on the given repository,
727 or update existing permissions if found.
726 or update existing permissions if found.
728
727
729 This command can only be run using an |authtoken| with admin
728 This command can only be run using an |authtoken| with admin
730 permissions on the |repo|.
729 permissions on the |repo|.
731
730
732 :param apiuser: This is filled automatically from the |authtoken|.
731 :param apiuser: This is filled automatically from the |authtoken|.
733 :type apiuser: AuthUser
732 :type apiuser: AuthUser
734 :param repoid: Set the repository name or repository ID.
733 :param repoid: Set the repository name or repository ID.
735 :type repoid: str or int
734 :type repoid: str or int
736 :param userid: Set the user name.
735 :param userid: Set the user name.
737 :type userid: str
736 :type userid: str
738 :param perm: Set the user permissions, using the following format
737 :param perm: Set the user permissions, using the following format
739 ``(repository.(none|read|write|admin))``
738 ``(repository.(none|read|write|admin))``
740 :type perm: str
739 :type perm: str
741
740
742 Example output:
741 Example output:
743
742
744 .. code-block:: bash
743 .. code-block:: bash
745
744
746 id : <id_given_in_input>
745 id : <id_given_in_input>
747 result: {
746 result: {
748 "msg" : "Granted perm: `<perm>` for user: `<username>` in repo: `<reponame>`",
747 "msg" : "Granted perm: `<perm>` for user: `<username>` in repo: `<reponame>`",
749 "success": true
748 "success": true
750 }
749 }
751 error: null
750 error: null
752
751
753
752
754 invalidate_cache
753 invalidate_cache
755 ----------------
754 ----------------
756
755
757 .. py:function:: invalidate_cache(apiuser, repoid, delete_keys=<Optional:False>)
756 .. py:function:: invalidate_cache(apiuser, repoid, delete_keys=<Optional:False>)
758
757
759 Invalidates the cache for the specified repository.
758 Invalidates the cache for the specified repository.
760
759
761 This command can only be run using an |authtoken| with admin rights to
760 This command can only be run using an |authtoken| with admin rights to
762 the specified repository.
761 the specified repository.
763
762
764 This command takes the following options:
763 This command takes the following options:
765
764
766 :param apiuser: This is filled automatically from |authtoken|.
765 :param apiuser: This is filled automatically from |authtoken|.
767 :type apiuser: AuthUser
766 :type apiuser: AuthUser
768 :param repoid: Sets the repository name or repository ID.
767 :param repoid: Sets the repository name or repository ID.
769 :type repoid: str or int
768 :type repoid: str or int
770 :param delete_keys: This deletes the invalidated keys instead of
769 :param delete_keys: This deletes the invalidated keys instead of
771 just flagging them.
770 just flagging them.
772 :type delete_keys: Optional(``True`` | ``False``)
771 :type delete_keys: Optional(``True`` | ``False``)
773
772
774 Example output:
773 Example output:
775
774
776 .. code-block:: bash
775 .. code-block:: bash
777
776
778 id : <id_given_in_input>
777 id : <id_given_in_input>
779 result : {
778 result : {
780 'msg': Cache for repository `<repository name>` was invalidated,
779 'msg': Cache for repository `<repository name>` was invalidated,
781 'repository': <repository name>
780 'repository': <repository name>
782 }
781 }
783 error : null
782 error : null
784
783
785 Example error output:
784 Example error output:
786
785
787 .. code-block:: bash
786 .. code-block:: bash
788
787
789 id : <id_given_in_input>
788 id : <id_given_in_input>
790 result : null
789 result : null
791 error : {
790 error : {
792 'Error occurred during cache invalidation action'
791 'Error occurred during cache invalidation action'
793 }
792 }
794
793
795
794
796 lock
795 lock
797 ----
796 ----
798
797
799 .. py:function:: lock(apiuser, repoid, locked=<Optional:None>, userid=<Optional:<OptionalAttr:apiuser>>)
798 .. py:function:: lock(apiuser, repoid, locked=<Optional:None>, userid=<Optional:<OptionalAttr:apiuser>>)
800
799
801 Sets the lock state of the specified |repo| by the given user.
800 Sets the lock state of the specified |repo| by the given user.
802 From more information, see :ref:`repo-locking`.
801 From more information, see :ref:`repo-locking`.
803
802
804 * If the ``userid`` option is not set, the repository is locked to the
803 * If the ``userid`` option is not set, the repository is locked to the
805 user who called the method.
804 user who called the method.
806 * If the ``locked`` parameter is not set, the current lock state of the
805 * If the ``locked`` parameter is not set, the current lock state of the
807 repository is displayed.
806 repository is displayed.
808
807
809 This command can only be run using an |authtoken| with admin rights to
808 This command can only be run using an |authtoken| with admin rights to
810 the specified repository.
809 the specified repository.
811
810
812 This command takes the following options:
811 This command takes the following options:
813
812
814 :param apiuser: This is filled automatically from the |authtoken|.
813 :param apiuser: This is filled automatically from the |authtoken|.
815 :type apiuser: AuthUser
814 :type apiuser: AuthUser
816 :param repoid: Sets the repository name or repository ID.
815 :param repoid: Sets the repository name or repository ID.
817 :type repoid: str or int
816 :type repoid: str or int
818 :param locked: Sets the lock state.
817 :param locked: Sets the lock state.
819 :type locked: Optional(``True`` | ``False``)
818 :type locked: Optional(``True`` | ``False``)
820 :param userid: Set the repository lock to this user.
819 :param userid: Set the repository lock to this user.
821 :type userid: Optional(str or int)
820 :type userid: Optional(str or int)
822
821
823 Example error output:
822 Example error output:
824
823
825 .. code-block:: bash
824 .. code-block:: bash
826
825
827 id : <id_given_in_input>
826 id : <id_given_in_input>
828 result : {
827 result : {
829 'repo': '<reponame>',
828 'repo': '<reponame>',
830 'locked': <bool: lock state>,
829 'locked': <bool: lock state>,
831 'locked_since': <int: lock timestamp>,
830 'locked_since': <int: lock timestamp>,
832 'locked_by': <username of person who made the lock>,
831 'locked_by': <username of person who made the lock>,
833 'lock_reason': <str: reason for locking>,
832 'lock_reason': <str: reason for locking>,
834 'lock_state_changed': <bool: True if lock state has been changed in this request>,
833 'lock_state_changed': <bool: True if lock state has been changed in this request>,
835 'msg': 'Repo `<reponame>` locked by `<username>` on <timestamp>.'
834 'msg': 'Repo `<reponame>` locked by `<username>` on <timestamp>.'
836 or
835 or
837 'msg': 'Repo `<repository name>` not locked.'
836 'msg': 'Repo `<repository name>` not locked.'
838 or
837 or
839 'msg': 'User `<user name>` set lock state for repo `<repository name>` to `<new lock state>`'
838 'msg': 'User `<user name>` set lock state for repo `<repository name>` to `<new lock state>`'
840 }
839 }
841 error : null
840 error : null
842
841
843 Example error output:
842 Example error output:
844
843
845 .. code-block:: bash
844 .. code-block:: bash
846
845
847 id : <id_given_in_input>
846 id : <id_given_in_input>
848 result : null
847 result : null
849 error : {
848 error : {
850 'Error occurred locking repository `<reponame>`'
849 'Error occurred locking repository `<reponame>`'
851 }
850 }
852
851
853
852
854 maintenance
853 maintenance
855 -----------
854 -----------
856
855
857 .. py:function:: maintenance(apiuser, repoid)
856 .. py:function:: maintenance(apiuser, repoid)
858
857
859 Triggers a maintenance on the given repository.
858 Triggers a maintenance on the given repository.
860
859
861 This command can only be run using an |authtoken| with admin
860 This command can only be run using an |authtoken| with admin
862 rights to the specified repository. For more information,
861 rights to the specified repository. For more information,
863 see :ref:`config-token-ref`.
862 see :ref:`config-token-ref`.
864
863
865 This command takes the following options:
864 This command takes the following options:
866
865
867 :param apiuser: This is filled automatically from the |authtoken|.
866 :param apiuser: This is filled automatically from the |authtoken|.
868 :type apiuser: AuthUser
867 :type apiuser: AuthUser
869 :param repoid: The repository name or repository ID.
868 :param repoid: The repository name or repository ID.
870 :type repoid: str or int
869 :type repoid: str or int
871
870
872 Example output:
871 Example output:
873
872
874 .. code-block:: bash
873 .. code-block:: bash
875
874
876 id : <id_given_in_input>
875 id : <id_given_in_input>
877 result : {
876 result : {
878 "msg": "executed maintenance command",
877 "msg": "executed maintenance command",
879 "executed_actions": [
878 "executed_actions": [
880 <action_message>, <action_message2>...
879 <action_message>, <action_message2>...
881 ],
880 ],
882 "repository": "<repository name>"
881 "repository": "<repository name>"
883 }
882 }
884 error : null
883 error : null
885
884
886 Example error output:
885 Example error output:
887
886
888 .. code-block:: bash
887 .. code-block:: bash
889
888
890 id : <id_given_in_input>
889 id : <id_given_in_input>
891 result : null
890 result : null
892 error : {
891 error : {
893 "Unable to execute maintenance on `<reponame>`"
892 "Unable to execute maintenance on `<reponame>`"
894 }
893 }
895
894
896
895
897 pull
896 pull
898 ----
897 ----
899
898
900 .. py:function:: pull(apiuser, repoid, remote_uri=<Optional:None>)
899 .. py:function:: pull(apiuser, repoid, remote_uri=<Optional:None>)
901
900
902 Triggers a pull on the given repository from a remote location. You
901 Triggers a pull on the given repository from a remote location. You
903 can use this to keep remote repositories up-to-date.
902 can use this to keep remote repositories up-to-date.
904
903
905 This command can only be run using an |authtoken| with admin
904 This command can only be run using an |authtoken| with admin
906 rights to the specified repository. For more information,
905 rights to the specified repository. For more information,
907 see :ref:`config-token-ref`.
906 see :ref:`config-token-ref`.
908
907
909 This command takes the following options:
908 This command takes the following options:
910
909
911 :param apiuser: This is filled automatically from the |authtoken|.
910 :param apiuser: This is filled automatically from the |authtoken|.
912 :type apiuser: AuthUser
911 :type apiuser: AuthUser
913 :param repoid: The repository name or repository ID.
912 :param repoid: The repository name or repository ID.
914 :type repoid: str or int
913 :type repoid: str or int
915 :param remote_uri: Optional remote URI to pass in for pull
914 :param remote_uri: Optional remote URI to pass in for pull
916 :type remote_uri: str
915 :type remote_uri: str
917
916
918 Example output:
917 Example output:
919
918
920 .. code-block:: bash
919 .. code-block:: bash
921
920
922 id : <id_given_in_input>
921 id : <id_given_in_input>
923 result : {
922 result : {
924 "msg": "Pulled from url `<remote_url>` on repo `<repository name>`"
923 "msg": "Pulled from url `<remote_url>` on repo `<repository name>`"
925 "repository": "<repository name>"
924 "repository": "<repository name>"
926 }
925 }
927 error : null
926 error : null
928
927
929 Example error output:
928 Example error output:
930
929
931 .. code-block:: bash
930 .. code-block:: bash
932
931
933 id : <id_given_in_input>
932 id : <id_given_in_input>
934 result : null
933 result : null
935 error : {
934 error : {
936 "Unable to push changes from `<remote_url>`"
935 "Unable to push changes from `<remote_url>`"
937 }
936 }
938
937
939
938
940 remove_field_from_repo
939 remove_field_from_repo
941 ----------------------
940 ----------------------
942
941
943 .. py:function:: remove_field_from_repo(apiuser, repoid, key)
942 .. py:function:: remove_field_from_repo(apiuser, repoid, key)
944
943
945 Removes an extra field from a repository.
944 Removes an extra field from a repository.
946
945
947 This command can only be run using an |authtoken| with at least
946 This command can only be run using an |authtoken| with at least
948 write permissions to the |repo|.
947 write permissions to the |repo|.
949
948
950 :param apiuser: This is filled automatically from the |authtoken|.
949 :param apiuser: This is filled automatically from the |authtoken|.
951 :type apiuser: AuthUser
950 :type apiuser: AuthUser
952 :param repoid: Set the repository name or repository ID.
951 :param repoid: Set the repository name or repository ID.
953 :type repoid: str or int
952 :type repoid: str or int
954 :param key: Set the unique field key for this repository.
953 :param key: Set the unique field key for this repository.
955 :type key: str
954 :type key: str
956
955
957
956
958 revoke_user_group_permission
957 revoke_user_group_permission
959 ----------------------------
958 ----------------------------
960
959
961 .. py:function:: revoke_user_group_permission(apiuser, repoid, usergroupid)
960 .. py:function:: revoke_user_group_permission(apiuser, repoid, usergroupid)
962
961
963 Revoke the permissions of a user group on a given repository.
962 Revoke the permissions of a user group on a given repository.
964
963
965 This command can only be run using an |authtoken| with admin
964 This command can only be run using an |authtoken| with admin
966 permissions on the |repo|.
965 permissions on the |repo|.
967
966
968 :param apiuser: This is filled automatically from the |authtoken|.
967 :param apiuser: This is filled automatically from the |authtoken|.
969 :type apiuser: AuthUser
968 :type apiuser: AuthUser
970 :param repoid: Set the repository name or repository ID.
969 :param repoid: Set the repository name or repository ID.
971 :type repoid: str or int
970 :type repoid: str or int
972 :param usergroupid: Specify the user group ID.
971 :param usergroupid: Specify the user group ID.
973 :type usergroupid: str or int
972 :type usergroupid: str or int
974
973
975 Example output:
974 Example output:
976
975
977 .. code-block:: bash
976 .. code-block:: bash
978
977
979 id : <id_given_in_input>
978 id : <id_given_in_input>
980 result: {
979 result: {
981 "msg" : "Revoked perm for group: `<usersgroupname>` in repo: `<reponame>`",
980 "msg" : "Revoked perm for group: `<usersgroupname>` in repo: `<reponame>`",
982 "success": true
981 "success": true
983 }
982 }
984 error: null
983 error: null
985
984
986
985
987 revoke_user_permission
986 revoke_user_permission
988 ----------------------
987 ----------------------
989
988
990 .. py:function:: revoke_user_permission(apiuser, repoid, userid)
989 .. py:function:: revoke_user_permission(apiuser, repoid, userid)
991
990
992 Revoke permission for a user on the specified repository.
991 Revoke permission for a user on the specified repository.
993
992
994 This command can only be run using an |authtoken| with admin
993 This command can only be run using an |authtoken| with admin
995 permissions on the |repo|.
994 permissions on the |repo|.
996
995
997 :param apiuser: This is filled automatically from the |authtoken|.
996 :param apiuser: This is filled automatically from the |authtoken|.
998 :type apiuser: AuthUser
997 :type apiuser: AuthUser
999 :param repoid: Set the repository name or repository ID.
998 :param repoid: Set the repository name or repository ID.
1000 :type repoid: str or int
999 :type repoid: str or int
1001 :param userid: Set the user name of revoked user.
1000 :param userid: Set the user name of revoked user.
1002 :type userid: str or int
1001 :type userid: str or int
1003
1002
1004 Example error output:
1003 Example error output:
1005
1004
1006 .. code-block:: bash
1005 .. code-block:: bash
1007
1006
1008 id : <id_given_in_input>
1007 id : <id_given_in_input>
1009 result: {
1008 result: {
1010 "msg" : "Revoked perm for user: `<username>` in repo: `<reponame>`",
1009 "msg" : "Revoked perm for user: `<username>` in repo: `<reponame>`",
1011 "success": true
1010 "success": true
1012 }
1011 }
1013 error: null
1012 error: null
1014
1013
1015
1014
1016 set_repo_settings
1015 set_repo_settings
1017 -----------------
1016 -----------------
1018
1017
1019 .. py:function:: set_repo_settings(apiuser, repoid, settings)
1018 .. py:function:: set_repo_settings(apiuser, repoid, settings)
1020
1019
1021 Update repository settings. Returns true on success.
1020 Update repository settings. Returns true on success.
1022
1021
1023 :param apiuser: This is filled automatically from the |authtoken|.
1022 :param apiuser: This is filled automatically from the |authtoken|.
1024 :type apiuser: AuthUser
1023 :type apiuser: AuthUser
1025 :param repoid: The repository name or repository id.
1024 :param repoid: The repository name or repository id.
1026 :type repoid: str or int
1025 :type repoid: str or int
1027 :param settings: The new settings for the repository.
1026 :param settings: The new settings for the repository.
1028 :type: settings: dict
1027 :type: settings: dict
1029
1028
1030 Example output:
1029 Example output:
1031
1030
1032 .. code-block:: bash
1031 .. code-block:: bash
1033
1032
1034 {
1033 {
1035 "error": null,
1034 "error": null,
1036 "id": 237,
1035 "id": 237,
1037 "result": true
1036 "result": true
1038 }
1037 }
1039
1038
1040
1039
1041 strip
1040 strip
1042 -----
1041 -----
1043
1042
1044 .. py:function:: strip(apiuser, repoid, revision, branch)
1043 .. py:function:: strip(apiuser, repoid, revision, branch)
1045
1044
1046 Strips the given revision from the specified repository.
1045 Strips the given revision from the specified repository.
1047
1046
1048 * This will remove the revision and all of its decendants.
1047 * This will remove the revision and all of its decendants.
1049
1048
1050 This command can only be run using an |authtoken| with admin rights to
1049 This command can only be run using an |authtoken| with admin rights to
1051 the specified repository.
1050 the specified repository.
1052
1051
1053 This command takes the following options:
1052 This command takes the following options:
1054
1053
1055 :param apiuser: This is filled automatically from the |authtoken|.
1054 :param apiuser: This is filled automatically from the |authtoken|.
1056 :type apiuser: AuthUser
1055 :type apiuser: AuthUser
1057 :param repoid: The repository name or repository ID.
1056 :param repoid: The repository name or repository ID.
1058 :type repoid: str or int
1057 :type repoid: str or int
1059 :param revision: The revision you wish to strip.
1058 :param revision: The revision you wish to strip.
1060 :type revision: str
1059 :type revision: str
1061 :param branch: The branch from which to strip the revision.
1060 :param branch: The branch from which to strip the revision.
1062 :type branch: str
1061 :type branch: str
1063
1062
1064 Example output:
1063 Example output:
1065
1064
1066 .. code-block:: bash
1065 .. code-block:: bash
1067
1066
1068 id : <id_given_in_input>
1067 id : <id_given_in_input>
1069 result : {
1068 result : {
1070 "msg": "'Stripped commit <commit_hash> from repo `<repository name>`'"
1069 "msg": "'Stripped commit <commit_hash> from repo `<repository name>`'"
1071 "repository": "<repository name>"
1070 "repository": "<repository name>"
1072 }
1071 }
1073 error : null
1072 error : null
1074
1073
1075 Example error output:
1074 Example error output:
1076
1075
1077 .. code-block:: bash
1076 .. code-block:: bash
1078
1077
1079 id : <id_given_in_input>
1078 id : <id_given_in_input>
1080 result : null
1079 result : null
1081 error : {
1080 error : {
1082 "Unable to strip commit <commit_hash> from repo `<repository name>`"
1081 "Unable to strip commit <commit_hash> from repo `<repository name>`"
1083 }
1082 }
1084
1083
1085
1084
1086 update_repo
1085 update_repo
1087 -----------
1086 -----------
1088
1087
1089 .. py:function:: update_repo(apiuser, repoid, repo_name=<Optional:None>, owner=<Optional:<OptionalAttr:apiuser>>, description=<Optional:''>, private=<Optional:False>, clone_uri=<Optional:None>, push_uri=<Optional:None>, landing_rev=<Optional:'rev:tip'>, fork_of=<Optional:None>, enable_statistics=<Optional:False>, enable_locking=<Optional:False>, enable_downloads=<Optional:False>, fields=<Optional:''>)
1088 .. py:function:: update_repo(apiuser, repoid, repo_name=<Optional:None>, owner=<Optional:<OptionalAttr:apiuser>>, description=<Optional:''>, private=<Optional:False>, clone_uri=<Optional:None>, push_uri=<Optional:None>, landing_rev=<Optional:'rev:tip'>, fork_of=<Optional:None>, enable_statistics=<Optional:False>, enable_locking=<Optional:False>, enable_downloads=<Optional:False>, fields=<Optional:''>)
1090
1089
1091 Updates a repository with the given information.
1090 Updates a repository with the given information.
1092
1091
1093 This command can only be run using an |authtoken| with at least
1092 This command can only be run using an |authtoken| with at least
1094 admin permissions to the |repo|.
1093 admin permissions to the |repo|.
1095
1094
1096 * If the repository name contains "/", repository will be updated
1095 * If the repository name contains "/", repository will be updated
1097 accordingly with a repository group or nested repository groups
1096 accordingly with a repository group or nested repository groups
1098
1097
1099 For example repoid=repo-test name="foo/bar/repo-test" will update |repo|
1098 For example repoid=repo-test name="foo/bar/repo-test" will update |repo|
1100 called "repo-test" and place it inside group "foo/bar".
1099 called "repo-test" and place it inside group "foo/bar".
1101 You have to have permissions to access and write to the last repository
1100 You have to have permissions to access and write to the last repository
1102 group ("bar" in this example)
1101 group ("bar" in this example)
1103
1102
1104 :param apiuser: This is filled automatically from the |authtoken|.
1103 :param apiuser: This is filled automatically from the |authtoken|.
1105 :type apiuser: AuthUser
1104 :type apiuser: AuthUser
1106 :param repoid: repository name or repository ID.
1105 :param repoid: repository name or repository ID.
1107 :type repoid: str or int
1106 :type repoid: str or int
1108 :param repo_name: Update the |repo| name, including the
1107 :param repo_name: Update the |repo| name, including the
1109 repository group it's in.
1108 repository group it's in.
1110 :type repo_name: str
1109 :type repo_name: str
1111 :param owner: Set the |repo| owner.
1110 :param owner: Set the |repo| owner.
1112 :type owner: str
1111 :type owner: str
1113 :param fork_of: Set the |repo| as fork of another |repo|.
1112 :param fork_of: Set the |repo| as fork of another |repo|.
1114 :type fork_of: str
1113 :type fork_of: str
1115 :param description: Update the |repo| description.
1114 :param description: Update the |repo| description.
1116 :type description: str
1115 :type description: str
1117 :param private: Set the |repo| as private. (True | False)
1116 :param private: Set the |repo| as private. (True | False)
1118 :type private: bool
1117 :type private: bool
1119 :param clone_uri: Update the |repo| clone URI.
1118 :param clone_uri: Update the |repo| clone URI.
1120 :type clone_uri: str
1119 :type clone_uri: str
1121 :param landing_rev: Set the |repo| landing revision. Default is ``rev:tip``.
1120 :param landing_rev: Set the |repo| landing revision. Default is ``rev:tip``.
1122 :type landing_rev: str
1121 :type landing_rev: str
1123 :param enable_statistics: Enable statistics on the |repo|, (True | False).
1122 :param enable_statistics: Enable statistics on the |repo|, (True | False).
1124 :type enable_statistics: bool
1123 :type enable_statistics: bool
1125 :param enable_locking: Enable |repo| locking.
1124 :param enable_locking: Enable |repo| locking.
1126 :type enable_locking: bool
1125 :type enable_locking: bool
1127 :param enable_downloads: Enable downloads from the |repo|, (True | False).
1126 :param enable_downloads: Enable downloads from the |repo|, (True | False).
1128 :type enable_downloads: bool
1127 :type enable_downloads: bool
1129 :param fields: Add extra fields to the |repo|. Use the following
1128 :param fields: Add extra fields to the |repo|. Use the following
1130 example format: ``field_key=field_val,field_key2=fieldval2``.
1129 example format: ``field_key=field_val,field_key2=fieldval2``.
1131 Escape ', ' with \,
1130 Escape ', ' with \,
1132 :type fields: str
1131 :type fields: str
1133
1132
1134
1133
@@ -1,87 +1,87 b''
1 |RCE|
1 |RCE|
2 =====
2 =====
3
3
4 |RCE| is a high-performance source code management and collaboration system.
4 |RCE| is a high-performance source code management and collaboration system.
5 It enables you to develop projects securely behind the firewall while
5 It enables you to develop projects securely behind the firewall while
6 providing collaboration tools that work with |git|, |hg|,
6 providing collaboration tools that work with |git|, |hg|,
7 and |svn| |repos|. The user interface allows you to create, edit,
7 and |svn| |repos|. The user interface allows you to create, edit,
8 and commit files and |repos| while managing their security permissions.
8 and commit files and |repos| while managing their security permissions.
9
9
10 |RCE| provides the following features:
10 |RCE| provides the following features:
11
11
12 * Source code management.
12 * Source code management.
13 * Extended permissions management.
13 * Extended permissions management.
14 * Integrated code collaboration tools.
14 * Integrated code collaboration tools.
15 * Integrated code review and notifications.
15 * Integrated code review and notifications.
16 * Scalability provided by multi-node setup.
16 * Scalability provided by multi-node setup.
17 * Fully programmable automation API.
17 * Fully programmable automation API.
18 * Web-based hook management.
18 * Web-based hook management.
19 * Native |svn| support.
19 * Native |svn| support.
20 * Migration from existing databases.
20 * Migration from existing databases.
21 * |RCE| SDK.
21 * |RCE| SDK.
22 * Built-in analytics
22 * Built-in analytics
23 * Built in integrations including: Slack, Webhooks (used for Jenkins/TeamCity and other CIs), Jira, Redmine, Hipchat
23 * Built in integrations including: Slack, Webhooks (used for Jenkins/TeamCity and other CIs), Jira, Redmine, Hipchat
24 * Pluggable authentication system.
24 * Pluggable authentication system.
25 * Support for AD, |LDAP|, Crowd, CAS, PAM.
25 * Support for AD, |LDAP|, Crowd, CAS, PAM.
26 * Support for external authentication via Oauth Google, Github, Bitbucket, Twitter.
26 * Support for external authentication via Oauth Google, Github, Bitbucket, Twitter.
27 * Debug modes of operation.
27 * Debug modes of operation.
28 * Private and public gists.
28 * Private and public gists.
29 * Gists with limited lifetimes and within instance only sharing.
29 * Gists with limited lifetimes and within instance only sharing.
30 * Fully integrated code search function.
30 * Fully integrated code search function.
31 * Always on SSL connectivity.
31 * Always on SSL connectivity.
32
32
33 .. only:: html
33 .. only:: html
34
34
35 Table of Contents
35 Table of Contents
36 -----------------
36 -----------------
37
37
38 .. toctree::
38 .. toctree::
39 :maxdepth: 1
39 :maxdepth: 1
40 :caption: Admin Documentation
40 :caption: Admin Documentation
41
41
42 install/quick-start
42 install/quick-start
43 install/install-database
43 install/install-database
44 install/install-steps
44 install/install-steps
45 admin/system-overview
45 admin/system-overview
46 nix/default-env
46 nix/default-env
47 admin/system-admin
47 admin/system-admin
48 admin/user-admin
48 admin/user-admin
49 admin/setting-repo-perms
49 admin/repo-admin
50 admin/security-tips
50 admin/security-tips
51 auth/auth
51 auth/auth
52 issue-trackers/issue-trackers
52 issue-trackers/issue-trackers
53 admin/lab-settings
53 admin/lab-settings
54
54
55 .. toctree::
55 .. toctree::
56 :maxdepth: 1
56 :maxdepth: 1
57 :caption: Feature Documentation
57 :caption: Feature Documentation
58
58
59 collaboration/collaboration
59 collaboration/collaboration
60 collaboration/review-notifications
60 collaboration/review-notifications
61 collaboration/pull-requests
61 collaboration/pull-requests
62 code-review/code-review
62 code-review/code-review
63 integrations/integrations
63 integrations/integrations
64
64
65 .. toctree::
65 .. toctree::
66 :maxdepth: 1
66 :maxdepth: 1
67 :caption: User Documentation
67 :caption: User Documentation
68
68
69 usage/basic-usage
69 usage/basic-usage
70 tutorials/tutorials
70 tutorials/tutorials
71
71
72 .. toctree::
72 .. toctree::
73 :maxdepth: 1
73 :maxdepth: 1
74 :caption: Developer Documentation
74 :caption: Developer Documentation
75
75
76 api/api
76 api/api
77 tools/rhodecode-tools
77 tools/rhodecode-tools
78 extensions/extensions-hooks
78 extensions/extensions-hooks
79 contributing/contributing
79 contributing/contributing
80
80
81 .. toctree::
81 .. toctree::
82 :maxdepth: 1
82 :maxdepth: 1
83 :caption: About
83 :caption: About
84
84
85 known-issues/known-issues
85 known-issues/known-issues
86 release-notes/release-notes
86 release-notes/release-notes
87 admin/glossary
87 admin/glossary
@@ -1,2314 +1,2315 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2019 RhodeCode GmbH
3 # Copyright (C) 2011-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import logging
21 import logging
22 import time
22 import time
23
23
24 import rhodecode
24 import rhodecode
25 from rhodecode.api import (
25 from rhodecode.api import (
26 jsonrpc_method, JSONRPCError, JSONRPCForbidden, JSONRPCValidationError)
26 jsonrpc_method, JSONRPCError, JSONRPCForbidden, JSONRPCValidationError)
27 from rhodecode.api.utils import (
27 from rhodecode.api.utils import (
28 has_superadmin_permission, Optional, OAttr, get_repo_or_error,
28 has_superadmin_permission, Optional, OAttr, get_repo_or_error,
29 get_user_group_or_error, get_user_or_error, validate_repo_permissions,
29 get_user_group_or_error, get_user_or_error, validate_repo_permissions,
30 get_perm_or_error, parse_args, get_origin, build_commit_data,
30 get_perm_or_error, parse_args, get_origin, build_commit_data,
31 validate_set_owner_permissions)
31 validate_set_owner_permissions)
32 from rhodecode.lib import audit_logger, rc_cache
32 from rhodecode.lib import audit_logger, rc_cache
33 from rhodecode.lib import repo_maintenance
33 from rhodecode.lib import repo_maintenance
34 from rhodecode.lib.auth import HasPermissionAnyApi, HasUserGroupPermissionAnyApi
34 from rhodecode.lib.auth import HasPermissionAnyApi, HasUserGroupPermissionAnyApi
35 from rhodecode.lib.celerylib.utils import get_task_id
35 from rhodecode.lib.celerylib.utils import get_task_id
36 from rhodecode.lib.utils2 import str2bool, time_to_datetime, safe_str, safe_int
36 from rhodecode.lib.utils2 import str2bool, time_to_datetime, safe_str, safe_int
37 from rhodecode.lib.ext_json import json
37 from rhodecode.lib.ext_json import json
38 from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError
38 from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError
39 from rhodecode.lib.vcs import RepositoryError
39 from rhodecode.lib.vcs import RepositoryError
40 from rhodecode.lib.vcs.exceptions import NodeDoesNotExistError
40 from rhodecode.lib.vcs.exceptions import NodeDoesNotExistError
41 from rhodecode.model.changeset_status import ChangesetStatusModel
41 from rhodecode.model.changeset_status import ChangesetStatusModel
42 from rhodecode.model.comment import CommentsModel
42 from rhodecode.model.comment import CommentsModel
43 from rhodecode.model.db import (
43 from rhodecode.model.db import (
44 Session, ChangesetStatus, RepositoryField, Repository, RepoGroup,
44 Session, ChangesetStatus, RepositoryField, Repository, RepoGroup,
45 ChangesetComment)
45 ChangesetComment)
46 from rhodecode.model.repo import RepoModel
46 from rhodecode.model.repo import RepoModel
47 from rhodecode.model.scm import ScmModel, RepoList
47 from rhodecode.model.scm import ScmModel, RepoList
48 from rhodecode.model.settings import SettingsModel, VcsSettingsModel
48 from rhodecode.model.settings import SettingsModel, VcsSettingsModel
49 from rhodecode.model import validation_schema
49 from rhodecode.model import validation_schema
50 from rhodecode.model.validation_schema.schemas import repo_schema
50 from rhodecode.model.validation_schema.schemas import repo_schema
51
51
52 log = logging.getLogger(__name__)
52 log = logging.getLogger(__name__)
53
53
54
54
55 @jsonrpc_method()
55 @jsonrpc_method()
56 def get_repo(request, apiuser, repoid, cache=Optional(True)):
56 def get_repo(request, apiuser, repoid, cache=Optional(True)):
57 """
57 """
58 Gets an existing repository by its name or repository_id.
58 Gets an existing repository by its name or repository_id.
59
59
60 The members section so the output returns users groups or users
60 The members section so the output returns users groups or users
61 associated with that repository.
61 associated with that repository.
62
62
63 This command can only be run using an |authtoken| with admin rights,
63 This command can only be run using an |authtoken| with admin rights,
64 or users with at least read rights to the |repo|.
64 or users with at least read rights to the |repo|.
65
65
66 :param apiuser: This is filled automatically from the |authtoken|.
66 :param apiuser: This is filled automatically from the |authtoken|.
67 :type apiuser: AuthUser
67 :type apiuser: AuthUser
68 :param repoid: The repository name or repository id.
68 :param repoid: The repository name or repository id.
69 :type repoid: str or int
69 :type repoid: str or int
70 :param cache: use the cached value for last changeset
70 :param cache: use the cached value for last changeset
71 :type: cache: Optional(bool)
71 :type: cache: Optional(bool)
72
72
73 Example output:
73 Example output:
74
74
75 .. code-block:: bash
75 .. code-block:: bash
76
76
77 {
77 {
78 "error": null,
78 "error": null,
79 "id": <repo_id>,
79 "id": <repo_id>,
80 "result": {
80 "result": {
81 "clone_uri": null,
81 "clone_uri": null,
82 "created_on": "timestamp",
82 "created_on": "timestamp",
83 "description": "repo description",
83 "description": "repo description",
84 "enable_downloads": false,
84 "enable_downloads": false,
85 "enable_locking": false,
85 "enable_locking": false,
86 "enable_statistics": false,
86 "enable_statistics": false,
87 "followers": [
87 "followers": [
88 {
88 {
89 "active": true,
89 "active": true,
90 "admin": false,
90 "admin": false,
91 "api_key": "****************************************",
91 "api_key": "****************************************",
92 "api_keys": [
92 "api_keys": [
93 "****************************************"
93 "****************************************"
94 ],
94 ],
95 "email": "user@example.com",
95 "email": "user@example.com",
96 "emails": [
96 "emails": [
97 "user@example.com"
97 "user@example.com"
98 ],
98 ],
99 "extern_name": "rhodecode",
99 "extern_name": "rhodecode",
100 "extern_type": "rhodecode",
100 "extern_type": "rhodecode",
101 "firstname": "username",
101 "firstname": "username",
102 "ip_addresses": [],
102 "ip_addresses": [],
103 "language": null,
103 "language": null,
104 "last_login": "2015-09-16T17:16:35.854",
104 "last_login": "2015-09-16T17:16:35.854",
105 "lastname": "surname",
105 "lastname": "surname",
106 "user_id": <user_id>,
106 "user_id": <user_id>,
107 "username": "name"
107 "username": "name"
108 }
108 }
109 ],
109 ],
110 "fork_of": "parent-repo",
110 "fork_of": "parent-repo",
111 "landing_rev": [
111 "landing_rev": [
112 "rev",
112 "rev",
113 "tip"
113 "tip"
114 ],
114 ],
115 "last_changeset": {
115 "last_changeset": {
116 "author": "User <user@example.com>",
116 "author": "User <user@example.com>",
117 "branch": "default",
117 "branch": "default",
118 "date": "timestamp",
118 "date": "timestamp",
119 "message": "last commit message",
119 "message": "last commit message",
120 "parents": [
120 "parents": [
121 {
121 {
122 "raw_id": "commit-id"
122 "raw_id": "commit-id"
123 }
123 }
124 ],
124 ],
125 "raw_id": "commit-id",
125 "raw_id": "commit-id",
126 "revision": <revision number>,
126 "revision": <revision number>,
127 "short_id": "short id"
127 "short_id": "short id"
128 },
128 },
129 "lock_reason": null,
129 "lock_reason": null,
130 "locked_by": null,
130 "locked_by": null,
131 "locked_date": null,
131 "locked_date": null,
132 "owner": "owner-name",
132 "owner": "owner-name",
133 "permissions": [
133 "permissions": [
134 {
134 {
135 "name": "super-admin-name",
135 "name": "super-admin-name",
136 "origin": "super-admin",
136 "origin": "super-admin",
137 "permission": "repository.admin",
137 "permission": "repository.admin",
138 "type": "user"
138 "type": "user"
139 },
139 },
140 {
140 {
141 "name": "owner-name",
141 "name": "owner-name",
142 "origin": "owner",
142 "origin": "owner",
143 "permission": "repository.admin",
143 "permission": "repository.admin",
144 "type": "user"
144 "type": "user"
145 },
145 },
146 {
146 {
147 "name": "user-group-name",
147 "name": "user-group-name",
148 "origin": "permission",
148 "origin": "permission",
149 "permission": "repository.write",
149 "permission": "repository.write",
150 "type": "user_group"
150 "type": "user_group"
151 }
151 }
152 ],
152 ],
153 "private": true,
153 "private": true,
154 "repo_id": 676,
154 "repo_id": 676,
155 "repo_name": "user-group/repo-name",
155 "repo_name": "user-group/repo-name",
156 "repo_type": "hg"
156 "repo_type": "hg"
157 }
157 }
158 }
158 }
159 """
159 """
160
160
161 repo = get_repo_or_error(repoid)
161 repo = get_repo_or_error(repoid)
162 cache = Optional.extract(cache)
162 cache = Optional.extract(cache)
163
163
164 include_secrets = False
164 include_secrets = False
165 if has_superadmin_permission(apiuser):
165 if has_superadmin_permission(apiuser):
166 include_secrets = True
166 include_secrets = True
167 else:
167 else:
168 # check if we have at least read permission for this repo !
168 # check if we have at least read permission for this repo !
169 _perms = (
169 _perms = (
170 'repository.admin', 'repository.write', 'repository.read',)
170 'repository.admin', 'repository.write', 'repository.read',)
171 validate_repo_permissions(apiuser, repoid, repo, _perms)
171 validate_repo_permissions(apiuser, repoid, repo, _perms)
172
172
173 permissions = []
173 permissions = []
174 for _user in repo.permissions():
174 for _user in repo.permissions():
175 user_data = {
175 user_data = {
176 'name': _user.username,
176 'name': _user.username,
177 'permission': _user.permission,
177 'permission': _user.permission,
178 'origin': get_origin(_user),
178 'origin': get_origin(_user),
179 'type': "user",
179 'type': "user",
180 }
180 }
181 permissions.append(user_data)
181 permissions.append(user_data)
182
182
183 for _user_group in repo.permission_user_groups():
183 for _user_group in repo.permission_user_groups():
184 user_group_data = {
184 user_group_data = {
185 'name': _user_group.users_group_name,
185 'name': _user_group.users_group_name,
186 'permission': _user_group.permission,
186 'permission': _user_group.permission,
187 'origin': get_origin(_user_group),
187 'origin': get_origin(_user_group),
188 'type': "user_group",
188 'type': "user_group",
189 }
189 }
190 permissions.append(user_group_data)
190 permissions.append(user_group_data)
191
191
192 following_users = [
192 following_users = [
193 user.user.get_api_data(include_secrets=include_secrets)
193 user.user.get_api_data(include_secrets=include_secrets)
194 for user in repo.followers]
194 for user in repo.followers]
195
195
196 if not cache:
196 if not cache:
197 repo.update_commit_cache()
197 repo.update_commit_cache()
198 data = repo.get_api_data(include_secrets=include_secrets)
198 data = repo.get_api_data(include_secrets=include_secrets)
199 data['permissions'] = permissions
199 data['permissions'] = permissions
200 data['followers'] = following_users
200 data['followers'] = following_users
201 return data
201 return data
202
202
203
203
204 @jsonrpc_method()
204 @jsonrpc_method()
205 def get_repos(request, apiuser, root=Optional(None), traverse=Optional(True)):
205 def get_repos(request, apiuser, root=Optional(None), traverse=Optional(True)):
206 """
206 """
207 Lists all existing repositories.
207 Lists all existing repositories.
208
208
209 This command can only be run using an |authtoken| with admin rights,
209 This command can only be run using an |authtoken| with admin rights,
210 or users with at least read rights to |repos|.
210 or users with at least read rights to |repos|.
211
211
212 :param apiuser: This is filled automatically from the |authtoken|.
212 :param apiuser: This is filled automatically from the |authtoken|.
213 :type apiuser: AuthUser
213 :type apiuser: AuthUser
214 :param root: specify root repository group to fetch repositories.
214 :param root: specify root repository group to fetch repositories.
215 filters the returned repositories to be members of given root group.
215 filters the returned repositories to be members of given root group.
216 :type root: Optional(None)
216 :type root: Optional(None)
217 :param traverse: traverse given root into subrepositories. With this flag
217 :param traverse: traverse given root into subrepositories. With this flag
218 set to False, it will only return top-level repositories from `root`.
218 set to False, it will only return top-level repositories from `root`.
219 if root is empty it will return just top-level repositories.
219 if root is empty it will return just top-level repositories.
220 :type traverse: Optional(True)
220 :type traverse: Optional(True)
221
221
222
222
223 Example output:
223 Example output:
224
224
225 .. code-block:: bash
225 .. code-block:: bash
226
226
227 id : <id_given_in_input>
227 id : <id_given_in_input>
228 result: [
228 result: [
229 {
229 {
230 "repo_id" : "<repo_id>",
230 "repo_id" : "<repo_id>",
231 "repo_name" : "<reponame>"
231 "repo_name" : "<reponame>"
232 "repo_type" : "<repo_type>",
232 "repo_type" : "<repo_type>",
233 "clone_uri" : "<clone_uri>",
233 "clone_uri" : "<clone_uri>",
234 "private": : "<bool>",
234 "private": : "<bool>",
235 "created_on" : "<datetimecreated>",
235 "created_on" : "<datetimecreated>",
236 "description" : "<description>",
236 "description" : "<description>",
237 "landing_rev": "<landing_rev>",
237 "landing_rev": "<landing_rev>",
238 "owner": "<repo_owner>",
238 "owner": "<repo_owner>",
239 "fork_of": "<name_of_fork_parent>",
239 "fork_of": "<name_of_fork_parent>",
240 "enable_downloads": "<bool>",
240 "enable_downloads": "<bool>",
241 "enable_locking": "<bool>",
241 "enable_locking": "<bool>",
242 "enable_statistics": "<bool>",
242 "enable_statistics": "<bool>",
243 },
243 },
244 ...
244 ...
245 ]
245 ]
246 error: null
246 error: null
247 """
247 """
248
248
249 include_secrets = has_superadmin_permission(apiuser)
249 include_secrets = has_superadmin_permission(apiuser)
250 _perms = ('repository.read', 'repository.write', 'repository.admin',)
250 _perms = ('repository.read', 'repository.write', 'repository.admin',)
251 extras = {'user': apiuser}
251 extras = {'user': apiuser}
252
252
253 root = Optional.extract(root)
253 root = Optional.extract(root)
254 traverse = Optional.extract(traverse, binary=True)
254 traverse = Optional.extract(traverse, binary=True)
255
255
256 if root:
256 if root:
257 # verify parent existance, if it's empty return an error
257 # verify parent existance, if it's empty return an error
258 parent = RepoGroup.get_by_group_name(root)
258 parent = RepoGroup.get_by_group_name(root)
259 if not parent:
259 if not parent:
260 raise JSONRPCError(
260 raise JSONRPCError(
261 'Root repository group `{}` does not exist'.format(root))
261 'Root repository group `{}` does not exist'.format(root))
262
262
263 if traverse:
263 if traverse:
264 repos = RepoModel().get_repos_for_root(root=root, traverse=traverse)
264 repos = RepoModel().get_repos_for_root(root=root, traverse=traverse)
265 else:
265 else:
266 repos = RepoModel().get_repos_for_root(root=parent)
266 repos = RepoModel().get_repos_for_root(root=parent)
267 else:
267 else:
268 if traverse:
268 if traverse:
269 repos = RepoModel().get_all()
269 repos = RepoModel().get_all()
270 else:
270 else:
271 # return just top-level
271 # return just top-level
272 repos = RepoModel().get_repos_for_root(root=None)
272 repos = RepoModel().get_repos_for_root(root=None)
273
273
274 repo_list = RepoList(repos, perm_set=_perms, extra_kwargs=extras)
274 repo_list = RepoList(repos, perm_set=_perms, extra_kwargs=extras)
275 return [repo.get_api_data(include_secrets=include_secrets)
275 return [repo.get_api_data(include_secrets=include_secrets)
276 for repo in repo_list]
276 for repo in repo_list]
277
277
278
278
279 @jsonrpc_method()
279 @jsonrpc_method()
280 def get_repo_changeset(request, apiuser, repoid, revision,
280 def get_repo_changeset(request, apiuser, repoid, revision,
281 details=Optional('basic')):
281 details=Optional('basic')):
282 """
282 """
283 Returns information about a changeset.
283 Returns information about a changeset.
284
284
285 Additionally parameters define the amount of details returned by
285 Additionally parameters define the amount of details returned by
286 this function.
286 this function.
287
287
288 This command can only be run using an |authtoken| with admin rights,
288 This command can only be run using an |authtoken| with admin rights,
289 or users with at least read rights to the |repo|.
289 or users with at least read rights to the |repo|.
290
290
291 :param apiuser: This is filled automatically from the |authtoken|.
291 :param apiuser: This is filled automatically from the |authtoken|.
292 :type apiuser: AuthUser
292 :type apiuser: AuthUser
293 :param repoid: The repository name or repository id
293 :param repoid: The repository name or repository id
294 :type repoid: str or int
294 :type repoid: str or int
295 :param revision: revision for which listing should be done
295 :param revision: revision for which listing should be done
296 :type revision: str
296 :type revision: str
297 :param details: details can be 'basic|extended|full' full gives diff
297 :param details: details can be 'basic|extended|full' full gives diff
298 info details like the diff itself, and number of changed files etc.
298 info details like the diff itself, and number of changed files etc.
299 :type details: Optional(str)
299 :type details: Optional(str)
300
300
301 """
301 """
302 repo = get_repo_or_error(repoid)
302 repo = get_repo_or_error(repoid)
303 if not has_superadmin_permission(apiuser):
303 if not has_superadmin_permission(apiuser):
304 _perms = (
304 _perms = (
305 'repository.admin', 'repository.write', 'repository.read',)
305 'repository.admin', 'repository.write', 'repository.read',)
306 validate_repo_permissions(apiuser, repoid, repo, _perms)
306 validate_repo_permissions(apiuser, repoid, repo, _perms)
307
307
308 changes_details = Optional.extract(details)
308 changes_details = Optional.extract(details)
309 _changes_details_types = ['basic', 'extended', 'full']
309 _changes_details_types = ['basic', 'extended', 'full']
310 if changes_details not in _changes_details_types:
310 if changes_details not in _changes_details_types:
311 raise JSONRPCError(
311 raise JSONRPCError(
312 'ret_type must be one of %s' % (
312 'ret_type must be one of %s' % (
313 ','.join(_changes_details_types)))
313 ','.join(_changes_details_types)))
314
314
315 pre_load = ['author', 'branch', 'date', 'message', 'parents',
315 pre_load = ['author', 'branch', 'date', 'message', 'parents',
316 'status', '_commit', '_file_paths']
316 'status', '_commit', '_file_paths']
317
317
318 try:
318 try:
319 cs = repo.get_commit(commit_id=revision, pre_load=pre_load)
319 cs = repo.get_commit(commit_id=revision, pre_load=pre_load)
320 except TypeError as e:
320 except TypeError as e:
321 raise JSONRPCError(safe_str(e))
321 raise JSONRPCError(safe_str(e))
322 _cs_json = cs.__json__()
322 _cs_json = cs.__json__()
323 _cs_json['diff'] = build_commit_data(cs, changes_details)
323 _cs_json['diff'] = build_commit_data(cs, changes_details)
324 if changes_details == 'full':
324 if changes_details == 'full':
325 _cs_json['refs'] = cs._get_refs()
325 _cs_json['refs'] = cs._get_refs()
326 return _cs_json
326 return _cs_json
327
327
328
328
329 @jsonrpc_method()
329 @jsonrpc_method()
330 def get_repo_changesets(request, apiuser, repoid, start_rev, limit,
330 def get_repo_changesets(request, apiuser, repoid, start_rev, limit,
331 details=Optional('basic')):
331 details=Optional('basic')):
332 """
332 """
333 Returns a set of commits limited by the number starting
333 Returns a set of commits limited by the number starting
334 from the `start_rev` option.
334 from the `start_rev` option.
335
335
336 Additional parameters define the amount of details returned by this
336 Additional parameters define the amount of details returned by this
337 function.
337 function.
338
338
339 This command can only be run using an |authtoken| with admin rights,
339 This command can only be run using an |authtoken| with admin rights,
340 or users with at least read rights to |repos|.
340 or users with at least read rights to |repos|.
341
341
342 :param apiuser: This is filled automatically from the |authtoken|.
342 :param apiuser: This is filled automatically from the |authtoken|.
343 :type apiuser: AuthUser
343 :type apiuser: AuthUser
344 :param repoid: The repository name or repository ID.
344 :param repoid: The repository name or repository ID.
345 :type repoid: str or int
345 :type repoid: str or int
346 :param start_rev: The starting revision from where to get changesets.
346 :param start_rev: The starting revision from where to get changesets.
347 :type start_rev: str
347 :type start_rev: str
348 :param limit: Limit the number of commits to this amount
348 :param limit: Limit the number of commits to this amount
349 :type limit: str or int
349 :type limit: str or int
350 :param details: Set the level of detail returned. Valid option are:
350 :param details: Set the level of detail returned. Valid option are:
351 ``basic``, ``extended`` and ``full``.
351 ``basic``, ``extended`` and ``full``.
352 :type details: Optional(str)
352 :type details: Optional(str)
353
353
354 .. note::
354 .. note::
355
355
356 Setting the parameter `details` to the value ``full`` is extensive
356 Setting the parameter `details` to the value ``full`` is extensive
357 and returns details like the diff itself, and the number
357 and returns details like the diff itself, and the number
358 of changed files.
358 of changed files.
359
359
360 """
360 """
361 repo = get_repo_or_error(repoid)
361 repo = get_repo_or_error(repoid)
362 if not has_superadmin_permission(apiuser):
362 if not has_superadmin_permission(apiuser):
363 _perms = (
363 _perms = (
364 'repository.admin', 'repository.write', 'repository.read',)
364 'repository.admin', 'repository.write', 'repository.read',)
365 validate_repo_permissions(apiuser, repoid, repo, _perms)
365 validate_repo_permissions(apiuser, repoid, repo, _perms)
366
366
367 changes_details = Optional.extract(details)
367 changes_details = Optional.extract(details)
368 _changes_details_types = ['basic', 'extended', 'full']
368 _changes_details_types = ['basic', 'extended', 'full']
369 if changes_details not in _changes_details_types:
369 if changes_details not in _changes_details_types:
370 raise JSONRPCError(
370 raise JSONRPCError(
371 'ret_type must be one of %s' % (
371 'ret_type must be one of %s' % (
372 ','.join(_changes_details_types)))
372 ','.join(_changes_details_types)))
373
373
374 limit = int(limit)
374 limit = int(limit)
375 pre_load = ['author', 'branch', 'date', 'message', 'parents',
375 pre_load = ['author', 'branch', 'date', 'message', 'parents',
376 'status', '_commit', '_file_paths']
376 'status', '_commit', '_file_paths']
377
377
378 vcs_repo = repo.scm_instance()
378 vcs_repo = repo.scm_instance()
379 # SVN needs a special case to distinguish its index and commit id
379 # SVN needs a special case to distinguish its index and commit id
380 if vcs_repo and vcs_repo.alias == 'svn' and (start_rev == '0'):
380 if vcs_repo and vcs_repo.alias == 'svn' and (start_rev == '0'):
381 start_rev = vcs_repo.commit_ids[0]
381 start_rev = vcs_repo.commit_ids[0]
382
382
383 try:
383 try:
384 commits = vcs_repo.get_commits(
384 commits = vcs_repo.get_commits(
385 start_id=start_rev, pre_load=pre_load, translate_tags=False)
385 start_id=start_rev, pre_load=pre_load, translate_tags=False)
386 except TypeError as e:
386 except TypeError as e:
387 raise JSONRPCError(safe_str(e))
387 raise JSONRPCError(safe_str(e))
388 except Exception:
388 except Exception:
389 log.exception('Fetching of commits failed')
389 log.exception('Fetching of commits failed')
390 raise JSONRPCError('Error occurred during commit fetching')
390 raise JSONRPCError('Error occurred during commit fetching')
391
391
392 ret = []
392 ret = []
393 for cnt, commit in enumerate(commits):
393 for cnt, commit in enumerate(commits):
394 if cnt >= limit != -1:
394 if cnt >= limit != -1:
395 break
395 break
396 _cs_json = commit.__json__()
396 _cs_json = commit.__json__()
397 _cs_json['diff'] = build_commit_data(commit, changes_details)
397 _cs_json['diff'] = build_commit_data(commit, changes_details)
398 if changes_details == 'full':
398 if changes_details == 'full':
399 _cs_json['refs'] = {
399 _cs_json['refs'] = {
400 'branches': [commit.branch],
400 'branches': [commit.branch],
401 'bookmarks': getattr(commit, 'bookmarks', []),
401 'bookmarks': getattr(commit, 'bookmarks', []),
402 'tags': commit.tags
402 'tags': commit.tags
403 }
403 }
404 ret.append(_cs_json)
404 ret.append(_cs_json)
405 return ret
405 return ret
406
406
407
407
408 @jsonrpc_method()
408 @jsonrpc_method()
409 def get_repo_nodes(request, apiuser, repoid, revision, root_path,
409 def get_repo_nodes(request, apiuser, repoid, revision, root_path,
410 ret_type=Optional('all'), details=Optional('basic'),
410 ret_type=Optional('all'), details=Optional('basic'),
411 max_file_bytes=Optional(None)):
411 max_file_bytes=Optional(None)):
412 """
412 """
413 Returns a list of nodes and children in a flat list for a given
413 Returns a list of nodes and children in a flat list for a given
414 path at given revision.
414 path at given revision.
415
415
416 It's possible to specify ret_type to show only `files` or `dirs`.
416 It's possible to specify ret_type to show only `files` or `dirs`.
417
417
418 This command can only be run using an |authtoken| with admin rights,
418 This command can only be run using an |authtoken| with admin rights,
419 or users with at least read rights to |repos|.
419 or users with at least read rights to |repos|.
420
420
421 :param apiuser: This is filled automatically from the |authtoken|.
421 :param apiuser: This is filled automatically from the |authtoken|.
422 :type apiuser: AuthUser
422 :type apiuser: AuthUser
423 :param repoid: The repository name or repository ID.
423 :param repoid: The repository name or repository ID.
424 :type repoid: str or int
424 :type repoid: str or int
425 :param revision: The revision for which listing should be done.
425 :param revision: The revision for which listing should be done.
426 :type revision: str
426 :type revision: str
427 :param root_path: The path from which to start displaying.
427 :param root_path: The path from which to start displaying.
428 :type root_path: str
428 :type root_path: str
429 :param ret_type: Set the return type. Valid options are
429 :param ret_type: Set the return type. Valid options are
430 ``all`` (default), ``files`` and ``dirs``.
430 ``all`` (default), ``files`` and ``dirs``.
431 :type ret_type: Optional(str)
431 :type ret_type: Optional(str)
432 :param details: Returns extended information about nodes, such as
432 :param details: Returns extended information about nodes, such as
433 md5, binary, and or content.
433 md5, binary, and or content.
434 The valid options are ``basic`` and ``full``.
434 The valid options are ``basic`` and ``full``.
435 :type details: Optional(str)
435 :type details: Optional(str)
436 :param max_file_bytes: Only return file content under this file size bytes
436 :param max_file_bytes: Only return file content under this file size bytes
437 :type details: Optional(int)
437 :type details: Optional(int)
438
438
439 Example output:
439 Example output:
440
440
441 .. code-block:: bash
441 .. code-block:: bash
442
442
443 id : <id_given_in_input>
443 id : <id_given_in_input>
444 result: [
444 result: [
445 {
445 {
446 "binary": false,
446 "binary": false,
447 "content": "File line\nLine2\n",
447 "content": "File line",
448 "extension": "md",
448 "extension": "md",
449 "lines": 2,
449 "lines": 2,
450 "md5": "059fa5d29b19c0657e384749480f6422",
450 "md5": "059fa5d29b19c0657e384749480f6422",
451 "mimetype": "text/x-minidsrc",
451 "mimetype": "text/x-minidsrc",
452 "name": "file.md",
452 "name": "file.md",
453 "size": 580,
453 "size": 580,
454 "type": "file"
454 "type": "file"
455 },
455 },
456 ...
456 ...
457 ]
457 ]
458 error: null
458 error: null
459 """
459 """
460
460
461 repo = get_repo_or_error(repoid)
461 repo = get_repo_or_error(repoid)
462 if not has_superadmin_permission(apiuser):
462 if not has_superadmin_permission(apiuser):
463 _perms = ('repository.admin', 'repository.write', 'repository.read',)
463 _perms = ('repository.admin', 'repository.write', 'repository.read',)
464 validate_repo_permissions(apiuser, repoid, repo, _perms)
464 validate_repo_permissions(apiuser, repoid, repo, _perms)
465
465
466 ret_type = Optional.extract(ret_type)
466 ret_type = Optional.extract(ret_type)
467 details = Optional.extract(details)
467 details = Optional.extract(details)
468 _extended_types = ['basic', 'full']
468 _extended_types = ['basic', 'full']
469 if details not in _extended_types:
469 if details not in _extended_types:
470 raise JSONRPCError('ret_type must be one of %s' % (','.join(_extended_types)))
470 raise JSONRPCError('ret_type must be one of %s' % (','.join(_extended_types)))
471 extended_info = False
471 extended_info = False
472 content = False
472 content = False
473 if details == 'basic':
473 if details == 'basic':
474 extended_info = True
474 extended_info = True
475
475
476 if details == 'full':
476 if details == 'full':
477 extended_info = content = True
477 extended_info = content = True
478
478
479 _map = {}
479 _map = {}
480 try:
480 try:
481 # check if repo is not empty by any chance, skip quicker if it is.
481 # check if repo is not empty by any chance, skip quicker if it is.
482 _scm = repo.scm_instance()
482 _scm = repo.scm_instance()
483 if _scm.is_empty():
483 if _scm.is_empty():
484 return []
484 return []
485
485
486 _d, _f = ScmModel().get_nodes(
486 _d, _f = ScmModel().get_nodes(
487 repo, revision, root_path, flat=False,
487 repo, revision, root_path, flat=False,
488 extended_info=extended_info, content=content,
488 extended_info=extended_info, content=content,
489 max_file_bytes=max_file_bytes)
489 max_file_bytes=max_file_bytes)
490 _map = {
490 _map = {
491 'all': _d + _f,
491 'all': _d + _f,
492 'files': _f,
492 'files': _f,
493 'dirs': _d,
493 'dirs': _d,
494 }
494 }
495 return _map[ret_type]
495 return _map[ret_type]
496 except KeyError:
496 except KeyError:
497 raise JSONRPCError(
497 raise JSONRPCError(
498 'ret_type must be one of %s' % (','.join(sorted(_map.keys()))))
498 'ret_type must be one of %s' % (','.join(sorted(_map.keys()))))
499 except Exception:
499 except Exception:
500 log.exception("Exception occurred while trying to get repo nodes")
500 log.exception("Exception occurred while trying to get repo nodes")
501 raise JSONRPCError(
501 raise JSONRPCError(
502 'failed to get repo: `%s` nodes' % repo.repo_name
502 'failed to get repo: `%s` nodes' % repo.repo_name
503 )
503 )
504
504
505
505
506 @jsonrpc_method()
506 @jsonrpc_method()
507 def get_repo_file(request, apiuser, repoid, commit_id, file_path,
507 def get_repo_file(request, apiuser, repoid, commit_id, file_path,
508 max_file_bytes=Optional(None), details=Optional('basic'),
508 max_file_bytes=Optional(None), details=Optional('basic'),
509 cache=Optional(True)):
509 cache=Optional(True)):
510 """
510 """
511 Returns a single file from repository at given revision.
511 Returns a single file from repository at given revision.
512
512
513 This command can only be run using an |authtoken| with admin rights,
513 This command can only be run using an |authtoken| with admin rights,
514 or users with at least read rights to |repos|.
514 or users with at least read rights to |repos|.
515
515
516 :param apiuser: This is filled automatically from the |authtoken|.
516 :param apiuser: This is filled automatically from the |authtoken|.
517 :type apiuser: AuthUser
517 :type apiuser: AuthUser
518 :param repoid: The repository name or repository ID.
518 :param repoid: The repository name or repository ID.
519 :type repoid: str or int
519 :type repoid: str or int
520 :param commit_id: The revision for which listing should be done.
520 :param commit_id: The revision for which listing should be done.
521 :type commit_id: str
521 :type commit_id: str
522 :param file_path: The path from which to start displaying.
522 :param file_path: The path from which to start displaying.
523 :type file_path: str
523 :type file_path: str
524 :param details: Returns different set of information about nodes.
524 :param details: Returns different set of information about nodes.
525 The valid options are ``minimal`` ``basic`` and ``full``.
525 The valid options are ``minimal`` ``basic`` and ``full``.
526 :type details: Optional(str)
526 :type details: Optional(str)
527 :param max_file_bytes: Only return file content under this file size bytes
527 :param max_file_bytes: Only return file content under this file size bytes
528 :type max_file_bytes: Optional(int)
528 :type max_file_bytes: Optional(int)
529 :param cache: Use internal caches for fetching files. If disabled fetching
529 :param cache: Use internal caches for fetching files. If disabled fetching
530 files is slower but more memory efficient
530 files is slower but more memory efficient
531 :type cache: Optional(bool)
531 :type cache: Optional(bool)
532
532 Example output:
533 Example output:
533
534
534 .. code-block:: bash
535 .. code-block:: bash
535
536
536 id : <id_given_in_input>
537 id : <id_given_in_input>
537 result: {
538 result: {
538 "binary": false,
539 "binary": false,
539 "extension": "py",
540 "extension": "py",
540 "lines": 35,
541 "lines": 35,
541 "content": "....",
542 "content": "....",
542 "md5": "76318336366b0f17ee249e11b0c99c41",
543 "md5": "76318336366b0f17ee249e11b0c99c41",
543 "mimetype": "text/x-python",
544 "mimetype": "text/x-python",
544 "name": "python.py",
545 "name": "python.py",
545 "size": 817,
546 "size": 817,
546 "type": "file",
547 "type": "file",
547 }
548 }
548 error: null
549 error: null
549 """
550 """
550
551
551 repo = get_repo_or_error(repoid)
552 repo = get_repo_or_error(repoid)
552 if not has_superadmin_permission(apiuser):
553 if not has_superadmin_permission(apiuser):
553 _perms = ('repository.admin', 'repository.write', 'repository.read',)
554 _perms = ('repository.admin', 'repository.write', 'repository.read',)
554 validate_repo_permissions(apiuser, repoid, repo, _perms)
555 validate_repo_permissions(apiuser, repoid, repo, _perms)
555
556
556 cache = Optional.extract(cache, binary=True)
557 cache = Optional.extract(cache, binary=True)
557 details = Optional.extract(details)
558 details = Optional.extract(details)
558 _extended_types = ['minimal', 'minimal+search', 'basic', 'full']
559 _extended_types = ['minimal', 'minimal+search', 'basic', 'full']
559 if details not in _extended_types:
560 if details not in _extended_types:
560 raise JSONRPCError(
561 raise JSONRPCError(
561 'ret_type must be one of %s, got %s' % (','.join(_extended_types)), details)
562 'ret_type must be one of %s, got %s' % (','.join(_extended_types)), details)
562 extended_info = False
563 extended_info = False
563 content = False
564 content = False
564
565
565 if details == 'minimal':
566 if details == 'minimal':
566 extended_info = False
567 extended_info = False
567
568
568 elif details == 'basic':
569 elif details == 'basic':
569 extended_info = True
570 extended_info = True
570
571
571 elif details == 'full':
572 elif details == 'full':
572 extended_info = content = True
573 extended_info = content = True
573
574
574 try:
575 try:
575 # check if repo is not empty by any chance, skip quicker if it is.
576 # check if repo is not empty by any chance, skip quicker if it is.
576 _scm = repo.scm_instance()
577 _scm = repo.scm_instance()
577 if _scm.is_empty():
578 if _scm.is_empty():
578 return None
579 return None
579
580
580 node = ScmModel().get_node(
581 node = ScmModel().get_node(
581 repo, commit_id, file_path, extended_info=extended_info,
582 repo, commit_id, file_path, extended_info=extended_info,
582 content=content, max_file_bytes=max_file_bytes, cache=cache)
583 content=content, max_file_bytes=max_file_bytes, cache=cache)
583 except NodeDoesNotExistError:
584 except NodeDoesNotExistError:
584 raise JSONRPCError('There is no file in repo: `{}` at path `{}` for commit: `{}`'.format(
585 raise JSONRPCError('There is no file in repo: `{}` at path `{}` for commit: `{}`'.format(
585 repo.repo_name, file_path, commit_id))
586 repo.repo_name, file_path, commit_id))
586 except Exception:
587 except Exception:
587 log.exception("Exception occurred while trying to get repo %s file",
588 log.exception("Exception occurred while trying to get repo %s file",
588 repo.repo_name)
589 repo.repo_name)
589 raise JSONRPCError('failed to get repo: `{}` file at path {}'.format(
590 raise JSONRPCError('failed to get repo: `{}` file at path {}'.format(
590 repo.repo_name, file_path))
591 repo.repo_name, file_path))
591
592
592 return node
593 return node
593
594
594
595
595 @jsonrpc_method()
596 @jsonrpc_method()
596 def get_repo_fts_tree(request, apiuser, repoid, commit_id, root_path):
597 def get_repo_fts_tree(request, apiuser, repoid, commit_id, root_path):
597 """
598 """
598 Returns a list of tree nodes for path at given revision. This api is built
599 Returns a list of tree nodes for path at given revision. This api is built
599 strictly for usage in full text search building, and shouldn't be consumed
600 strictly for usage in full text search building, and shouldn't be consumed
600
601
601 This command can only be run using an |authtoken| with admin rights,
602 This command can only be run using an |authtoken| with admin rights,
602 or users with at least read rights to |repos|.
603 or users with at least read rights to |repos|.
603
604
604 """
605 """
605
606
606 repo = get_repo_or_error(repoid)
607 repo = get_repo_or_error(repoid)
607 if not has_superadmin_permission(apiuser):
608 if not has_superadmin_permission(apiuser):
608 _perms = ('repository.admin', 'repository.write', 'repository.read',)
609 _perms = ('repository.admin', 'repository.write', 'repository.read',)
609 validate_repo_permissions(apiuser, repoid, repo, _perms)
610 validate_repo_permissions(apiuser, repoid, repo, _perms)
610
611
611 repo_id = repo.repo_id
612 repo_id = repo.repo_id
612 cache_seconds = safe_int(rhodecode.CONFIG.get('rc_cache.cache_repo.expiration_time'))
613 cache_seconds = safe_int(rhodecode.CONFIG.get('rc_cache.cache_repo.expiration_time'))
613 cache_on = cache_seconds > 0
614 cache_on = cache_seconds > 0
614
615
615 cache_namespace_uid = 'cache_repo.{}'.format(repo_id)
616 cache_namespace_uid = 'cache_repo.{}'.format(repo_id)
616 region = rc_cache.get_or_create_region('cache_repo', cache_namespace_uid)
617 region = rc_cache.get_or_create_region('cache_repo', cache_namespace_uid)
617
618
618 @region.conditional_cache_on_arguments(namespace=cache_namespace_uid,
619 @region.conditional_cache_on_arguments(namespace=cache_namespace_uid,
619 condition=cache_on)
620 condition=cache_on)
620 def compute_fts_tree(repo_id, commit_id, root_path, cache_ver):
621 def compute_fts_tree(repo_id, commit_id, root_path, cache_ver):
621 return ScmModel().get_fts_data(repo_id, commit_id, root_path)
622 return ScmModel().get_fts_data(repo_id, commit_id, root_path)
622
623
623 try:
624 try:
624 # check if repo is not empty by any chance, skip quicker if it is.
625 # check if repo is not empty by any chance, skip quicker if it is.
625 _scm = repo.scm_instance()
626 _scm = repo.scm_instance()
626 if _scm.is_empty():
627 if _scm.is_empty():
627 return []
628 return []
628 except RepositoryError:
629 except RepositoryError:
629 log.exception("Exception occurred while trying to get repo nodes")
630 log.exception("Exception occurred while trying to get repo nodes")
630 raise JSONRPCError('failed to get repo: `%s` nodes' % repo.repo_name)
631 raise JSONRPCError('failed to get repo: `%s` nodes' % repo.repo_name)
631
632
632 try:
633 try:
633 # we need to resolve commit_id to a FULL sha for cache to work correctly.
634 # we need to resolve commit_id to a FULL sha for cache to work correctly.
634 # sending 'master' is a pointer that needs to be translated to current commit.
635 # sending 'master' is a pointer that needs to be translated to current commit.
635 commit_id = _scm.get_commit(commit_id=commit_id).raw_id
636 commit_id = _scm.get_commit(commit_id=commit_id).raw_id
636 log.debug(
637 log.debug(
637 'Computing FTS REPO TREE for repo_id %s commit_id `%s` '
638 'Computing FTS REPO TREE for repo_id %s commit_id `%s` '
638 'with caching: %s[TTL: %ss]' % (
639 'with caching: %s[TTL: %ss]' % (
639 repo_id, commit_id, cache_on, cache_seconds or 0))
640 repo_id, commit_id, cache_on, cache_seconds or 0))
640
641
641 tree_files = compute_fts_tree(repo_id, commit_id, root_path, 'v1')
642 tree_files = compute_fts_tree(repo_id, commit_id, root_path, 'v1')
642 return tree_files
643 return tree_files
643
644
644 except Exception:
645 except Exception:
645 log.exception("Exception occurred while trying to get repo nodes")
646 log.exception("Exception occurred while trying to get repo nodes")
646 raise JSONRPCError('failed to get repo: `%s` nodes' % repo.repo_name)
647 raise JSONRPCError('failed to get repo: `%s` nodes' % repo.repo_name)
647
648
648
649
649 @jsonrpc_method()
650 @jsonrpc_method()
650 def get_repo_refs(request, apiuser, repoid):
651 def get_repo_refs(request, apiuser, repoid):
651 """
652 """
652 Returns a dictionary of current references. It returns
653 Returns a dictionary of current references. It returns
653 bookmarks, branches, closed_branches, and tags for given repository
654 bookmarks, branches, closed_branches, and tags for given repository
654
655
655 It's possible to specify ret_type to show only `files` or `dirs`.
656 It's possible to specify ret_type to show only `files` or `dirs`.
656
657
657 This command can only be run using an |authtoken| with admin rights,
658 This command can only be run using an |authtoken| with admin rights,
658 or users with at least read rights to |repos|.
659 or users with at least read rights to |repos|.
659
660
660 :param apiuser: This is filled automatically from the |authtoken|.
661 :param apiuser: This is filled automatically from the |authtoken|.
661 :type apiuser: AuthUser
662 :type apiuser: AuthUser
662 :param repoid: The repository name or repository ID.
663 :param repoid: The repository name or repository ID.
663 :type repoid: str or int
664 :type repoid: str or int
664
665
665 Example output:
666 Example output:
666
667
667 .. code-block:: bash
668 .. code-block:: bash
668
669
669 id : <id_given_in_input>
670 id : <id_given_in_input>
670 "result": {
671 "result": {
671 "bookmarks": {
672 "bookmarks": {
672 "dev": "5611d30200f4040ba2ab4f3d64e5b06408a02188",
673 "dev": "5611d30200f4040ba2ab4f3d64e5b06408a02188",
673 "master": "367f590445081d8ec8c2ea0456e73ae1f1c3d6cf"
674 "master": "367f590445081d8ec8c2ea0456e73ae1f1c3d6cf"
674 },
675 },
675 "branches": {
676 "branches": {
676 "default": "5611d30200f4040ba2ab4f3d64e5b06408a02188",
677 "default": "5611d30200f4040ba2ab4f3d64e5b06408a02188",
677 "stable": "367f590445081d8ec8c2ea0456e73ae1f1c3d6cf"
678 "stable": "367f590445081d8ec8c2ea0456e73ae1f1c3d6cf"
678 },
679 },
679 "branches_closed": {},
680 "branches_closed": {},
680 "tags": {
681 "tags": {
681 "tip": "5611d30200f4040ba2ab4f3d64e5b06408a02188",
682 "tip": "5611d30200f4040ba2ab4f3d64e5b06408a02188",
682 "v4.4.0": "1232313f9e6adac5ce5399c2a891dc1e72b79022",
683 "v4.4.0": "1232313f9e6adac5ce5399c2a891dc1e72b79022",
683 "v4.4.1": "cbb9f1d329ae5768379cdec55a62ebdd546c4e27",
684 "v4.4.1": "cbb9f1d329ae5768379cdec55a62ebdd546c4e27",
684 "v4.4.2": "24ffe44a27fcd1c5b6936144e176b9f6dd2f3a17",
685 "v4.4.2": "24ffe44a27fcd1c5b6936144e176b9f6dd2f3a17",
685 }
686 }
686 }
687 }
687 error: null
688 error: null
688 """
689 """
689
690
690 repo = get_repo_or_error(repoid)
691 repo = get_repo_or_error(repoid)
691 if not has_superadmin_permission(apiuser):
692 if not has_superadmin_permission(apiuser):
692 _perms = ('repository.admin', 'repository.write', 'repository.read',)
693 _perms = ('repository.admin', 'repository.write', 'repository.read',)
693 validate_repo_permissions(apiuser, repoid, repo, _perms)
694 validate_repo_permissions(apiuser, repoid, repo, _perms)
694
695
695 try:
696 try:
696 # check if repo is not empty by any chance, skip quicker if it is.
697 # check if repo is not empty by any chance, skip quicker if it is.
697 vcs_instance = repo.scm_instance()
698 vcs_instance = repo.scm_instance()
698 refs = vcs_instance.refs()
699 refs = vcs_instance.refs()
699 return refs
700 return refs
700 except Exception:
701 except Exception:
701 log.exception("Exception occurred while trying to get repo refs")
702 log.exception("Exception occurred while trying to get repo refs")
702 raise JSONRPCError(
703 raise JSONRPCError(
703 'failed to get repo: `%s` references' % repo.repo_name
704 'failed to get repo: `%s` references' % repo.repo_name
704 )
705 )
705
706
706
707
707 @jsonrpc_method()
708 @jsonrpc_method()
708 def create_repo(
709 def create_repo(
709 request, apiuser, repo_name, repo_type,
710 request, apiuser, repo_name, repo_type,
710 owner=Optional(OAttr('apiuser')),
711 owner=Optional(OAttr('apiuser')),
711 description=Optional(''),
712 description=Optional(''),
712 private=Optional(False),
713 private=Optional(False),
713 clone_uri=Optional(None),
714 clone_uri=Optional(None),
714 push_uri=Optional(None),
715 push_uri=Optional(None),
715 landing_rev=Optional('rev:tip'),
716 landing_rev=Optional('rev:tip'),
716 enable_statistics=Optional(False),
717 enable_statistics=Optional(False),
717 enable_locking=Optional(False),
718 enable_locking=Optional(False),
718 enable_downloads=Optional(False),
719 enable_downloads=Optional(False),
719 copy_permissions=Optional(False)):
720 copy_permissions=Optional(False)):
720 """
721 """
721 Creates a repository.
722 Creates a repository.
722
723
723 * If the repository name contains "/", repository will be created inside
724 * If the repository name contains "/", repository will be created inside
724 a repository group or nested repository groups
725 a repository group or nested repository groups
725
726
726 For example "foo/bar/repo1" will create |repo| called "repo1" inside
727 For example "foo/bar/repo1" will create |repo| called "repo1" inside
727 group "foo/bar". You have to have permissions to access and write to
728 group "foo/bar". You have to have permissions to access and write to
728 the last repository group ("bar" in this example)
729 the last repository group ("bar" in this example)
729
730
730 This command can only be run using an |authtoken| with at least
731 This command can only be run using an |authtoken| with at least
731 permissions to create repositories, or write permissions to
732 permissions to create repositories, or write permissions to
732 parent repository groups.
733 parent repository groups.
733
734
734 :param apiuser: This is filled automatically from the |authtoken|.
735 :param apiuser: This is filled automatically from the |authtoken|.
735 :type apiuser: AuthUser
736 :type apiuser: AuthUser
736 :param repo_name: Set the repository name.
737 :param repo_name: Set the repository name.
737 :type repo_name: str
738 :type repo_name: str
738 :param repo_type: Set the repository type; 'hg','git', or 'svn'.
739 :param repo_type: Set the repository type; 'hg','git', or 'svn'.
739 :type repo_type: str
740 :type repo_type: str
740 :param owner: user_id or username
741 :param owner: user_id or username
741 :type owner: Optional(str)
742 :type owner: Optional(str)
742 :param description: Set the repository description.
743 :param description: Set the repository description.
743 :type description: Optional(str)
744 :type description: Optional(str)
744 :param private: set repository as private
745 :param private: set repository as private
745 :type private: bool
746 :type private: bool
746 :param clone_uri: set clone_uri
747 :param clone_uri: set clone_uri
747 :type clone_uri: str
748 :type clone_uri: str
748 :param push_uri: set push_uri
749 :param push_uri: set push_uri
749 :type push_uri: str
750 :type push_uri: str
750 :param landing_rev: <rev_type>:<rev>
751 :param landing_rev: <rev_type>:<rev>
751 :type landing_rev: str
752 :type landing_rev: str
752 :param enable_locking:
753 :param enable_locking:
753 :type enable_locking: bool
754 :type enable_locking: bool
754 :param enable_downloads:
755 :param enable_downloads:
755 :type enable_downloads: bool
756 :type enable_downloads: bool
756 :param enable_statistics:
757 :param enable_statistics:
757 :type enable_statistics: bool
758 :type enable_statistics: bool
758 :param copy_permissions: Copy permission from group in which the
759 :param copy_permissions: Copy permission from group in which the
759 repository is being created.
760 repository is being created.
760 :type copy_permissions: bool
761 :type copy_permissions: bool
761
762
762
763
763 Example output:
764 Example output:
764
765
765 .. code-block:: bash
766 .. code-block:: bash
766
767
767 id : <id_given_in_input>
768 id : <id_given_in_input>
768 result: {
769 result: {
769 "msg": "Created new repository `<reponame>`",
770 "msg": "Created new repository `<reponame>`",
770 "success": true,
771 "success": true,
771 "task": "<celery task id or None if done sync>"
772 "task": "<celery task id or None if done sync>"
772 }
773 }
773 error: null
774 error: null
774
775
775
776
776 Example error output:
777 Example error output:
777
778
778 .. code-block:: bash
779 .. code-block:: bash
779
780
780 id : <id_given_in_input>
781 id : <id_given_in_input>
781 result : null
782 result : null
782 error : {
783 error : {
783 'failed to create repository `<repo_name>`'
784 'failed to create repository `<repo_name>`'
784 }
785 }
785
786
786 """
787 """
787
788
788 owner = validate_set_owner_permissions(apiuser, owner)
789 owner = validate_set_owner_permissions(apiuser, owner)
789
790
790 description = Optional.extract(description)
791 description = Optional.extract(description)
791 copy_permissions = Optional.extract(copy_permissions)
792 copy_permissions = Optional.extract(copy_permissions)
792 clone_uri = Optional.extract(clone_uri)
793 clone_uri = Optional.extract(clone_uri)
793 push_uri = Optional.extract(push_uri)
794 push_uri = Optional.extract(push_uri)
794 landing_commit_ref = Optional.extract(landing_rev)
795 landing_commit_ref = Optional.extract(landing_rev)
795
796
796 defs = SettingsModel().get_default_repo_settings(strip_prefix=True)
797 defs = SettingsModel().get_default_repo_settings(strip_prefix=True)
797 if isinstance(private, Optional):
798 if isinstance(private, Optional):
798 private = defs.get('repo_private') or Optional.extract(private)
799 private = defs.get('repo_private') or Optional.extract(private)
799 if isinstance(repo_type, Optional):
800 if isinstance(repo_type, Optional):
800 repo_type = defs.get('repo_type')
801 repo_type = defs.get('repo_type')
801 if isinstance(enable_statistics, Optional):
802 if isinstance(enable_statistics, Optional):
802 enable_statistics = defs.get('repo_enable_statistics')
803 enable_statistics = defs.get('repo_enable_statistics')
803 if isinstance(enable_locking, Optional):
804 if isinstance(enable_locking, Optional):
804 enable_locking = defs.get('repo_enable_locking')
805 enable_locking = defs.get('repo_enable_locking')
805 if isinstance(enable_downloads, Optional):
806 if isinstance(enable_downloads, Optional):
806 enable_downloads = defs.get('repo_enable_downloads')
807 enable_downloads = defs.get('repo_enable_downloads')
807
808
808 schema = repo_schema.RepoSchema().bind(
809 schema = repo_schema.RepoSchema().bind(
809 repo_type_options=rhodecode.BACKENDS.keys(),
810 repo_type_options=rhodecode.BACKENDS.keys(),
810 repo_type=repo_type,
811 repo_type=repo_type,
811 # user caller
812 # user caller
812 user=apiuser)
813 user=apiuser)
813
814
814 try:
815 try:
815 schema_data = schema.deserialize(dict(
816 schema_data = schema.deserialize(dict(
816 repo_name=repo_name,
817 repo_name=repo_name,
817 repo_type=repo_type,
818 repo_type=repo_type,
818 repo_owner=owner.username,
819 repo_owner=owner.username,
819 repo_description=description,
820 repo_description=description,
820 repo_landing_commit_ref=landing_commit_ref,
821 repo_landing_commit_ref=landing_commit_ref,
821 repo_clone_uri=clone_uri,
822 repo_clone_uri=clone_uri,
822 repo_push_uri=push_uri,
823 repo_push_uri=push_uri,
823 repo_private=private,
824 repo_private=private,
824 repo_copy_permissions=copy_permissions,
825 repo_copy_permissions=copy_permissions,
825 repo_enable_statistics=enable_statistics,
826 repo_enable_statistics=enable_statistics,
826 repo_enable_downloads=enable_downloads,
827 repo_enable_downloads=enable_downloads,
827 repo_enable_locking=enable_locking))
828 repo_enable_locking=enable_locking))
828 except validation_schema.Invalid as err:
829 except validation_schema.Invalid as err:
829 raise JSONRPCValidationError(colander_exc=err)
830 raise JSONRPCValidationError(colander_exc=err)
830
831
831 try:
832 try:
832 data = {
833 data = {
833 'owner': owner,
834 'owner': owner,
834 'repo_name': schema_data['repo_group']['repo_name_without_group'],
835 'repo_name': schema_data['repo_group']['repo_name_without_group'],
835 'repo_name_full': schema_data['repo_name'],
836 'repo_name_full': schema_data['repo_name'],
836 'repo_group': schema_data['repo_group']['repo_group_id'],
837 'repo_group': schema_data['repo_group']['repo_group_id'],
837 'repo_type': schema_data['repo_type'],
838 'repo_type': schema_data['repo_type'],
838 'repo_description': schema_data['repo_description'],
839 'repo_description': schema_data['repo_description'],
839 'repo_private': schema_data['repo_private'],
840 'repo_private': schema_data['repo_private'],
840 'clone_uri': schema_data['repo_clone_uri'],
841 'clone_uri': schema_data['repo_clone_uri'],
841 'push_uri': schema_data['repo_push_uri'],
842 'push_uri': schema_data['repo_push_uri'],
842 'repo_landing_rev': schema_data['repo_landing_commit_ref'],
843 'repo_landing_rev': schema_data['repo_landing_commit_ref'],
843 'enable_statistics': schema_data['repo_enable_statistics'],
844 'enable_statistics': schema_data['repo_enable_statistics'],
844 'enable_locking': schema_data['repo_enable_locking'],
845 'enable_locking': schema_data['repo_enable_locking'],
845 'enable_downloads': schema_data['repo_enable_downloads'],
846 'enable_downloads': schema_data['repo_enable_downloads'],
846 'repo_copy_permissions': schema_data['repo_copy_permissions'],
847 'repo_copy_permissions': schema_data['repo_copy_permissions'],
847 }
848 }
848
849
849 task = RepoModel().create(form_data=data, cur_user=owner.user_id)
850 task = RepoModel().create(form_data=data, cur_user=owner.user_id)
850 task_id = get_task_id(task)
851 task_id = get_task_id(task)
851 # no commit, it's done in RepoModel, or async via celery
852 # no commit, it's done in RepoModel, or async via celery
852 return {
853 return {
853 'msg': "Created new repository `%s`" % (schema_data['repo_name'],),
854 'msg': "Created new repository `%s`" % (schema_data['repo_name'],),
854 'success': True, # cannot return the repo data here since fork
855 'success': True, # cannot return the repo data here since fork
855 # can be done async
856 # can be done async
856 'task': task_id
857 'task': task_id
857 }
858 }
858 except Exception:
859 except Exception:
859 log.exception(
860 log.exception(
860 u"Exception while trying to create the repository %s",
861 u"Exception while trying to create the repository %s",
861 schema_data['repo_name'])
862 schema_data['repo_name'])
862 raise JSONRPCError(
863 raise JSONRPCError(
863 'failed to create repository `%s`' % (schema_data['repo_name'],))
864 'failed to create repository `%s`' % (schema_data['repo_name'],))
864
865
865
866
866 @jsonrpc_method()
867 @jsonrpc_method()
867 def add_field_to_repo(request, apiuser, repoid, key, label=Optional(''),
868 def add_field_to_repo(request, apiuser, repoid, key, label=Optional(''),
868 description=Optional('')):
869 description=Optional('')):
869 """
870 """
870 Adds an extra field to a repository.
871 Adds an extra field to a repository.
871
872
872 This command can only be run using an |authtoken| with at least
873 This command can only be run using an |authtoken| with at least
873 write permissions to the |repo|.
874 write permissions to the |repo|.
874
875
875 :param apiuser: This is filled automatically from the |authtoken|.
876 :param apiuser: This is filled automatically from the |authtoken|.
876 :type apiuser: AuthUser
877 :type apiuser: AuthUser
877 :param repoid: Set the repository name or repository id.
878 :param repoid: Set the repository name or repository id.
878 :type repoid: str or int
879 :type repoid: str or int
879 :param key: Create a unique field key for this repository.
880 :param key: Create a unique field key for this repository.
880 :type key: str
881 :type key: str
881 :param label:
882 :param label:
882 :type label: Optional(str)
883 :type label: Optional(str)
883 :param description:
884 :param description:
884 :type description: Optional(str)
885 :type description: Optional(str)
885 """
886 """
886 repo = get_repo_or_error(repoid)
887 repo = get_repo_or_error(repoid)
887 if not has_superadmin_permission(apiuser):
888 if not has_superadmin_permission(apiuser):
888 _perms = ('repository.admin',)
889 _perms = ('repository.admin',)
889 validate_repo_permissions(apiuser, repoid, repo, _perms)
890 validate_repo_permissions(apiuser, repoid, repo, _perms)
890
891
891 label = Optional.extract(label) or key
892 label = Optional.extract(label) or key
892 description = Optional.extract(description)
893 description = Optional.extract(description)
893
894
894 field = RepositoryField.get_by_key_name(key, repo)
895 field = RepositoryField.get_by_key_name(key, repo)
895 if field:
896 if field:
896 raise JSONRPCError('Field with key '
897 raise JSONRPCError('Field with key '
897 '`%s` exists for repo `%s`' % (key, repoid))
898 '`%s` exists for repo `%s`' % (key, repoid))
898
899
899 try:
900 try:
900 RepoModel().add_repo_field(repo, key, field_label=label,
901 RepoModel().add_repo_field(repo, key, field_label=label,
901 field_desc=description)
902 field_desc=description)
902 Session().commit()
903 Session().commit()
903 return {
904 return {
904 'msg': "Added new repository field `%s`" % (key,),
905 'msg': "Added new repository field `%s`" % (key,),
905 'success': True,
906 'success': True,
906 }
907 }
907 except Exception:
908 except Exception:
908 log.exception("Exception occurred while trying to add field to repo")
909 log.exception("Exception occurred while trying to add field to repo")
909 raise JSONRPCError(
910 raise JSONRPCError(
910 'failed to create new field for repository `%s`' % (repoid,))
911 'failed to create new field for repository `%s`' % (repoid,))
911
912
912
913
913 @jsonrpc_method()
914 @jsonrpc_method()
914 def remove_field_from_repo(request, apiuser, repoid, key):
915 def remove_field_from_repo(request, apiuser, repoid, key):
915 """
916 """
916 Removes an extra field from a repository.
917 Removes an extra field from a repository.
917
918
918 This command can only be run using an |authtoken| with at least
919 This command can only be run using an |authtoken| with at least
919 write permissions to the |repo|.
920 write permissions to the |repo|.
920
921
921 :param apiuser: This is filled automatically from the |authtoken|.
922 :param apiuser: This is filled automatically from the |authtoken|.
922 :type apiuser: AuthUser
923 :type apiuser: AuthUser
923 :param repoid: Set the repository name or repository ID.
924 :param repoid: Set the repository name or repository ID.
924 :type repoid: str or int
925 :type repoid: str or int
925 :param key: Set the unique field key for this repository.
926 :param key: Set the unique field key for this repository.
926 :type key: str
927 :type key: str
927 """
928 """
928
929
929 repo = get_repo_or_error(repoid)
930 repo = get_repo_or_error(repoid)
930 if not has_superadmin_permission(apiuser):
931 if not has_superadmin_permission(apiuser):
931 _perms = ('repository.admin',)
932 _perms = ('repository.admin',)
932 validate_repo_permissions(apiuser, repoid, repo, _perms)
933 validate_repo_permissions(apiuser, repoid, repo, _perms)
933
934
934 field = RepositoryField.get_by_key_name(key, repo)
935 field = RepositoryField.get_by_key_name(key, repo)
935 if not field:
936 if not field:
936 raise JSONRPCError('Field with key `%s` does not '
937 raise JSONRPCError('Field with key `%s` does not '
937 'exists for repo `%s`' % (key, repoid))
938 'exists for repo `%s`' % (key, repoid))
938
939
939 try:
940 try:
940 RepoModel().delete_repo_field(repo, field_key=key)
941 RepoModel().delete_repo_field(repo, field_key=key)
941 Session().commit()
942 Session().commit()
942 return {
943 return {
943 'msg': "Deleted repository field `%s`" % (key,),
944 'msg': "Deleted repository field `%s`" % (key,),
944 'success': True,
945 'success': True,
945 }
946 }
946 except Exception:
947 except Exception:
947 log.exception(
948 log.exception(
948 "Exception occurred while trying to delete field from repo")
949 "Exception occurred while trying to delete field from repo")
949 raise JSONRPCError(
950 raise JSONRPCError(
950 'failed to delete field for repository `%s`' % (repoid,))
951 'failed to delete field for repository `%s`' % (repoid,))
951
952
952
953
953 @jsonrpc_method()
954 @jsonrpc_method()
954 def update_repo(
955 def update_repo(
955 request, apiuser, repoid, repo_name=Optional(None),
956 request, apiuser, repoid, repo_name=Optional(None),
956 owner=Optional(OAttr('apiuser')), description=Optional(''),
957 owner=Optional(OAttr('apiuser')), description=Optional(''),
957 private=Optional(False),
958 private=Optional(False),
958 clone_uri=Optional(None), push_uri=Optional(None),
959 clone_uri=Optional(None), push_uri=Optional(None),
959 landing_rev=Optional('rev:tip'), fork_of=Optional(None),
960 landing_rev=Optional('rev:tip'), fork_of=Optional(None),
960 enable_statistics=Optional(False),
961 enable_statistics=Optional(False),
961 enable_locking=Optional(False),
962 enable_locking=Optional(False),
962 enable_downloads=Optional(False), fields=Optional('')):
963 enable_downloads=Optional(False), fields=Optional('')):
963 """
964 """
964 Updates a repository with the given information.
965 Updates a repository with the given information.
965
966
966 This command can only be run using an |authtoken| with at least
967 This command can only be run using an |authtoken| with at least
967 admin permissions to the |repo|.
968 admin permissions to the |repo|.
968
969
969 * If the repository name contains "/", repository will be updated
970 * If the repository name contains "/", repository will be updated
970 accordingly with a repository group or nested repository groups
971 accordingly with a repository group or nested repository groups
971
972
972 For example repoid=repo-test name="foo/bar/repo-test" will update |repo|
973 For example repoid=repo-test name="foo/bar/repo-test" will update |repo|
973 called "repo-test" and place it inside group "foo/bar".
974 called "repo-test" and place it inside group "foo/bar".
974 You have to have permissions to access and write to the last repository
975 You have to have permissions to access and write to the last repository
975 group ("bar" in this example)
976 group ("bar" in this example)
976
977
977 :param apiuser: This is filled automatically from the |authtoken|.
978 :param apiuser: This is filled automatically from the |authtoken|.
978 :type apiuser: AuthUser
979 :type apiuser: AuthUser
979 :param repoid: repository name or repository ID.
980 :param repoid: repository name or repository ID.
980 :type repoid: str or int
981 :type repoid: str or int
981 :param repo_name: Update the |repo| name, including the
982 :param repo_name: Update the |repo| name, including the
982 repository group it's in.
983 repository group it's in.
983 :type repo_name: str
984 :type repo_name: str
984 :param owner: Set the |repo| owner.
985 :param owner: Set the |repo| owner.
985 :type owner: str
986 :type owner: str
986 :param fork_of: Set the |repo| as fork of another |repo|.
987 :param fork_of: Set the |repo| as fork of another |repo|.
987 :type fork_of: str
988 :type fork_of: str
988 :param description: Update the |repo| description.
989 :param description: Update the |repo| description.
989 :type description: str
990 :type description: str
990 :param private: Set the |repo| as private. (True | False)
991 :param private: Set the |repo| as private. (True | False)
991 :type private: bool
992 :type private: bool
992 :param clone_uri: Update the |repo| clone URI.
993 :param clone_uri: Update the |repo| clone URI.
993 :type clone_uri: str
994 :type clone_uri: str
994 :param landing_rev: Set the |repo| landing revision. Default is ``rev:tip``.
995 :param landing_rev: Set the |repo| landing revision. Default is ``rev:tip``.
995 :type landing_rev: str
996 :type landing_rev: str
996 :param enable_statistics: Enable statistics on the |repo|, (True | False).
997 :param enable_statistics: Enable statistics on the |repo|, (True | False).
997 :type enable_statistics: bool
998 :type enable_statistics: bool
998 :param enable_locking: Enable |repo| locking.
999 :param enable_locking: Enable |repo| locking.
999 :type enable_locking: bool
1000 :type enable_locking: bool
1000 :param enable_downloads: Enable downloads from the |repo|, (True | False).
1001 :param enable_downloads: Enable downloads from the |repo|, (True | False).
1001 :type enable_downloads: bool
1002 :type enable_downloads: bool
1002 :param fields: Add extra fields to the |repo|. Use the following
1003 :param fields: Add extra fields to the |repo|. Use the following
1003 example format: ``field_key=field_val,field_key2=fieldval2``.
1004 example format: ``field_key=field_val,field_key2=fieldval2``.
1004 Escape ', ' with \,
1005 Escape ', ' with \,
1005 :type fields: str
1006 :type fields: str
1006 """
1007 """
1007
1008
1008 repo = get_repo_or_error(repoid)
1009 repo = get_repo_or_error(repoid)
1009
1010
1010 include_secrets = False
1011 include_secrets = False
1011 if not has_superadmin_permission(apiuser):
1012 if not has_superadmin_permission(apiuser):
1012 validate_repo_permissions(apiuser, repoid, repo, ('repository.admin',))
1013 validate_repo_permissions(apiuser, repoid, repo, ('repository.admin',))
1013 else:
1014 else:
1014 include_secrets = True
1015 include_secrets = True
1015
1016
1016 updates = dict(
1017 updates = dict(
1017 repo_name=repo_name
1018 repo_name=repo_name
1018 if not isinstance(repo_name, Optional) else repo.repo_name,
1019 if not isinstance(repo_name, Optional) else repo.repo_name,
1019
1020
1020 fork_id=fork_of
1021 fork_id=fork_of
1021 if not isinstance(fork_of, Optional) else repo.fork.repo_name if repo.fork else None,
1022 if not isinstance(fork_of, Optional) else repo.fork.repo_name if repo.fork else None,
1022
1023
1023 user=owner
1024 user=owner
1024 if not isinstance(owner, Optional) else repo.user.username,
1025 if not isinstance(owner, Optional) else repo.user.username,
1025
1026
1026 repo_description=description
1027 repo_description=description
1027 if not isinstance(description, Optional) else repo.description,
1028 if not isinstance(description, Optional) else repo.description,
1028
1029
1029 repo_private=private
1030 repo_private=private
1030 if not isinstance(private, Optional) else repo.private,
1031 if not isinstance(private, Optional) else repo.private,
1031
1032
1032 clone_uri=clone_uri
1033 clone_uri=clone_uri
1033 if not isinstance(clone_uri, Optional) else repo.clone_uri,
1034 if not isinstance(clone_uri, Optional) else repo.clone_uri,
1034
1035
1035 push_uri=push_uri
1036 push_uri=push_uri
1036 if not isinstance(push_uri, Optional) else repo.push_uri,
1037 if not isinstance(push_uri, Optional) else repo.push_uri,
1037
1038
1038 repo_landing_rev=landing_rev
1039 repo_landing_rev=landing_rev
1039 if not isinstance(landing_rev, Optional) else repo._landing_revision,
1040 if not isinstance(landing_rev, Optional) else repo._landing_revision,
1040
1041
1041 repo_enable_statistics=enable_statistics
1042 repo_enable_statistics=enable_statistics
1042 if not isinstance(enable_statistics, Optional) else repo.enable_statistics,
1043 if not isinstance(enable_statistics, Optional) else repo.enable_statistics,
1043
1044
1044 repo_enable_locking=enable_locking
1045 repo_enable_locking=enable_locking
1045 if not isinstance(enable_locking, Optional) else repo.enable_locking,
1046 if not isinstance(enable_locking, Optional) else repo.enable_locking,
1046
1047
1047 repo_enable_downloads=enable_downloads
1048 repo_enable_downloads=enable_downloads
1048 if not isinstance(enable_downloads, Optional) else repo.enable_downloads)
1049 if not isinstance(enable_downloads, Optional) else repo.enable_downloads)
1049
1050
1050 ref_choices, _labels = ScmModel().get_repo_landing_revs(
1051 ref_choices, _labels = ScmModel().get_repo_landing_revs(
1051 request.translate, repo=repo)
1052 request.translate, repo=repo)
1052
1053
1053 old_values = repo.get_api_data()
1054 old_values = repo.get_api_data()
1054 repo_type = repo.repo_type
1055 repo_type = repo.repo_type
1055 schema = repo_schema.RepoSchema().bind(
1056 schema = repo_schema.RepoSchema().bind(
1056 repo_type_options=rhodecode.BACKENDS.keys(),
1057 repo_type_options=rhodecode.BACKENDS.keys(),
1057 repo_ref_options=ref_choices,
1058 repo_ref_options=ref_choices,
1058 repo_type=repo_type,
1059 repo_type=repo_type,
1059 # user caller
1060 # user caller
1060 user=apiuser,
1061 user=apiuser,
1061 old_values=old_values)
1062 old_values=old_values)
1062 try:
1063 try:
1063 schema_data = schema.deserialize(dict(
1064 schema_data = schema.deserialize(dict(
1064 # we save old value, users cannot change type
1065 # we save old value, users cannot change type
1065 repo_type=repo_type,
1066 repo_type=repo_type,
1066
1067
1067 repo_name=updates['repo_name'],
1068 repo_name=updates['repo_name'],
1068 repo_owner=updates['user'],
1069 repo_owner=updates['user'],
1069 repo_description=updates['repo_description'],
1070 repo_description=updates['repo_description'],
1070 repo_clone_uri=updates['clone_uri'],
1071 repo_clone_uri=updates['clone_uri'],
1071 repo_push_uri=updates['push_uri'],
1072 repo_push_uri=updates['push_uri'],
1072 repo_fork_of=updates['fork_id'],
1073 repo_fork_of=updates['fork_id'],
1073 repo_private=updates['repo_private'],
1074 repo_private=updates['repo_private'],
1074 repo_landing_commit_ref=updates['repo_landing_rev'],
1075 repo_landing_commit_ref=updates['repo_landing_rev'],
1075 repo_enable_statistics=updates['repo_enable_statistics'],
1076 repo_enable_statistics=updates['repo_enable_statistics'],
1076 repo_enable_downloads=updates['repo_enable_downloads'],
1077 repo_enable_downloads=updates['repo_enable_downloads'],
1077 repo_enable_locking=updates['repo_enable_locking']))
1078 repo_enable_locking=updates['repo_enable_locking']))
1078 except validation_schema.Invalid as err:
1079 except validation_schema.Invalid as err:
1079 raise JSONRPCValidationError(colander_exc=err)
1080 raise JSONRPCValidationError(colander_exc=err)
1080
1081
1081 # save validated data back into the updates dict
1082 # save validated data back into the updates dict
1082 validated_updates = dict(
1083 validated_updates = dict(
1083 repo_name=schema_data['repo_group']['repo_name_without_group'],
1084 repo_name=schema_data['repo_group']['repo_name_without_group'],
1084 repo_group=schema_data['repo_group']['repo_group_id'],
1085 repo_group=schema_data['repo_group']['repo_group_id'],
1085
1086
1086 user=schema_data['repo_owner'],
1087 user=schema_data['repo_owner'],
1087 repo_description=schema_data['repo_description'],
1088 repo_description=schema_data['repo_description'],
1088 repo_private=schema_data['repo_private'],
1089 repo_private=schema_data['repo_private'],
1089 clone_uri=schema_data['repo_clone_uri'],
1090 clone_uri=schema_data['repo_clone_uri'],
1090 push_uri=schema_data['repo_push_uri'],
1091 push_uri=schema_data['repo_push_uri'],
1091 repo_landing_rev=schema_data['repo_landing_commit_ref'],
1092 repo_landing_rev=schema_data['repo_landing_commit_ref'],
1092 repo_enable_statistics=schema_data['repo_enable_statistics'],
1093 repo_enable_statistics=schema_data['repo_enable_statistics'],
1093 repo_enable_locking=schema_data['repo_enable_locking'],
1094 repo_enable_locking=schema_data['repo_enable_locking'],
1094 repo_enable_downloads=schema_data['repo_enable_downloads'],
1095 repo_enable_downloads=schema_data['repo_enable_downloads'],
1095 )
1096 )
1096
1097
1097 if schema_data['repo_fork_of']:
1098 if schema_data['repo_fork_of']:
1098 fork_repo = get_repo_or_error(schema_data['repo_fork_of'])
1099 fork_repo = get_repo_or_error(schema_data['repo_fork_of'])
1099 validated_updates['fork_id'] = fork_repo.repo_id
1100 validated_updates['fork_id'] = fork_repo.repo_id
1100
1101
1101 # extra fields
1102 # extra fields
1102 fields = parse_args(Optional.extract(fields), key_prefix='ex_')
1103 fields = parse_args(Optional.extract(fields), key_prefix='ex_')
1103 if fields:
1104 if fields:
1104 validated_updates.update(fields)
1105 validated_updates.update(fields)
1105
1106
1106 try:
1107 try:
1107 RepoModel().update(repo, **validated_updates)
1108 RepoModel().update(repo, **validated_updates)
1108 audit_logger.store_api(
1109 audit_logger.store_api(
1109 'repo.edit', action_data={'old_data': old_values},
1110 'repo.edit', action_data={'old_data': old_values},
1110 user=apiuser, repo=repo)
1111 user=apiuser, repo=repo)
1111 Session().commit()
1112 Session().commit()
1112 return {
1113 return {
1113 'msg': 'updated repo ID:%s %s' % (repo.repo_id, repo.repo_name),
1114 'msg': 'updated repo ID:%s %s' % (repo.repo_id, repo.repo_name),
1114 'repository': repo.get_api_data(include_secrets=include_secrets)
1115 'repository': repo.get_api_data(include_secrets=include_secrets)
1115 }
1116 }
1116 except Exception:
1117 except Exception:
1117 log.exception(
1118 log.exception(
1118 u"Exception while trying to update the repository %s",
1119 u"Exception while trying to update the repository %s",
1119 repoid)
1120 repoid)
1120 raise JSONRPCError('failed to update repo `%s`' % repoid)
1121 raise JSONRPCError('failed to update repo `%s`' % repoid)
1121
1122
1122
1123
1123 @jsonrpc_method()
1124 @jsonrpc_method()
1124 def fork_repo(request, apiuser, repoid, fork_name,
1125 def fork_repo(request, apiuser, repoid, fork_name,
1125 owner=Optional(OAttr('apiuser')),
1126 owner=Optional(OAttr('apiuser')),
1126 description=Optional(''),
1127 description=Optional(''),
1127 private=Optional(False),
1128 private=Optional(False),
1128 clone_uri=Optional(None),
1129 clone_uri=Optional(None),
1129 landing_rev=Optional('rev:tip'),
1130 landing_rev=Optional('rev:tip'),
1130 copy_permissions=Optional(False)):
1131 copy_permissions=Optional(False)):
1131 """
1132 """
1132 Creates a fork of the specified |repo|.
1133 Creates a fork of the specified |repo|.
1133
1134
1134 * If the fork_name contains "/", fork will be created inside
1135 * If the fork_name contains "/", fork will be created inside
1135 a repository group or nested repository groups
1136 a repository group or nested repository groups
1136
1137
1137 For example "foo/bar/fork-repo" will create fork called "fork-repo"
1138 For example "foo/bar/fork-repo" will create fork called "fork-repo"
1138 inside group "foo/bar". You have to have permissions to access and
1139 inside group "foo/bar". You have to have permissions to access and
1139 write to the last repository group ("bar" in this example)
1140 write to the last repository group ("bar" in this example)
1140
1141
1141 This command can only be run using an |authtoken| with minimum
1142 This command can only be run using an |authtoken| with minimum
1142 read permissions of the forked repo, create fork permissions for an user.
1143 read permissions of the forked repo, create fork permissions for an user.
1143
1144
1144 :param apiuser: This is filled automatically from the |authtoken|.
1145 :param apiuser: This is filled automatically from the |authtoken|.
1145 :type apiuser: AuthUser
1146 :type apiuser: AuthUser
1146 :param repoid: Set repository name or repository ID.
1147 :param repoid: Set repository name or repository ID.
1147 :type repoid: str or int
1148 :type repoid: str or int
1148 :param fork_name: Set the fork name, including it's repository group membership.
1149 :param fork_name: Set the fork name, including it's repository group membership.
1149 :type fork_name: str
1150 :type fork_name: str
1150 :param owner: Set the fork owner.
1151 :param owner: Set the fork owner.
1151 :type owner: str
1152 :type owner: str
1152 :param description: Set the fork description.
1153 :param description: Set the fork description.
1153 :type description: str
1154 :type description: str
1154 :param copy_permissions: Copy permissions from parent |repo|. The
1155 :param copy_permissions: Copy permissions from parent |repo|. The
1155 default is False.
1156 default is False.
1156 :type copy_permissions: bool
1157 :type copy_permissions: bool
1157 :param private: Make the fork private. The default is False.
1158 :param private: Make the fork private. The default is False.
1158 :type private: bool
1159 :type private: bool
1159 :param landing_rev: Set the landing revision. The default is tip.
1160 :param landing_rev: Set the landing revision. The default is tip.
1160
1161
1161 Example output:
1162 Example output:
1162
1163
1163 .. code-block:: bash
1164 .. code-block:: bash
1164
1165
1165 id : <id_for_response>
1166 id : <id_for_response>
1166 api_key : "<api_key>"
1167 api_key : "<api_key>"
1167 args: {
1168 args: {
1168 "repoid" : "<reponame or repo_id>",
1169 "repoid" : "<reponame or repo_id>",
1169 "fork_name": "<forkname>",
1170 "fork_name": "<forkname>",
1170 "owner": "<username or user_id = Optional(=apiuser)>",
1171 "owner": "<username or user_id = Optional(=apiuser)>",
1171 "description": "<description>",
1172 "description": "<description>",
1172 "copy_permissions": "<bool>",
1173 "copy_permissions": "<bool>",
1173 "private": "<bool>",
1174 "private": "<bool>",
1174 "landing_rev": "<landing_rev>"
1175 "landing_rev": "<landing_rev>"
1175 }
1176 }
1176
1177
1177 Example error output:
1178 Example error output:
1178
1179
1179 .. code-block:: bash
1180 .. code-block:: bash
1180
1181
1181 id : <id_given_in_input>
1182 id : <id_given_in_input>
1182 result: {
1183 result: {
1183 "msg": "Created fork of `<reponame>` as `<forkname>`",
1184 "msg": "Created fork of `<reponame>` as `<forkname>`",
1184 "success": true,
1185 "success": true,
1185 "task": "<celery task id or None if done sync>"
1186 "task": "<celery task id or None if done sync>"
1186 }
1187 }
1187 error: null
1188 error: null
1188
1189
1189 """
1190 """
1190
1191
1191 repo = get_repo_or_error(repoid)
1192 repo = get_repo_or_error(repoid)
1192 repo_name = repo.repo_name
1193 repo_name = repo.repo_name
1193
1194
1194 if not has_superadmin_permission(apiuser):
1195 if not has_superadmin_permission(apiuser):
1195 # check if we have at least read permission for
1196 # check if we have at least read permission for
1196 # this repo that we fork !
1197 # this repo that we fork !
1197 _perms = (
1198 _perms = (
1198 'repository.admin', 'repository.write', 'repository.read')
1199 'repository.admin', 'repository.write', 'repository.read')
1199 validate_repo_permissions(apiuser, repoid, repo, _perms)
1200 validate_repo_permissions(apiuser, repoid, repo, _perms)
1200
1201
1201 # check if the regular user has at least fork permissions as well
1202 # check if the regular user has at least fork permissions as well
1202 if not HasPermissionAnyApi('hg.fork.repository')(user=apiuser):
1203 if not HasPermissionAnyApi('hg.fork.repository')(user=apiuser):
1203 raise JSONRPCForbidden()
1204 raise JSONRPCForbidden()
1204
1205
1205 # check if user can set owner parameter
1206 # check if user can set owner parameter
1206 owner = validate_set_owner_permissions(apiuser, owner)
1207 owner = validate_set_owner_permissions(apiuser, owner)
1207
1208
1208 description = Optional.extract(description)
1209 description = Optional.extract(description)
1209 copy_permissions = Optional.extract(copy_permissions)
1210 copy_permissions = Optional.extract(copy_permissions)
1210 clone_uri = Optional.extract(clone_uri)
1211 clone_uri = Optional.extract(clone_uri)
1211 landing_commit_ref = Optional.extract(landing_rev)
1212 landing_commit_ref = Optional.extract(landing_rev)
1212 private = Optional.extract(private)
1213 private = Optional.extract(private)
1213
1214
1214 schema = repo_schema.RepoSchema().bind(
1215 schema = repo_schema.RepoSchema().bind(
1215 repo_type_options=rhodecode.BACKENDS.keys(),
1216 repo_type_options=rhodecode.BACKENDS.keys(),
1216 repo_type=repo.repo_type,
1217 repo_type=repo.repo_type,
1217 # user caller
1218 # user caller
1218 user=apiuser)
1219 user=apiuser)
1219
1220
1220 try:
1221 try:
1221 schema_data = schema.deserialize(dict(
1222 schema_data = schema.deserialize(dict(
1222 repo_name=fork_name,
1223 repo_name=fork_name,
1223 repo_type=repo.repo_type,
1224 repo_type=repo.repo_type,
1224 repo_owner=owner.username,
1225 repo_owner=owner.username,
1225 repo_description=description,
1226 repo_description=description,
1226 repo_landing_commit_ref=landing_commit_ref,
1227 repo_landing_commit_ref=landing_commit_ref,
1227 repo_clone_uri=clone_uri,
1228 repo_clone_uri=clone_uri,
1228 repo_private=private,
1229 repo_private=private,
1229 repo_copy_permissions=copy_permissions))
1230 repo_copy_permissions=copy_permissions))
1230 except validation_schema.Invalid as err:
1231 except validation_schema.Invalid as err:
1231 raise JSONRPCValidationError(colander_exc=err)
1232 raise JSONRPCValidationError(colander_exc=err)
1232
1233
1233 try:
1234 try:
1234 data = {
1235 data = {
1235 'fork_parent_id': repo.repo_id,
1236 'fork_parent_id': repo.repo_id,
1236
1237
1237 'repo_name': schema_data['repo_group']['repo_name_without_group'],
1238 'repo_name': schema_data['repo_group']['repo_name_without_group'],
1238 'repo_name_full': schema_data['repo_name'],
1239 'repo_name_full': schema_data['repo_name'],
1239 'repo_group': schema_data['repo_group']['repo_group_id'],
1240 'repo_group': schema_data['repo_group']['repo_group_id'],
1240 'repo_type': schema_data['repo_type'],
1241 'repo_type': schema_data['repo_type'],
1241 'description': schema_data['repo_description'],
1242 'description': schema_data['repo_description'],
1242 'private': schema_data['repo_private'],
1243 'private': schema_data['repo_private'],
1243 'copy_permissions': schema_data['repo_copy_permissions'],
1244 'copy_permissions': schema_data['repo_copy_permissions'],
1244 'landing_rev': schema_data['repo_landing_commit_ref'],
1245 'landing_rev': schema_data['repo_landing_commit_ref'],
1245 }
1246 }
1246
1247
1247 task = RepoModel().create_fork(data, cur_user=owner.user_id)
1248 task = RepoModel().create_fork(data, cur_user=owner.user_id)
1248 # no commit, it's done in RepoModel, or async via celery
1249 # no commit, it's done in RepoModel, or async via celery
1249 task_id = get_task_id(task)
1250 task_id = get_task_id(task)
1250
1251
1251 return {
1252 return {
1252 'msg': 'Created fork of `%s` as `%s`' % (
1253 'msg': 'Created fork of `%s` as `%s`' % (
1253 repo.repo_name, schema_data['repo_name']),
1254 repo.repo_name, schema_data['repo_name']),
1254 'success': True, # cannot return the repo data here since fork
1255 'success': True, # cannot return the repo data here since fork
1255 # can be done async
1256 # can be done async
1256 'task': task_id
1257 'task': task_id
1257 }
1258 }
1258 except Exception:
1259 except Exception:
1259 log.exception(
1260 log.exception(
1260 u"Exception while trying to create fork %s",
1261 u"Exception while trying to create fork %s",
1261 schema_data['repo_name'])
1262 schema_data['repo_name'])
1262 raise JSONRPCError(
1263 raise JSONRPCError(
1263 'failed to fork repository `%s` as `%s`' % (
1264 'failed to fork repository `%s` as `%s`' % (
1264 repo_name, schema_data['repo_name']))
1265 repo_name, schema_data['repo_name']))
1265
1266
1266
1267
1267 @jsonrpc_method()
1268 @jsonrpc_method()
1268 def delete_repo(request, apiuser, repoid, forks=Optional('')):
1269 def delete_repo(request, apiuser, repoid, forks=Optional('')):
1269 """
1270 """
1270 Deletes a repository.
1271 Deletes a repository.
1271
1272
1272 * When the `forks` parameter is set it's possible to detach or delete
1273 * When the `forks` parameter is set it's possible to detach or delete
1273 forks of deleted repository.
1274 forks of deleted repository.
1274
1275
1275 This command can only be run using an |authtoken| with admin
1276 This command can only be run using an |authtoken| with admin
1276 permissions on the |repo|.
1277 permissions on the |repo|.
1277
1278
1278 :param apiuser: This is filled automatically from the |authtoken|.
1279 :param apiuser: This is filled automatically from the |authtoken|.
1279 :type apiuser: AuthUser
1280 :type apiuser: AuthUser
1280 :param repoid: Set the repository name or repository ID.
1281 :param repoid: Set the repository name or repository ID.
1281 :type repoid: str or int
1282 :type repoid: str or int
1282 :param forks: Set to `detach` or `delete` forks from the |repo|.
1283 :param forks: Set to `detach` or `delete` forks from the |repo|.
1283 :type forks: Optional(str)
1284 :type forks: Optional(str)
1284
1285
1285 Example error output:
1286 Example error output:
1286
1287
1287 .. code-block:: bash
1288 .. code-block:: bash
1288
1289
1289 id : <id_given_in_input>
1290 id : <id_given_in_input>
1290 result: {
1291 result: {
1291 "msg": "Deleted repository `<reponame>`",
1292 "msg": "Deleted repository `<reponame>`",
1292 "success": true
1293 "success": true
1293 }
1294 }
1294 error: null
1295 error: null
1295 """
1296 """
1296
1297
1297 repo = get_repo_or_error(repoid)
1298 repo = get_repo_or_error(repoid)
1298 repo_name = repo.repo_name
1299 repo_name = repo.repo_name
1299 if not has_superadmin_permission(apiuser):
1300 if not has_superadmin_permission(apiuser):
1300 _perms = ('repository.admin',)
1301 _perms = ('repository.admin',)
1301 validate_repo_permissions(apiuser, repoid, repo, _perms)
1302 validate_repo_permissions(apiuser, repoid, repo, _perms)
1302
1303
1303 try:
1304 try:
1304 handle_forks = Optional.extract(forks)
1305 handle_forks = Optional.extract(forks)
1305 _forks_msg = ''
1306 _forks_msg = ''
1306 _forks = [f for f in repo.forks]
1307 _forks = [f for f in repo.forks]
1307 if handle_forks == 'detach':
1308 if handle_forks == 'detach':
1308 _forks_msg = ' ' + 'Detached %s forks' % len(_forks)
1309 _forks_msg = ' ' + 'Detached %s forks' % len(_forks)
1309 elif handle_forks == 'delete':
1310 elif handle_forks == 'delete':
1310 _forks_msg = ' ' + 'Deleted %s forks' % len(_forks)
1311 _forks_msg = ' ' + 'Deleted %s forks' % len(_forks)
1311 elif _forks:
1312 elif _forks:
1312 raise JSONRPCError(
1313 raise JSONRPCError(
1313 'Cannot delete `%s` it still contains attached forks' %
1314 'Cannot delete `%s` it still contains attached forks' %
1314 (repo.repo_name,)
1315 (repo.repo_name,)
1315 )
1316 )
1316 old_data = repo.get_api_data()
1317 old_data = repo.get_api_data()
1317 RepoModel().delete(repo, forks=forks)
1318 RepoModel().delete(repo, forks=forks)
1318
1319
1319 repo = audit_logger.RepoWrap(repo_id=None,
1320 repo = audit_logger.RepoWrap(repo_id=None,
1320 repo_name=repo.repo_name)
1321 repo_name=repo.repo_name)
1321
1322
1322 audit_logger.store_api(
1323 audit_logger.store_api(
1323 'repo.delete', action_data={'old_data': old_data},
1324 'repo.delete', action_data={'old_data': old_data},
1324 user=apiuser, repo=repo)
1325 user=apiuser, repo=repo)
1325
1326
1326 ScmModel().mark_for_invalidation(repo_name, delete=True)
1327 ScmModel().mark_for_invalidation(repo_name, delete=True)
1327 Session().commit()
1328 Session().commit()
1328 return {
1329 return {
1329 'msg': 'Deleted repository `%s`%s' % (repo_name, _forks_msg),
1330 'msg': 'Deleted repository `%s`%s' % (repo_name, _forks_msg),
1330 'success': True
1331 'success': True
1331 }
1332 }
1332 except Exception:
1333 except Exception:
1333 log.exception("Exception occurred while trying to delete repo")
1334 log.exception("Exception occurred while trying to delete repo")
1334 raise JSONRPCError(
1335 raise JSONRPCError(
1335 'failed to delete repository `%s`' % (repo_name,)
1336 'failed to delete repository `%s`' % (repo_name,)
1336 )
1337 )
1337
1338
1338
1339
1339 #TODO: marcink, change name ?
1340 #TODO: marcink, change name ?
1340 @jsonrpc_method()
1341 @jsonrpc_method()
1341 def invalidate_cache(request, apiuser, repoid, delete_keys=Optional(False)):
1342 def invalidate_cache(request, apiuser, repoid, delete_keys=Optional(False)):
1342 """
1343 """
1343 Invalidates the cache for the specified repository.
1344 Invalidates the cache for the specified repository.
1344
1345
1345 This command can only be run using an |authtoken| with admin rights to
1346 This command can only be run using an |authtoken| with admin rights to
1346 the specified repository.
1347 the specified repository.
1347
1348
1348 This command takes the following options:
1349 This command takes the following options:
1349
1350
1350 :param apiuser: This is filled automatically from |authtoken|.
1351 :param apiuser: This is filled automatically from |authtoken|.
1351 :type apiuser: AuthUser
1352 :type apiuser: AuthUser
1352 :param repoid: Sets the repository name or repository ID.
1353 :param repoid: Sets the repository name or repository ID.
1353 :type repoid: str or int
1354 :type repoid: str or int
1354 :param delete_keys: This deletes the invalidated keys instead of
1355 :param delete_keys: This deletes the invalidated keys instead of
1355 just flagging them.
1356 just flagging them.
1356 :type delete_keys: Optional(``True`` | ``False``)
1357 :type delete_keys: Optional(``True`` | ``False``)
1357
1358
1358 Example output:
1359 Example output:
1359
1360
1360 .. code-block:: bash
1361 .. code-block:: bash
1361
1362
1362 id : <id_given_in_input>
1363 id : <id_given_in_input>
1363 result : {
1364 result : {
1364 'msg': Cache for repository `<repository name>` was invalidated,
1365 'msg': Cache for repository `<repository name>` was invalidated,
1365 'repository': <repository name>
1366 'repository': <repository name>
1366 }
1367 }
1367 error : null
1368 error : null
1368
1369
1369 Example error output:
1370 Example error output:
1370
1371
1371 .. code-block:: bash
1372 .. code-block:: bash
1372
1373
1373 id : <id_given_in_input>
1374 id : <id_given_in_input>
1374 result : null
1375 result : null
1375 error : {
1376 error : {
1376 'Error occurred during cache invalidation action'
1377 'Error occurred during cache invalidation action'
1377 }
1378 }
1378
1379
1379 """
1380 """
1380
1381
1381 repo = get_repo_or_error(repoid)
1382 repo = get_repo_or_error(repoid)
1382 if not has_superadmin_permission(apiuser):
1383 if not has_superadmin_permission(apiuser):
1383 _perms = ('repository.admin', 'repository.write',)
1384 _perms = ('repository.admin', 'repository.write',)
1384 validate_repo_permissions(apiuser, repoid, repo, _perms)
1385 validate_repo_permissions(apiuser, repoid, repo, _perms)
1385
1386
1386 delete = Optional.extract(delete_keys)
1387 delete = Optional.extract(delete_keys)
1387 try:
1388 try:
1388 ScmModel().mark_for_invalidation(repo.repo_name, delete=delete)
1389 ScmModel().mark_for_invalidation(repo.repo_name, delete=delete)
1389 return {
1390 return {
1390 'msg': 'Cache for repository `%s` was invalidated' % (repoid,),
1391 'msg': 'Cache for repository `%s` was invalidated' % (repoid,),
1391 'repository': repo.repo_name
1392 'repository': repo.repo_name
1392 }
1393 }
1393 except Exception:
1394 except Exception:
1394 log.exception(
1395 log.exception(
1395 "Exception occurred while trying to invalidate repo cache")
1396 "Exception occurred while trying to invalidate repo cache")
1396 raise JSONRPCError(
1397 raise JSONRPCError(
1397 'Error occurred during cache invalidation action'
1398 'Error occurred during cache invalidation action'
1398 )
1399 )
1399
1400
1400
1401
1401 #TODO: marcink, change name ?
1402 #TODO: marcink, change name ?
1402 @jsonrpc_method()
1403 @jsonrpc_method()
1403 def lock(request, apiuser, repoid, locked=Optional(None),
1404 def lock(request, apiuser, repoid, locked=Optional(None),
1404 userid=Optional(OAttr('apiuser'))):
1405 userid=Optional(OAttr('apiuser'))):
1405 """
1406 """
1406 Sets the lock state of the specified |repo| by the given user.
1407 Sets the lock state of the specified |repo| by the given user.
1407 From more information, see :ref:`repo-locking`.
1408 From more information, see :ref:`repo-locking`.
1408
1409
1409 * If the ``userid`` option is not set, the repository is locked to the
1410 * If the ``userid`` option is not set, the repository is locked to the
1410 user who called the method.
1411 user who called the method.
1411 * If the ``locked`` parameter is not set, the current lock state of the
1412 * If the ``locked`` parameter is not set, the current lock state of the
1412 repository is displayed.
1413 repository is displayed.
1413
1414
1414 This command can only be run using an |authtoken| with admin rights to
1415 This command can only be run using an |authtoken| with admin rights to
1415 the specified repository.
1416 the specified repository.
1416
1417
1417 This command takes the following options:
1418 This command takes the following options:
1418
1419
1419 :param apiuser: This is filled automatically from the |authtoken|.
1420 :param apiuser: This is filled automatically from the |authtoken|.
1420 :type apiuser: AuthUser
1421 :type apiuser: AuthUser
1421 :param repoid: Sets the repository name or repository ID.
1422 :param repoid: Sets the repository name or repository ID.
1422 :type repoid: str or int
1423 :type repoid: str or int
1423 :param locked: Sets the lock state.
1424 :param locked: Sets the lock state.
1424 :type locked: Optional(``True`` | ``False``)
1425 :type locked: Optional(``True`` | ``False``)
1425 :param userid: Set the repository lock to this user.
1426 :param userid: Set the repository lock to this user.
1426 :type userid: Optional(str or int)
1427 :type userid: Optional(str or int)
1427
1428
1428 Example error output:
1429 Example error output:
1429
1430
1430 .. code-block:: bash
1431 .. code-block:: bash
1431
1432
1432 id : <id_given_in_input>
1433 id : <id_given_in_input>
1433 result : {
1434 result : {
1434 'repo': '<reponame>',
1435 'repo': '<reponame>',
1435 'locked': <bool: lock state>,
1436 'locked': <bool: lock state>,
1436 'locked_since': <int: lock timestamp>,
1437 'locked_since': <int: lock timestamp>,
1437 'locked_by': <username of person who made the lock>,
1438 'locked_by': <username of person who made the lock>,
1438 'lock_reason': <str: reason for locking>,
1439 'lock_reason': <str: reason for locking>,
1439 'lock_state_changed': <bool: True if lock state has been changed in this request>,
1440 'lock_state_changed': <bool: True if lock state has been changed in this request>,
1440 'msg': 'Repo `<reponame>` locked by `<username>` on <timestamp>.'
1441 'msg': 'Repo `<reponame>` locked by `<username>` on <timestamp>.'
1441 or
1442 or
1442 'msg': 'Repo `<repository name>` not locked.'
1443 'msg': 'Repo `<repository name>` not locked.'
1443 or
1444 or
1444 'msg': 'User `<user name>` set lock state for repo `<repository name>` to `<new lock state>`'
1445 'msg': 'User `<user name>` set lock state for repo `<repository name>` to `<new lock state>`'
1445 }
1446 }
1446 error : null
1447 error : null
1447
1448
1448 Example error output:
1449 Example error output:
1449
1450
1450 .. code-block:: bash
1451 .. code-block:: bash
1451
1452
1452 id : <id_given_in_input>
1453 id : <id_given_in_input>
1453 result : null
1454 result : null
1454 error : {
1455 error : {
1455 'Error occurred locking repository `<reponame>`'
1456 'Error occurred locking repository `<reponame>`'
1456 }
1457 }
1457 """
1458 """
1458
1459
1459 repo = get_repo_or_error(repoid)
1460 repo = get_repo_or_error(repoid)
1460 if not has_superadmin_permission(apiuser):
1461 if not has_superadmin_permission(apiuser):
1461 # check if we have at least write permission for this repo !
1462 # check if we have at least write permission for this repo !
1462 _perms = ('repository.admin', 'repository.write',)
1463 _perms = ('repository.admin', 'repository.write',)
1463 validate_repo_permissions(apiuser, repoid, repo, _perms)
1464 validate_repo_permissions(apiuser, repoid, repo, _perms)
1464
1465
1465 # make sure normal user does not pass someone else userid,
1466 # make sure normal user does not pass someone else userid,
1466 # he is not allowed to do that
1467 # he is not allowed to do that
1467 if not isinstance(userid, Optional) and userid != apiuser.user_id:
1468 if not isinstance(userid, Optional) and userid != apiuser.user_id:
1468 raise JSONRPCError('userid is not the same as your user')
1469 raise JSONRPCError('userid is not the same as your user')
1469
1470
1470 if isinstance(userid, Optional):
1471 if isinstance(userid, Optional):
1471 userid = apiuser.user_id
1472 userid = apiuser.user_id
1472
1473
1473 user = get_user_or_error(userid)
1474 user = get_user_or_error(userid)
1474
1475
1475 if isinstance(locked, Optional):
1476 if isinstance(locked, Optional):
1476 lockobj = repo.locked
1477 lockobj = repo.locked
1477
1478
1478 if lockobj[0] is None:
1479 if lockobj[0] is None:
1479 _d = {
1480 _d = {
1480 'repo': repo.repo_name,
1481 'repo': repo.repo_name,
1481 'locked': False,
1482 'locked': False,
1482 'locked_since': None,
1483 'locked_since': None,
1483 'locked_by': None,
1484 'locked_by': None,
1484 'lock_reason': None,
1485 'lock_reason': None,
1485 'lock_state_changed': False,
1486 'lock_state_changed': False,
1486 'msg': 'Repo `%s` not locked.' % repo.repo_name
1487 'msg': 'Repo `%s` not locked.' % repo.repo_name
1487 }
1488 }
1488 return _d
1489 return _d
1489 else:
1490 else:
1490 _user_id, _time, _reason = lockobj
1491 _user_id, _time, _reason = lockobj
1491 lock_user = get_user_or_error(userid)
1492 lock_user = get_user_or_error(userid)
1492 _d = {
1493 _d = {
1493 'repo': repo.repo_name,
1494 'repo': repo.repo_name,
1494 'locked': True,
1495 'locked': True,
1495 'locked_since': _time,
1496 'locked_since': _time,
1496 'locked_by': lock_user.username,
1497 'locked_by': lock_user.username,
1497 'lock_reason': _reason,
1498 'lock_reason': _reason,
1498 'lock_state_changed': False,
1499 'lock_state_changed': False,
1499 'msg': ('Repo `%s` locked by `%s` on `%s`.'
1500 'msg': ('Repo `%s` locked by `%s` on `%s`.'
1500 % (repo.repo_name, lock_user.username,
1501 % (repo.repo_name, lock_user.username,
1501 json.dumps(time_to_datetime(_time))))
1502 json.dumps(time_to_datetime(_time))))
1502 }
1503 }
1503 return _d
1504 return _d
1504
1505
1505 # force locked state through a flag
1506 # force locked state through a flag
1506 else:
1507 else:
1507 locked = str2bool(locked)
1508 locked = str2bool(locked)
1508 lock_reason = Repository.LOCK_API
1509 lock_reason = Repository.LOCK_API
1509 try:
1510 try:
1510 if locked:
1511 if locked:
1511 lock_time = time.time()
1512 lock_time = time.time()
1512 Repository.lock(repo, user.user_id, lock_time, lock_reason)
1513 Repository.lock(repo, user.user_id, lock_time, lock_reason)
1513 else:
1514 else:
1514 lock_time = None
1515 lock_time = None
1515 Repository.unlock(repo)
1516 Repository.unlock(repo)
1516 _d = {
1517 _d = {
1517 'repo': repo.repo_name,
1518 'repo': repo.repo_name,
1518 'locked': locked,
1519 'locked': locked,
1519 'locked_since': lock_time,
1520 'locked_since': lock_time,
1520 'locked_by': user.username,
1521 'locked_by': user.username,
1521 'lock_reason': lock_reason,
1522 'lock_reason': lock_reason,
1522 'lock_state_changed': True,
1523 'lock_state_changed': True,
1523 'msg': ('User `%s` set lock state for repo `%s` to `%s`'
1524 'msg': ('User `%s` set lock state for repo `%s` to `%s`'
1524 % (user.username, repo.repo_name, locked))
1525 % (user.username, repo.repo_name, locked))
1525 }
1526 }
1526 return _d
1527 return _d
1527 except Exception:
1528 except Exception:
1528 log.exception(
1529 log.exception(
1529 "Exception occurred while trying to lock repository")
1530 "Exception occurred while trying to lock repository")
1530 raise JSONRPCError(
1531 raise JSONRPCError(
1531 'Error occurred locking repository `%s`' % repo.repo_name
1532 'Error occurred locking repository `%s`' % repo.repo_name
1532 )
1533 )
1533
1534
1534
1535
1535 @jsonrpc_method()
1536 @jsonrpc_method()
1536 def comment_commit(
1537 def comment_commit(
1537 request, apiuser, repoid, commit_id, message, status=Optional(None),
1538 request, apiuser, repoid, commit_id, message, status=Optional(None),
1538 comment_type=Optional(ChangesetComment.COMMENT_TYPE_NOTE),
1539 comment_type=Optional(ChangesetComment.COMMENT_TYPE_NOTE),
1539 resolves_comment_id=Optional(None),
1540 resolves_comment_id=Optional(None),
1540 userid=Optional(OAttr('apiuser'))):
1541 userid=Optional(OAttr('apiuser'))):
1541 """
1542 """
1542 Set a commit comment, and optionally change the status of the commit.
1543 Set a commit comment, and optionally change the status of the commit.
1543
1544
1544 :param apiuser: This is filled automatically from the |authtoken|.
1545 :param apiuser: This is filled automatically from the |authtoken|.
1545 :type apiuser: AuthUser
1546 :type apiuser: AuthUser
1546 :param repoid: Set the repository name or repository ID.
1547 :param repoid: Set the repository name or repository ID.
1547 :type repoid: str or int
1548 :type repoid: str or int
1548 :param commit_id: Specify the commit_id for which to set a comment.
1549 :param commit_id: Specify the commit_id for which to set a comment.
1549 :type commit_id: str
1550 :type commit_id: str
1550 :param message: The comment text.
1551 :param message: The comment text.
1551 :type message: str
1552 :type message: str
1552 :param status: (**Optional**) status of commit, one of: 'not_reviewed',
1553 :param status: (**Optional**) status of commit, one of: 'not_reviewed',
1553 'approved', 'rejected', 'under_review'
1554 'approved', 'rejected', 'under_review'
1554 :type status: str
1555 :type status: str
1555 :param comment_type: Comment type, one of: 'note', 'todo'
1556 :param comment_type: Comment type, one of: 'note', 'todo'
1556 :type comment_type: Optional(str), default: 'note'
1557 :type comment_type: Optional(str), default: 'note'
1557 :param userid: Set the user name of the comment creator.
1558 :param userid: Set the user name of the comment creator.
1558 :type userid: Optional(str or int)
1559 :type userid: Optional(str or int)
1559
1560
1560 Example error output:
1561 Example error output:
1561
1562
1562 .. code-block:: bash
1563 .. code-block:: bash
1563
1564
1564 {
1565 {
1565 "id" : <id_given_in_input>,
1566 "id" : <id_given_in_input>,
1566 "result" : {
1567 "result" : {
1567 "msg": "Commented on commit `<commit_id>` for repository `<repoid>`",
1568 "msg": "Commented on commit `<commit_id>` for repository `<repoid>`",
1568 "status_change": null or <status>,
1569 "status_change": null or <status>,
1569 "success": true
1570 "success": true
1570 },
1571 },
1571 "error" : null
1572 "error" : null
1572 }
1573 }
1573
1574
1574 """
1575 """
1575 repo = get_repo_or_error(repoid)
1576 repo = get_repo_or_error(repoid)
1576 if not has_superadmin_permission(apiuser):
1577 if not has_superadmin_permission(apiuser):
1577 _perms = ('repository.read', 'repository.write', 'repository.admin')
1578 _perms = ('repository.read', 'repository.write', 'repository.admin')
1578 validate_repo_permissions(apiuser, repoid, repo, _perms)
1579 validate_repo_permissions(apiuser, repoid, repo, _perms)
1579
1580
1580 try:
1581 try:
1581 commit_id = repo.scm_instance().get_commit(commit_id=commit_id).raw_id
1582 commit_id = repo.scm_instance().get_commit(commit_id=commit_id).raw_id
1582 except Exception as e:
1583 except Exception as e:
1583 log.exception('Failed to fetch commit')
1584 log.exception('Failed to fetch commit')
1584 raise JSONRPCError(safe_str(e))
1585 raise JSONRPCError(safe_str(e))
1585
1586
1586 if isinstance(userid, Optional):
1587 if isinstance(userid, Optional):
1587 userid = apiuser.user_id
1588 userid = apiuser.user_id
1588
1589
1589 user = get_user_or_error(userid)
1590 user = get_user_or_error(userid)
1590 status = Optional.extract(status)
1591 status = Optional.extract(status)
1591 comment_type = Optional.extract(comment_type)
1592 comment_type = Optional.extract(comment_type)
1592 resolves_comment_id = Optional.extract(resolves_comment_id)
1593 resolves_comment_id = Optional.extract(resolves_comment_id)
1593
1594
1594 allowed_statuses = [x[0] for x in ChangesetStatus.STATUSES]
1595 allowed_statuses = [x[0] for x in ChangesetStatus.STATUSES]
1595 if status and status not in allowed_statuses:
1596 if status and status not in allowed_statuses:
1596 raise JSONRPCError('Bad status, must be on '
1597 raise JSONRPCError('Bad status, must be on '
1597 'of %s got %s' % (allowed_statuses, status,))
1598 'of %s got %s' % (allowed_statuses, status,))
1598
1599
1599 if resolves_comment_id:
1600 if resolves_comment_id:
1600 comment = ChangesetComment.get(resolves_comment_id)
1601 comment = ChangesetComment.get(resolves_comment_id)
1601 if not comment:
1602 if not comment:
1602 raise JSONRPCError(
1603 raise JSONRPCError(
1603 'Invalid resolves_comment_id `%s` for this commit.'
1604 'Invalid resolves_comment_id `%s` for this commit.'
1604 % resolves_comment_id)
1605 % resolves_comment_id)
1605 if comment.comment_type != ChangesetComment.COMMENT_TYPE_TODO:
1606 if comment.comment_type != ChangesetComment.COMMENT_TYPE_TODO:
1606 raise JSONRPCError(
1607 raise JSONRPCError(
1607 'Comment `%s` is wrong type for setting status to resolved.'
1608 'Comment `%s` is wrong type for setting status to resolved.'
1608 % resolves_comment_id)
1609 % resolves_comment_id)
1609
1610
1610 try:
1611 try:
1611 rc_config = SettingsModel().get_all_settings()
1612 rc_config = SettingsModel().get_all_settings()
1612 renderer = rc_config.get('rhodecode_markup_renderer', 'rst')
1613 renderer = rc_config.get('rhodecode_markup_renderer', 'rst')
1613 status_change_label = ChangesetStatus.get_status_lbl(status)
1614 status_change_label = ChangesetStatus.get_status_lbl(status)
1614 comment = CommentsModel().create(
1615 comment = CommentsModel().create(
1615 message, repo, user, commit_id=commit_id,
1616 message, repo, user, commit_id=commit_id,
1616 status_change=status_change_label,
1617 status_change=status_change_label,
1617 status_change_type=status,
1618 status_change_type=status,
1618 renderer=renderer,
1619 renderer=renderer,
1619 comment_type=comment_type,
1620 comment_type=comment_type,
1620 resolves_comment_id=resolves_comment_id,
1621 resolves_comment_id=resolves_comment_id,
1621 auth_user=apiuser
1622 auth_user=apiuser
1622 )
1623 )
1623 if status:
1624 if status:
1624 # also do a status change
1625 # also do a status change
1625 try:
1626 try:
1626 ChangesetStatusModel().set_status(
1627 ChangesetStatusModel().set_status(
1627 repo, status, user, comment, revision=commit_id,
1628 repo, status, user, comment, revision=commit_id,
1628 dont_allow_on_closed_pull_request=True
1629 dont_allow_on_closed_pull_request=True
1629 )
1630 )
1630 except StatusChangeOnClosedPullRequestError:
1631 except StatusChangeOnClosedPullRequestError:
1631 log.exception(
1632 log.exception(
1632 "Exception occurred while trying to change repo commit status")
1633 "Exception occurred while trying to change repo commit status")
1633 msg = ('Changing status on a changeset associated with '
1634 msg = ('Changing status on a changeset associated with '
1634 'a closed pull request is not allowed')
1635 'a closed pull request is not allowed')
1635 raise JSONRPCError(msg)
1636 raise JSONRPCError(msg)
1636
1637
1637 Session().commit()
1638 Session().commit()
1638 return {
1639 return {
1639 'msg': (
1640 'msg': (
1640 'Commented on commit `%s` for repository `%s`' % (
1641 'Commented on commit `%s` for repository `%s`' % (
1641 comment.revision, repo.repo_name)),
1642 comment.revision, repo.repo_name)),
1642 'status_change': status,
1643 'status_change': status,
1643 'success': True,
1644 'success': True,
1644 }
1645 }
1645 except JSONRPCError:
1646 except JSONRPCError:
1646 # catch any inside errors, and re-raise them to prevent from
1647 # catch any inside errors, and re-raise them to prevent from
1647 # below global catch to silence them
1648 # below global catch to silence them
1648 raise
1649 raise
1649 except Exception:
1650 except Exception:
1650 log.exception("Exception occurred while trying to comment on commit")
1651 log.exception("Exception occurred while trying to comment on commit")
1651 raise JSONRPCError(
1652 raise JSONRPCError(
1652 'failed to set comment on repository `%s`' % (repo.repo_name,)
1653 'failed to set comment on repository `%s`' % (repo.repo_name,)
1653 )
1654 )
1654
1655
1655
1656
1656 @jsonrpc_method()
1657 @jsonrpc_method()
1657 def get_repo_comments(request, apiuser, repoid,
1658 def get_repo_comments(request, apiuser, repoid,
1658 commit_id=Optional(None), comment_type=Optional(None),
1659 commit_id=Optional(None), comment_type=Optional(None),
1659 userid=Optional(None)):
1660 userid=Optional(None)):
1660 """
1661 """
1661 Get all comments for a repository
1662 Get all comments for a repository
1662
1663
1663 :param apiuser: This is filled automatically from the |authtoken|.
1664 :param apiuser: This is filled automatically from the |authtoken|.
1664 :type apiuser: AuthUser
1665 :type apiuser: AuthUser
1665 :param repoid: Set the repository name or repository ID.
1666 :param repoid: Set the repository name or repository ID.
1666 :type repoid: str or int
1667 :type repoid: str or int
1667 :param commit_id: Optionally filter the comments by the commit_id
1668 :param commit_id: Optionally filter the comments by the commit_id
1668 :type commit_id: Optional(str), default: None
1669 :type commit_id: Optional(str), default: None
1669 :param comment_type: Optionally filter the comments by the comment_type
1670 :param comment_type: Optionally filter the comments by the comment_type
1670 one of: 'note', 'todo'
1671 one of: 'note', 'todo'
1671 :type comment_type: Optional(str), default: None
1672 :type comment_type: Optional(str), default: None
1672 :param userid: Optionally filter the comments by the author of comment
1673 :param userid: Optionally filter the comments by the author of comment
1673 :type userid: Optional(str or int), Default: None
1674 :type userid: Optional(str or int), Default: None
1674
1675
1675 Example error output:
1676 Example error output:
1676
1677
1677 .. code-block:: bash
1678 .. code-block:: bash
1678
1679
1679 {
1680 {
1680 "id" : <id_given_in_input>,
1681 "id" : <id_given_in_input>,
1681 "result" : [
1682 "result" : [
1682 {
1683 {
1683 "comment_author": <USER_DETAILS>,
1684 "comment_author": <USER_DETAILS>,
1684 "comment_created_on": "2017-02-01T14:38:16.309",
1685 "comment_created_on": "2017-02-01T14:38:16.309",
1685 "comment_f_path": "file.txt",
1686 "comment_f_path": "file.txt",
1686 "comment_id": 282,
1687 "comment_id": 282,
1687 "comment_lineno": "n1",
1688 "comment_lineno": "n1",
1688 "comment_resolved_by": null,
1689 "comment_resolved_by": null,
1689 "comment_status": [],
1690 "comment_status": [],
1690 "comment_text": "This file needs a header",
1691 "comment_text": "This file needs a header",
1691 "comment_type": "todo"
1692 "comment_type": "todo"
1692 }
1693 }
1693 ],
1694 ],
1694 "error" : null
1695 "error" : null
1695 }
1696 }
1696
1697
1697 """
1698 """
1698 repo = get_repo_or_error(repoid)
1699 repo = get_repo_or_error(repoid)
1699 if not has_superadmin_permission(apiuser):
1700 if not has_superadmin_permission(apiuser):
1700 _perms = ('repository.read', 'repository.write', 'repository.admin')
1701 _perms = ('repository.read', 'repository.write', 'repository.admin')
1701 validate_repo_permissions(apiuser, repoid, repo, _perms)
1702 validate_repo_permissions(apiuser, repoid, repo, _perms)
1702
1703
1703 commit_id = Optional.extract(commit_id)
1704 commit_id = Optional.extract(commit_id)
1704
1705
1705 userid = Optional.extract(userid)
1706 userid = Optional.extract(userid)
1706 if userid:
1707 if userid:
1707 user = get_user_or_error(userid)
1708 user = get_user_or_error(userid)
1708 else:
1709 else:
1709 user = None
1710 user = None
1710
1711
1711 comment_type = Optional.extract(comment_type)
1712 comment_type = Optional.extract(comment_type)
1712 if comment_type and comment_type not in ChangesetComment.COMMENT_TYPES:
1713 if comment_type and comment_type not in ChangesetComment.COMMENT_TYPES:
1713 raise JSONRPCError(
1714 raise JSONRPCError(
1714 'comment_type must be one of `{}` got {}'.format(
1715 'comment_type must be one of `{}` got {}'.format(
1715 ChangesetComment.COMMENT_TYPES, comment_type)
1716 ChangesetComment.COMMENT_TYPES, comment_type)
1716 )
1717 )
1717
1718
1718 comments = CommentsModel().get_repository_comments(
1719 comments = CommentsModel().get_repository_comments(
1719 repo=repo, comment_type=comment_type, user=user, commit_id=commit_id)
1720 repo=repo, comment_type=comment_type, user=user, commit_id=commit_id)
1720 return comments
1721 return comments
1721
1722
1722
1723
1723 @jsonrpc_method()
1724 @jsonrpc_method()
1724 def grant_user_permission(request, apiuser, repoid, userid, perm):
1725 def grant_user_permission(request, apiuser, repoid, userid, perm):
1725 """
1726 """
1726 Grant permissions for the specified user on the given repository,
1727 Grant permissions for the specified user on the given repository,
1727 or update existing permissions if found.
1728 or update existing permissions if found.
1728
1729
1729 This command can only be run using an |authtoken| with admin
1730 This command can only be run using an |authtoken| with admin
1730 permissions on the |repo|.
1731 permissions on the |repo|.
1731
1732
1732 :param apiuser: This is filled automatically from the |authtoken|.
1733 :param apiuser: This is filled automatically from the |authtoken|.
1733 :type apiuser: AuthUser
1734 :type apiuser: AuthUser
1734 :param repoid: Set the repository name or repository ID.
1735 :param repoid: Set the repository name or repository ID.
1735 :type repoid: str or int
1736 :type repoid: str or int
1736 :param userid: Set the user name.
1737 :param userid: Set the user name.
1737 :type userid: str
1738 :type userid: str
1738 :param perm: Set the user permissions, using the following format
1739 :param perm: Set the user permissions, using the following format
1739 ``(repository.(none|read|write|admin))``
1740 ``(repository.(none|read|write|admin))``
1740 :type perm: str
1741 :type perm: str
1741
1742
1742 Example output:
1743 Example output:
1743
1744
1744 .. code-block:: bash
1745 .. code-block:: bash
1745
1746
1746 id : <id_given_in_input>
1747 id : <id_given_in_input>
1747 result: {
1748 result: {
1748 "msg" : "Granted perm: `<perm>` for user: `<username>` in repo: `<reponame>`",
1749 "msg" : "Granted perm: `<perm>` for user: `<username>` in repo: `<reponame>`",
1749 "success": true
1750 "success": true
1750 }
1751 }
1751 error: null
1752 error: null
1752 """
1753 """
1753
1754
1754 repo = get_repo_or_error(repoid)
1755 repo = get_repo_or_error(repoid)
1755 user = get_user_or_error(userid)
1756 user = get_user_or_error(userid)
1756 perm = get_perm_or_error(perm)
1757 perm = get_perm_or_error(perm)
1757 if not has_superadmin_permission(apiuser):
1758 if not has_superadmin_permission(apiuser):
1758 _perms = ('repository.admin',)
1759 _perms = ('repository.admin',)
1759 validate_repo_permissions(apiuser, repoid, repo, _perms)
1760 validate_repo_permissions(apiuser, repoid, repo, _perms)
1760
1761
1761 perm_additions = [[user.user_id, perm.permission_name, "user"]]
1762 perm_additions = [[user.user_id, perm.permission_name, "user"]]
1762 try:
1763 try:
1763 changes = RepoModel().update_permissions(
1764 changes = RepoModel().update_permissions(
1764 repo=repo, perm_additions=perm_additions, cur_user=apiuser)
1765 repo=repo, perm_additions=perm_additions, cur_user=apiuser)
1765
1766
1766 action_data = {
1767 action_data = {
1767 'added': changes['added'],
1768 'added': changes['added'],
1768 'updated': changes['updated'],
1769 'updated': changes['updated'],
1769 'deleted': changes['deleted'],
1770 'deleted': changes['deleted'],
1770 }
1771 }
1771 audit_logger.store_api(
1772 audit_logger.store_api(
1772 'repo.edit.permissions', action_data=action_data, user=apiuser, repo=repo)
1773 'repo.edit.permissions', action_data=action_data, user=apiuser, repo=repo)
1773
1774
1774 Session().commit()
1775 Session().commit()
1775 return {
1776 return {
1776 'msg': 'Granted perm: `%s` for user: `%s` in repo: `%s`' % (
1777 'msg': 'Granted perm: `%s` for user: `%s` in repo: `%s`' % (
1777 perm.permission_name, user.username, repo.repo_name
1778 perm.permission_name, user.username, repo.repo_name
1778 ),
1779 ),
1779 'success': True
1780 'success': True
1780 }
1781 }
1781 except Exception:
1782 except Exception:
1782 log.exception("Exception occurred while trying edit permissions for repo")
1783 log.exception("Exception occurred while trying edit permissions for repo")
1783 raise JSONRPCError(
1784 raise JSONRPCError(
1784 'failed to edit permission for user: `%s` in repo: `%s`' % (
1785 'failed to edit permission for user: `%s` in repo: `%s`' % (
1785 userid, repoid
1786 userid, repoid
1786 )
1787 )
1787 )
1788 )
1788
1789
1789
1790
1790 @jsonrpc_method()
1791 @jsonrpc_method()
1791 def revoke_user_permission(request, apiuser, repoid, userid):
1792 def revoke_user_permission(request, apiuser, repoid, userid):
1792 """
1793 """
1793 Revoke permission for a user on the specified repository.
1794 Revoke permission for a user on the specified repository.
1794
1795
1795 This command can only be run using an |authtoken| with admin
1796 This command can only be run using an |authtoken| with admin
1796 permissions on the |repo|.
1797 permissions on the |repo|.
1797
1798
1798 :param apiuser: This is filled automatically from the |authtoken|.
1799 :param apiuser: This is filled automatically from the |authtoken|.
1799 :type apiuser: AuthUser
1800 :type apiuser: AuthUser
1800 :param repoid: Set the repository name or repository ID.
1801 :param repoid: Set the repository name or repository ID.
1801 :type repoid: str or int
1802 :type repoid: str or int
1802 :param userid: Set the user name of revoked user.
1803 :param userid: Set the user name of revoked user.
1803 :type userid: str or int
1804 :type userid: str or int
1804
1805
1805 Example error output:
1806 Example error output:
1806
1807
1807 .. code-block:: bash
1808 .. code-block:: bash
1808
1809
1809 id : <id_given_in_input>
1810 id : <id_given_in_input>
1810 result: {
1811 result: {
1811 "msg" : "Revoked perm for user: `<username>` in repo: `<reponame>`",
1812 "msg" : "Revoked perm for user: `<username>` in repo: `<reponame>`",
1812 "success": true
1813 "success": true
1813 }
1814 }
1814 error: null
1815 error: null
1815 """
1816 """
1816
1817
1817 repo = get_repo_or_error(repoid)
1818 repo = get_repo_or_error(repoid)
1818 user = get_user_or_error(userid)
1819 user = get_user_or_error(userid)
1819 if not has_superadmin_permission(apiuser):
1820 if not has_superadmin_permission(apiuser):
1820 _perms = ('repository.admin',)
1821 _perms = ('repository.admin',)
1821 validate_repo_permissions(apiuser, repoid, repo, _perms)
1822 validate_repo_permissions(apiuser, repoid, repo, _perms)
1822
1823
1823 perm_deletions = [[user.user_id, None, "user"]]
1824 perm_deletions = [[user.user_id, None, "user"]]
1824 try:
1825 try:
1825 changes = RepoModel().update_permissions(
1826 changes = RepoModel().update_permissions(
1826 repo=repo, perm_deletions=perm_deletions, cur_user=user)
1827 repo=repo, perm_deletions=perm_deletions, cur_user=user)
1827
1828
1828 action_data = {
1829 action_data = {
1829 'added': changes['added'],
1830 'added': changes['added'],
1830 'updated': changes['updated'],
1831 'updated': changes['updated'],
1831 'deleted': changes['deleted'],
1832 'deleted': changes['deleted'],
1832 }
1833 }
1833 audit_logger.store_api(
1834 audit_logger.store_api(
1834 'repo.edit.permissions', action_data=action_data, user=apiuser, repo=repo)
1835 'repo.edit.permissions', action_data=action_data, user=apiuser, repo=repo)
1835
1836
1836 Session().commit()
1837 Session().commit()
1837 return {
1838 return {
1838 'msg': 'Revoked perm for user: `%s` in repo: `%s`' % (
1839 'msg': 'Revoked perm for user: `%s` in repo: `%s`' % (
1839 user.username, repo.repo_name
1840 user.username, repo.repo_name
1840 ),
1841 ),
1841 'success': True
1842 'success': True
1842 }
1843 }
1843 except Exception:
1844 except Exception:
1844 log.exception("Exception occurred while trying revoke permissions to repo")
1845 log.exception("Exception occurred while trying revoke permissions to repo")
1845 raise JSONRPCError(
1846 raise JSONRPCError(
1846 'failed to edit permission for user: `%s` in repo: `%s`' % (
1847 'failed to edit permission for user: `%s` in repo: `%s`' % (
1847 userid, repoid
1848 userid, repoid
1848 )
1849 )
1849 )
1850 )
1850
1851
1851
1852
1852 @jsonrpc_method()
1853 @jsonrpc_method()
1853 def grant_user_group_permission(request, apiuser, repoid, usergroupid, perm):
1854 def grant_user_group_permission(request, apiuser, repoid, usergroupid, perm):
1854 """
1855 """
1855 Grant permission for a user group on the specified repository,
1856 Grant permission for a user group on the specified repository,
1856 or update existing permissions.
1857 or update existing permissions.
1857
1858
1858 This command can only be run using an |authtoken| with admin
1859 This command can only be run using an |authtoken| with admin
1859 permissions on the |repo|.
1860 permissions on the |repo|.
1860
1861
1861 :param apiuser: This is filled automatically from the |authtoken|.
1862 :param apiuser: This is filled automatically from the |authtoken|.
1862 :type apiuser: AuthUser
1863 :type apiuser: AuthUser
1863 :param repoid: Set the repository name or repository ID.
1864 :param repoid: Set the repository name or repository ID.
1864 :type repoid: str or int
1865 :type repoid: str or int
1865 :param usergroupid: Specify the ID of the user group.
1866 :param usergroupid: Specify the ID of the user group.
1866 :type usergroupid: str or int
1867 :type usergroupid: str or int
1867 :param perm: Set the user group permissions using the following
1868 :param perm: Set the user group permissions using the following
1868 format: (repository.(none|read|write|admin))
1869 format: (repository.(none|read|write|admin))
1869 :type perm: str
1870 :type perm: str
1870
1871
1871 Example output:
1872 Example output:
1872
1873
1873 .. code-block:: bash
1874 .. code-block:: bash
1874
1875
1875 id : <id_given_in_input>
1876 id : <id_given_in_input>
1876 result : {
1877 result : {
1877 "msg" : "Granted perm: `<perm>` for group: `<usersgroupname>` in repo: `<reponame>`",
1878 "msg" : "Granted perm: `<perm>` for group: `<usersgroupname>` in repo: `<reponame>`",
1878 "success": true
1879 "success": true
1879
1880
1880 }
1881 }
1881 error : null
1882 error : null
1882
1883
1883 Example error output:
1884 Example error output:
1884
1885
1885 .. code-block:: bash
1886 .. code-block:: bash
1886
1887
1887 id : <id_given_in_input>
1888 id : <id_given_in_input>
1888 result : null
1889 result : null
1889 error : {
1890 error : {
1890 "failed to edit permission for user group: `<usergroup>` in repo `<repo>`'
1891 "failed to edit permission for user group: `<usergroup>` in repo `<repo>`'
1891 }
1892 }
1892
1893
1893 """
1894 """
1894
1895
1895 repo = get_repo_or_error(repoid)
1896 repo = get_repo_or_error(repoid)
1896 perm = get_perm_or_error(perm)
1897 perm = get_perm_or_error(perm)
1897 if not has_superadmin_permission(apiuser):
1898 if not has_superadmin_permission(apiuser):
1898 _perms = ('repository.admin',)
1899 _perms = ('repository.admin',)
1899 validate_repo_permissions(apiuser, repoid, repo, _perms)
1900 validate_repo_permissions(apiuser, repoid, repo, _perms)
1900
1901
1901 user_group = get_user_group_or_error(usergroupid)
1902 user_group = get_user_group_or_error(usergroupid)
1902 if not has_superadmin_permission(apiuser):
1903 if not has_superadmin_permission(apiuser):
1903 # check if we have at least read permission for this user group !
1904 # check if we have at least read permission for this user group !
1904 _perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin',)
1905 _perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin',)
1905 if not HasUserGroupPermissionAnyApi(*_perms)(
1906 if not HasUserGroupPermissionAnyApi(*_perms)(
1906 user=apiuser, user_group_name=user_group.users_group_name):
1907 user=apiuser, user_group_name=user_group.users_group_name):
1907 raise JSONRPCError(
1908 raise JSONRPCError(
1908 'user group `%s` does not exist' % (usergroupid,))
1909 'user group `%s` does not exist' % (usergroupid,))
1909
1910
1910 perm_additions = [[user_group.users_group_id, perm.permission_name, "user_group"]]
1911 perm_additions = [[user_group.users_group_id, perm.permission_name, "user_group"]]
1911 try:
1912 try:
1912 changes = RepoModel().update_permissions(
1913 changes = RepoModel().update_permissions(
1913 repo=repo, perm_additions=perm_additions, cur_user=apiuser)
1914 repo=repo, perm_additions=perm_additions, cur_user=apiuser)
1914 action_data = {
1915 action_data = {
1915 'added': changes['added'],
1916 'added': changes['added'],
1916 'updated': changes['updated'],
1917 'updated': changes['updated'],
1917 'deleted': changes['deleted'],
1918 'deleted': changes['deleted'],
1918 }
1919 }
1919 audit_logger.store_api(
1920 audit_logger.store_api(
1920 'repo.edit.permissions', action_data=action_data, user=apiuser, repo=repo)
1921 'repo.edit.permissions', action_data=action_data, user=apiuser, repo=repo)
1921
1922
1922 Session().commit()
1923 Session().commit()
1923 return {
1924 return {
1924 'msg': 'Granted perm: `%s` for user group: `%s` in '
1925 'msg': 'Granted perm: `%s` for user group: `%s` in '
1925 'repo: `%s`' % (
1926 'repo: `%s`' % (
1926 perm.permission_name, user_group.users_group_name,
1927 perm.permission_name, user_group.users_group_name,
1927 repo.repo_name
1928 repo.repo_name
1928 ),
1929 ),
1929 'success': True
1930 'success': True
1930 }
1931 }
1931 except Exception:
1932 except Exception:
1932 log.exception(
1933 log.exception(
1933 "Exception occurred while trying change permission on repo")
1934 "Exception occurred while trying change permission on repo")
1934 raise JSONRPCError(
1935 raise JSONRPCError(
1935 'failed to edit permission for user group: `%s` in '
1936 'failed to edit permission for user group: `%s` in '
1936 'repo: `%s`' % (
1937 'repo: `%s`' % (
1937 usergroupid, repo.repo_name
1938 usergroupid, repo.repo_name
1938 )
1939 )
1939 )
1940 )
1940
1941
1941
1942
1942 @jsonrpc_method()
1943 @jsonrpc_method()
1943 def revoke_user_group_permission(request, apiuser, repoid, usergroupid):
1944 def revoke_user_group_permission(request, apiuser, repoid, usergroupid):
1944 """
1945 """
1945 Revoke the permissions of a user group on a given repository.
1946 Revoke the permissions of a user group on a given repository.
1946
1947
1947 This command can only be run using an |authtoken| with admin
1948 This command can only be run using an |authtoken| with admin
1948 permissions on the |repo|.
1949 permissions on the |repo|.
1949
1950
1950 :param apiuser: This is filled automatically from the |authtoken|.
1951 :param apiuser: This is filled automatically from the |authtoken|.
1951 :type apiuser: AuthUser
1952 :type apiuser: AuthUser
1952 :param repoid: Set the repository name or repository ID.
1953 :param repoid: Set the repository name or repository ID.
1953 :type repoid: str or int
1954 :type repoid: str or int
1954 :param usergroupid: Specify the user group ID.
1955 :param usergroupid: Specify the user group ID.
1955 :type usergroupid: str or int
1956 :type usergroupid: str or int
1956
1957
1957 Example output:
1958 Example output:
1958
1959
1959 .. code-block:: bash
1960 .. code-block:: bash
1960
1961
1961 id : <id_given_in_input>
1962 id : <id_given_in_input>
1962 result: {
1963 result: {
1963 "msg" : "Revoked perm for group: `<usersgroupname>` in repo: `<reponame>`",
1964 "msg" : "Revoked perm for group: `<usersgroupname>` in repo: `<reponame>`",
1964 "success": true
1965 "success": true
1965 }
1966 }
1966 error: null
1967 error: null
1967 """
1968 """
1968
1969
1969 repo = get_repo_or_error(repoid)
1970 repo = get_repo_or_error(repoid)
1970 if not has_superadmin_permission(apiuser):
1971 if not has_superadmin_permission(apiuser):
1971 _perms = ('repository.admin',)
1972 _perms = ('repository.admin',)
1972 validate_repo_permissions(apiuser, repoid, repo, _perms)
1973 validate_repo_permissions(apiuser, repoid, repo, _perms)
1973
1974
1974 user_group = get_user_group_or_error(usergroupid)
1975 user_group = get_user_group_or_error(usergroupid)
1975 if not has_superadmin_permission(apiuser):
1976 if not has_superadmin_permission(apiuser):
1976 # check if we have at least read permission for this user group !
1977 # check if we have at least read permission for this user group !
1977 _perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin',)
1978 _perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin',)
1978 if not HasUserGroupPermissionAnyApi(*_perms)(
1979 if not HasUserGroupPermissionAnyApi(*_perms)(
1979 user=apiuser, user_group_name=user_group.users_group_name):
1980 user=apiuser, user_group_name=user_group.users_group_name):
1980 raise JSONRPCError(
1981 raise JSONRPCError(
1981 'user group `%s` does not exist' % (usergroupid,))
1982 'user group `%s` does not exist' % (usergroupid,))
1982
1983
1983 perm_deletions = [[user_group.users_group_id, None, "user_group"]]
1984 perm_deletions = [[user_group.users_group_id, None, "user_group"]]
1984 try:
1985 try:
1985 changes = RepoModel().update_permissions(
1986 changes = RepoModel().update_permissions(
1986 repo=repo, perm_deletions=perm_deletions, cur_user=apiuser)
1987 repo=repo, perm_deletions=perm_deletions, cur_user=apiuser)
1987 action_data = {
1988 action_data = {
1988 'added': changes['added'],
1989 'added': changes['added'],
1989 'updated': changes['updated'],
1990 'updated': changes['updated'],
1990 'deleted': changes['deleted'],
1991 'deleted': changes['deleted'],
1991 }
1992 }
1992 audit_logger.store_api(
1993 audit_logger.store_api(
1993 'repo.edit.permissions', action_data=action_data, user=apiuser, repo=repo)
1994 'repo.edit.permissions', action_data=action_data, user=apiuser, repo=repo)
1994
1995
1995 Session().commit()
1996 Session().commit()
1996 return {
1997 return {
1997 'msg': 'Revoked perm for user group: `%s` in repo: `%s`' % (
1998 'msg': 'Revoked perm for user group: `%s` in repo: `%s`' % (
1998 user_group.users_group_name, repo.repo_name
1999 user_group.users_group_name, repo.repo_name
1999 ),
2000 ),
2000 'success': True
2001 'success': True
2001 }
2002 }
2002 except Exception:
2003 except Exception:
2003 log.exception("Exception occurred while trying revoke "
2004 log.exception("Exception occurred while trying revoke "
2004 "user group permission on repo")
2005 "user group permission on repo")
2005 raise JSONRPCError(
2006 raise JSONRPCError(
2006 'failed to edit permission for user group: `%s` in '
2007 'failed to edit permission for user group: `%s` in '
2007 'repo: `%s`' % (
2008 'repo: `%s`' % (
2008 user_group.users_group_name, repo.repo_name
2009 user_group.users_group_name, repo.repo_name
2009 )
2010 )
2010 )
2011 )
2011
2012
2012
2013
2013 @jsonrpc_method()
2014 @jsonrpc_method()
2014 def pull(request, apiuser, repoid, remote_uri=Optional(None)):
2015 def pull(request, apiuser, repoid, remote_uri=Optional(None)):
2015 """
2016 """
2016 Triggers a pull on the given repository from a remote location. You
2017 Triggers a pull on the given repository from a remote location. You
2017 can use this to keep remote repositories up-to-date.
2018 can use this to keep remote repositories up-to-date.
2018
2019
2019 This command can only be run using an |authtoken| with admin
2020 This command can only be run using an |authtoken| with admin
2020 rights to the specified repository. For more information,
2021 rights to the specified repository. For more information,
2021 see :ref:`config-token-ref`.
2022 see :ref:`config-token-ref`.
2022
2023
2023 This command takes the following options:
2024 This command takes the following options:
2024
2025
2025 :param apiuser: This is filled automatically from the |authtoken|.
2026 :param apiuser: This is filled automatically from the |authtoken|.
2026 :type apiuser: AuthUser
2027 :type apiuser: AuthUser
2027 :param repoid: The repository name or repository ID.
2028 :param repoid: The repository name or repository ID.
2028 :type repoid: str or int
2029 :type repoid: str or int
2029 :param remote_uri: Optional remote URI to pass in for pull
2030 :param remote_uri: Optional remote URI to pass in for pull
2030 :type remote_uri: str
2031 :type remote_uri: str
2031
2032
2032 Example output:
2033 Example output:
2033
2034
2034 .. code-block:: bash
2035 .. code-block:: bash
2035
2036
2036 id : <id_given_in_input>
2037 id : <id_given_in_input>
2037 result : {
2038 result : {
2038 "msg": "Pulled from url `<remote_url>` on repo `<repository name>`"
2039 "msg": "Pulled from url `<remote_url>` on repo `<repository name>`"
2039 "repository": "<repository name>"
2040 "repository": "<repository name>"
2040 }
2041 }
2041 error : null
2042 error : null
2042
2043
2043 Example error output:
2044 Example error output:
2044
2045
2045 .. code-block:: bash
2046 .. code-block:: bash
2046
2047
2047 id : <id_given_in_input>
2048 id : <id_given_in_input>
2048 result : null
2049 result : null
2049 error : {
2050 error : {
2050 "Unable to push changes from `<remote_url>`"
2051 "Unable to push changes from `<remote_url>`"
2051 }
2052 }
2052
2053
2053 """
2054 """
2054
2055
2055 repo = get_repo_or_error(repoid)
2056 repo = get_repo_or_error(repoid)
2056 remote_uri = Optional.extract(remote_uri)
2057 remote_uri = Optional.extract(remote_uri)
2057 remote_uri_display = remote_uri or repo.clone_uri_hidden
2058 remote_uri_display = remote_uri or repo.clone_uri_hidden
2058 if not has_superadmin_permission(apiuser):
2059 if not has_superadmin_permission(apiuser):
2059 _perms = ('repository.admin',)
2060 _perms = ('repository.admin',)
2060 validate_repo_permissions(apiuser, repoid, repo, _perms)
2061 validate_repo_permissions(apiuser, repoid, repo, _perms)
2061
2062
2062 try:
2063 try:
2063 ScmModel().pull_changes(
2064 ScmModel().pull_changes(
2064 repo.repo_name, apiuser.username, remote_uri=remote_uri)
2065 repo.repo_name, apiuser.username, remote_uri=remote_uri)
2065 return {
2066 return {
2066 'msg': 'Pulled from url `%s` on repo `%s`' % (
2067 'msg': 'Pulled from url `%s` on repo `%s`' % (
2067 remote_uri_display, repo.repo_name),
2068 remote_uri_display, repo.repo_name),
2068 'repository': repo.repo_name
2069 'repository': repo.repo_name
2069 }
2070 }
2070 except Exception:
2071 except Exception:
2071 log.exception("Exception occurred while trying to "
2072 log.exception("Exception occurred while trying to "
2072 "pull changes from remote location")
2073 "pull changes from remote location")
2073 raise JSONRPCError(
2074 raise JSONRPCError(
2074 'Unable to pull changes from `%s`' % remote_uri_display
2075 'Unable to pull changes from `%s`' % remote_uri_display
2075 )
2076 )
2076
2077
2077
2078
2078 @jsonrpc_method()
2079 @jsonrpc_method()
2079 def strip(request, apiuser, repoid, revision, branch):
2080 def strip(request, apiuser, repoid, revision, branch):
2080 """
2081 """
2081 Strips the given revision from the specified repository.
2082 Strips the given revision from the specified repository.
2082
2083
2083 * This will remove the revision and all of its decendants.
2084 * This will remove the revision and all of its decendants.
2084
2085
2085 This command can only be run using an |authtoken| with admin rights to
2086 This command can only be run using an |authtoken| with admin rights to
2086 the specified repository.
2087 the specified repository.
2087
2088
2088 This command takes the following options:
2089 This command takes the following options:
2089
2090
2090 :param apiuser: This is filled automatically from the |authtoken|.
2091 :param apiuser: This is filled automatically from the |authtoken|.
2091 :type apiuser: AuthUser
2092 :type apiuser: AuthUser
2092 :param repoid: The repository name or repository ID.
2093 :param repoid: The repository name or repository ID.
2093 :type repoid: str or int
2094 :type repoid: str or int
2094 :param revision: The revision you wish to strip.
2095 :param revision: The revision you wish to strip.
2095 :type revision: str
2096 :type revision: str
2096 :param branch: The branch from which to strip the revision.
2097 :param branch: The branch from which to strip the revision.
2097 :type branch: str
2098 :type branch: str
2098
2099
2099 Example output:
2100 Example output:
2100
2101
2101 .. code-block:: bash
2102 .. code-block:: bash
2102
2103
2103 id : <id_given_in_input>
2104 id : <id_given_in_input>
2104 result : {
2105 result : {
2105 "msg": "'Stripped commit <commit_hash> from repo `<repository name>`'"
2106 "msg": "'Stripped commit <commit_hash> from repo `<repository name>`'"
2106 "repository": "<repository name>"
2107 "repository": "<repository name>"
2107 }
2108 }
2108 error : null
2109 error : null
2109
2110
2110 Example error output:
2111 Example error output:
2111
2112
2112 .. code-block:: bash
2113 .. code-block:: bash
2113
2114
2114 id : <id_given_in_input>
2115 id : <id_given_in_input>
2115 result : null
2116 result : null
2116 error : {
2117 error : {
2117 "Unable to strip commit <commit_hash> from repo `<repository name>`"
2118 "Unable to strip commit <commit_hash> from repo `<repository name>`"
2118 }
2119 }
2119
2120
2120 """
2121 """
2121
2122
2122 repo = get_repo_or_error(repoid)
2123 repo = get_repo_or_error(repoid)
2123 if not has_superadmin_permission(apiuser):
2124 if not has_superadmin_permission(apiuser):
2124 _perms = ('repository.admin',)
2125 _perms = ('repository.admin',)
2125 validate_repo_permissions(apiuser, repoid, repo, _perms)
2126 validate_repo_permissions(apiuser, repoid, repo, _perms)
2126
2127
2127 try:
2128 try:
2128 ScmModel().strip(repo, revision, branch)
2129 ScmModel().strip(repo, revision, branch)
2129 audit_logger.store_api(
2130 audit_logger.store_api(
2130 'repo.commit.strip', action_data={'commit_id': revision},
2131 'repo.commit.strip', action_data={'commit_id': revision},
2131 repo=repo,
2132 repo=repo,
2132 user=apiuser, commit=True)
2133 user=apiuser, commit=True)
2133
2134
2134 return {
2135 return {
2135 'msg': 'Stripped commit %s from repo `%s`' % (
2136 'msg': 'Stripped commit %s from repo `%s`' % (
2136 revision, repo.repo_name),
2137 revision, repo.repo_name),
2137 'repository': repo.repo_name
2138 'repository': repo.repo_name
2138 }
2139 }
2139 except Exception:
2140 except Exception:
2140 log.exception("Exception while trying to strip")
2141 log.exception("Exception while trying to strip")
2141 raise JSONRPCError(
2142 raise JSONRPCError(
2142 'Unable to strip commit %s from repo `%s`' % (
2143 'Unable to strip commit %s from repo `%s`' % (
2143 revision, repo.repo_name)
2144 revision, repo.repo_name)
2144 )
2145 )
2145
2146
2146
2147
2147 @jsonrpc_method()
2148 @jsonrpc_method()
2148 def get_repo_settings(request, apiuser, repoid, key=Optional(None)):
2149 def get_repo_settings(request, apiuser, repoid, key=Optional(None)):
2149 """
2150 """
2150 Returns all settings for a repository. If key is given it only returns the
2151 Returns all settings for a repository. If key is given it only returns the
2151 setting identified by the key or null.
2152 setting identified by the key or null.
2152
2153
2153 :param apiuser: This is filled automatically from the |authtoken|.
2154 :param apiuser: This is filled automatically from the |authtoken|.
2154 :type apiuser: AuthUser
2155 :type apiuser: AuthUser
2155 :param repoid: The repository name or repository id.
2156 :param repoid: The repository name or repository id.
2156 :type repoid: str or int
2157 :type repoid: str or int
2157 :param key: Key of the setting to return.
2158 :param key: Key of the setting to return.
2158 :type: key: Optional(str)
2159 :type: key: Optional(str)
2159
2160
2160 Example output:
2161 Example output:
2161
2162
2162 .. code-block:: bash
2163 .. code-block:: bash
2163
2164
2164 {
2165 {
2165 "error": null,
2166 "error": null,
2166 "id": 237,
2167 "id": 237,
2167 "result": {
2168 "result": {
2168 "extensions_largefiles": true,
2169 "extensions_largefiles": true,
2169 "extensions_evolve": true,
2170 "extensions_evolve": true,
2170 "hooks_changegroup_push_logger": true,
2171 "hooks_changegroup_push_logger": true,
2171 "hooks_changegroup_repo_size": false,
2172 "hooks_changegroup_repo_size": false,
2172 "hooks_outgoing_pull_logger": true,
2173 "hooks_outgoing_pull_logger": true,
2173 "phases_publish": "True",
2174 "phases_publish": "True",
2174 "rhodecode_hg_use_rebase_for_merging": true,
2175 "rhodecode_hg_use_rebase_for_merging": true,
2175 "rhodecode_pr_merge_enabled": true,
2176 "rhodecode_pr_merge_enabled": true,
2176 "rhodecode_use_outdated_comments": true
2177 "rhodecode_use_outdated_comments": true
2177 }
2178 }
2178 }
2179 }
2179 """
2180 """
2180
2181
2181 # Restrict access to this api method to admins only.
2182 # Restrict access to this api method to admins only.
2182 if not has_superadmin_permission(apiuser):
2183 if not has_superadmin_permission(apiuser):
2183 raise JSONRPCForbidden()
2184 raise JSONRPCForbidden()
2184
2185
2185 try:
2186 try:
2186 repo = get_repo_or_error(repoid)
2187 repo = get_repo_or_error(repoid)
2187 settings_model = VcsSettingsModel(repo=repo)
2188 settings_model = VcsSettingsModel(repo=repo)
2188 settings = settings_model.get_global_settings()
2189 settings = settings_model.get_global_settings()
2189 settings.update(settings_model.get_repo_settings())
2190 settings.update(settings_model.get_repo_settings())
2190
2191
2191 # If only a single setting is requested fetch it from all settings.
2192 # If only a single setting is requested fetch it from all settings.
2192 key = Optional.extract(key)
2193 key = Optional.extract(key)
2193 if key is not None:
2194 if key is not None:
2194 settings = settings.get(key, None)
2195 settings = settings.get(key, None)
2195 except Exception:
2196 except Exception:
2196 msg = 'Failed to fetch settings for repository `{}`'.format(repoid)
2197 msg = 'Failed to fetch settings for repository `{}`'.format(repoid)
2197 log.exception(msg)
2198 log.exception(msg)
2198 raise JSONRPCError(msg)
2199 raise JSONRPCError(msg)
2199
2200
2200 return settings
2201 return settings
2201
2202
2202
2203
2203 @jsonrpc_method()
2204 @jsonrpc_method()
2204 def set_repo_settings(request, apiuser, repoid, settings):
2205 def set_repo_settings(request, apiuser, repoid, settings):
2205 """
2206 """
2206 Update repository settings. Returns true on success.
2207 Update repository settings. Returns true on success.
2207
2208
2208 :param apiuser: This is filled automatically from the |authtoken|.
2209 :param apiuser: This is filled automatically from the |authtoken|.
2209 :type apiuser: AuthUser
2210 :type apiuser: AuthUser
2210 :param repoid: The repository name or repository id.
2211 :param repoid: The repository name or repository id.
2211 :type repoid: str or int
2212 :type repoid: str or int
2212 :param settings: The new settings for the repository.
2213 :param settings: The new settings for the repository.
2213 :type: settings: dict
2214 :type: settings: dict
2214
2215
2215 Example output:
2216 Example output:
2216
2217
2217 .. code-block:: bash
2218 .. code-block:: bash
2218
2219
2219 {
2220 {
2220 "error": null,
2221 "error": null,
2221 "id": 237,
2222 "id": 237,
2222 "result": true
2223 "result": true
2223 }
2224 }
2224 """
2225 """
2225 # Restrict access to this api method to admins only.
2226 # Restrict access to this api method to admins only.
2226 if not has_superadmin_permission(apiuser):
2227 if not has_superadmin_permission(apiuser):
2227 raise JSONRPCForbidden()
2228 raise JSONRPCForbidden()
2228
2229
2229 if type(settings) is not dict:
2230 if type(settings) is not dict:
2230 raise JSONRPCError('Settings have to be a JSON Object.')
2231 raise JSONRPCError('Settings have to be a JSON Object.')
2231
2232
2232 try:
2233 try:
2233 settings_model = VcsSettingsModel(repo=repoid)
2234 settings_model = VcsSettingsModel(repo=repoid)
2234
2235
2235 # Merge global, repo and incoming settings.
2236 # Merge global, repo and incoming settings.
2236 new_settings = settings_model.get_global_settings()
2237 new_settings = settings_model.get_global_settings()
2237 new_settings.update(settings_model.get_repo_settings())
2238 new_settings.update(settings_model.get_repo_settings())
2238 new_settings.update(settings)
2239 new_settings.update(settings)
2239
2240
2240 # Update the settings.
2241 # Update the settings.
2241 inherit_global_settings = new_settings.get(
2242 inherit_global_settings = new_settings.get(
2242 'inherit_global_settings', False)
2243 'inherit_global_settings', False)
2243 settings_model.create_or_update_repo_settings(
2244 settings_model.create_or_update_repo_settings(
2244 new_settings, inherit_global_settings=inherit_global_settings)
2245 new_settings, inherit_global_settings=inherit_global_settings)
2245 Session().commit()
2246 Session().commit()
2246 except Exception:
2247 except Exception:
2247 msg = 'Failed to update settings for repository `{}`'.format(repoid)
2248 msg = 'Failed to update settings for repository `{}`'.format(repoid)
2248 log.exception(msg)
2249 log.exception(msg)
2249 raise JSONRPCError(msg)
2250 raise JSONRPCError(msg)
2250
2251
2251 # Indicate success.
2252 # Indicate success.
2252 return True
2253 return True
2253
2254
2254
2255
2255 @jsonrpc_method()
2256 @jsonrpc_method()
2256 def maintenance(request, apiuser, repoid):
2257 def maintenance(request, apiuser, repoid):
2257 """
2258 """
2258 Triggers a maintenance on the given repository.
2259 Triggers a maintenance on the given repository.
2259
2260
2260 This command can only be run using an |authtoken| with admin
2261 This command can only be run using an |authtoken| with admin
2261 rights to the specified repository. For more information,
2262 rights to the specified repository. For more information,
2262 see :ref:`config-token-ref`.
2263 see :ref:`config-token-ref`.
2263
2264
2264 This command takes the following options:
2265 This command takes the following options:
2265
2266
2266 :param apiuser: This is filled automatically from the |authtoken|.
2267 :param apiuser: This is filled automatically from the |authtoken|.
2267 :type apiuser: AuthUser
2268 :type apiuser: AuthUser
2268 :param repoid: The repository name or repository ID.
2269 :param repoid: The repository name or repository ID.
2269 :type repoid: str or int
2270 :type repoid: str or int
2270
2271
2271 Example output:
2272 Example output:
2272
2273
2273 .. code-block:: bash
2274 .. code-block:: bash
2274
2275
2275 id : <id_given_in_input>
2276 id : <id_given_in_input>
2276 result : {
2277 result : {
2277 "msg": "executed maintenance command",
2278 "msg": "executed maintenance command",
2278 "executed_actions": [
2279 "executed_actions": [
2279 <action_message>, <action_message2>...
2280 <action_message>, <action_message2>...
2280 ],
2281 ],
2281 "repository": "<repository name>"
2282 "repository": "<repository name>"
2282 }
2283 }
2283 error : null
2284 error : null
2284
2285
2285 Example error output:
2286 Example error output:
2286
2287
2287 .. code-block:: bash
2288 .. code-block:: bash
2288
2289
2289 id : <id_given_in_input>
2290 id : <id_given_in_input>
2290 result : null
2291 result : null
2291 error : {
2292 error : {
2292 "Unable to execute maintenance on `<reponame>`"
2293 "Unable to execute maintenance on `<reponame>`"
2293 }
2294 }
2294
2295
2295 """
2296 """
2296
2297
2297 repo = get_repo_or_error(repoid)
2298 repo = get_repo_or_error(repoid)
2298 if not has_superadmin_permission(apiuser):
2299 if not has_superadmin_permission(apiuser):
2299 _perms = ('repository.admin',)
2300 _perms = ('repository.admin',)
2300 validate_repo_permissions(apiuser, repoid, repo, _perms)
2301 validate_repo_permissions(apiuser, repoid, repo, _perms)
2301
2302
2302 try:
2303 try:
2303 maintenance = repo_maintenance.RepoMaintenance()
2304 maintenance = repo_maintenance.RepoMaintenance()
2304 executed_actions = maintenance.execute(repo)
2305 executed_actions = maintenance.execute(repo)
2305
2306
2306 return {
2307 return {
2307 'msg': 'executed maintenance command',
2308 'msg': 'executed maintenance command',
2308 'executed_actions': executed_actions,
2309 'executed_actions': executed_actions,
2309 'repository': repo.repo_name
2310 'repository': repo.repo_name
2310 }
2311 }
2311 except Exception:
2312 except Exception:
2312 log.exception("Exception occurred while trying to run maintenance")
2313 log.exception("Exception occurred while trying to run maintenance")
2313 raise JSONRPCError(
2314 raise JSONRPCError(
2314 'Unable to execute maintenance on `%s`' % repo.repo_name)
2315 'Unable to execute maintenance on `%s`' % repo.repo_name)
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