Left: | ||
Right: |
OLD | NEW |
---|---|
1 # Copyright 2008 Google Inc. | 1 # Copyright 2008 Google Inc. |
2 # | 2 # |
3 # Licensed under the Apache License, Version 2.0 (the "License"); | 3 # Licensed under the Apache License, Version 2.0 (the "License"); |
4 # you may not use this file except in compliance with the License. | 4 # you may not use this file except in compliance with the License. |
5 # You may obtain a copy of the License at | 5 # You may obtain a copy of the License at |
6 # | 6 # |
7 # http://www.apache.org/licenses/LICENSE-2.0 | 7 # http://www.apache.org/licenses/LICENSE-2.0 |
8 # | 8 # |
9 # Unless required by applicable law or agreed to in writing, software | 9 # Unless required by applicable law or agreed to in writing, software |
10 # distributed under the License is distributed on an "AS IS" BASIS, | 10 # distributed under the License is distributed on an "AS IS" BASIS, |
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 # See the License for the specific language governing permissions and | 12 # See the License for the specific language governing permissions and |
13 # limitations under the License. | 13 # limitations under the License. |
14 | 14 |
15 """Views for Rietveld.""" | 15 """Views for Rietveld.""" |
16 | 16 |
17 | 17 |
18 import binascii | 18 import binascii |
19 import copy | |
19 import datetime | 20 import datetime |
20 import email # see incoming_mail() | 21 import email # see incoming_mail() |
21 import email.utils | 22 import email.utils |
23 import difflib | |
22 import itertools | 24 import itertools |
23 import json | 25 import json |
24 import logging | 26 import logging |
25 import md5 | 27 import md5 |
26 import mimetypes | 28 import mimetypes |
27 import os | 29 import os |
28 import random | 30 import random |
29 import re | 31 import re |
30 import tarfile | 32 import tarfile |
31 import tempfile | 33 import tempfile |
(...skipping 1704 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1736 | 1738 |
1737 ps_key = db.Key.from_path( | 1739 ps_key = db.Key.from_path( |
1738 models.PatchSet.kind(), | 1740 models.PatchSet.kind(), |
1739 db.allocate_ids(db.Key.from_path(models.PatchSet.kind(), 1, | 1741 db.allocate_ids(db.Key.from_path(models.PatchSet.kind(), 1, |
1740 parent=issue.key()), 1)[0], | 1742 parent=issue.key()), 1)[0], |
1741 parent=issue.key()) | 1743 parent=issue.key()) |
1742 | 1744 |
1743 patchset = models.PatchSet(issue=issue, data=data, url=url, key=ps_key) | 1745 patchset = models.PatchSet(issue=issue, data=data, url=url, key=ps_key) |
1744 patchset.put() | 1746 patchset.put() |
1745 | 1747 |
1748 commitPatch = _create_commit_message_patch(patchset, | |
1749 patchset.issue.description) | |
1750 commitPatch.put() | |
1751 | |
1746 if not separate_patches: | 1752 if not separate_patches: |
1747 try: | 1753 try: |
1748 patches = engine.ParsePatchSet(patchset) | 1754 patches = engine.ParsePatchSet(patchset) |
1749 except: | 1755 except: |
1750 # catch all exceptions happening in engine.ParsePatchSet, | 1756 # catch all exceptions happening in engine.ParsePatchSet, |
1751 # engine.SplitPatch. With malformed diffs a variety of exceptions could | 1757 # engine.SplitPatch. With malformed diffs a variety of exceptions could |
1752 # happen there. | 1758 # happen there. |
1753 logging.exception('Exception during patch parsing') | 1759 logging.exception('Exception during patch parsing') |
1754 patches = [] | 1760 patches = [] |
1755 if not patches: | 1761 if not patches: |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1821 @issue_editor_required | 1827 @issue_editor_required |
1822 @xsrf_required | 1828 @xsrf_required |
1823 def add(request): | 1829 def add(request): |
1824 """/<issue>/add - Add a new PatchSet to an existing Issue.""" | 1830 """/<issue>/add - Add a new PatchSet to an existing Issue.""" |
1825 issue = request.issue | 1831 issue = request.issue |
1826 form = AddForm(request.POST, request.FILES) | 1832 form = AddForm(request.POST, request.FILES) |
1827 if not _add_patchset_from_form(request, issue, form): | 1833 if not _add_patchset_from_form(request, issue, form): |
1828 return show(request, issue.key().id(), form) | 1834 return show(request, issue.key().id(), form) |
1829 return HttpResponseRedirect(reverse(show, args=[issue.key().id()])) | 1835 return HttpResponseRedirect(reverse(show, args=[issue.key().id()])) |
1830 | 1836 |
1837 def _create_commit_message_patch(patchset, description): | |
1838 filename = "COMMIT_MSG" | |
tfarina1
2013/07/26 00:55:56
Can you rename this to "Commit Message"? So it mat
Andi
2013/07/29 08:38:34
I'd also would like to see a module constant for t
jparent1
2013/08/14 20:16:52
Done.
jparent1
2013/08/14 20:16:52
Done.
| |
1839 | |
1840 diff = "" | |
1841 udiff = difflib.unified_diff("",description.splitlines(1),· | |
1842 fromfile="\dev\\null",tofile=filename) | |
1843 for line in udiff: | |
1844 diff += line | |
1845 | |
1846 patch_key = db.Key.from_path( | |
1847 models.Patch.kind(), | |
1848 db.allocate_ids(db.Key.from_path(models.Patch.kind(), 1, | |
1849 parent=patchset.key()), 1)[0], | |
1850 parent=patchset.key()) | |
1851 commitPatch = models.Patch(patchset=patchset, text=utils.to_dbtext(diff),· | |
1852 filename=filename, key=patch_key, | |
1853 no_base_file=True) | |
1854 return commitPatch | |
1831 | 1855 |
1832 def _add_patchset_from_form(request, issue, form, message_key='message', | 1856 def _add_patchset_from_form(request, issue, form, message_key='message', |
1833 emails_add_only=False): | 1857 emails_add_only=False): |
1834 """Helper for add() and upload().""" | 1858 """Helper for add() and upload().""" |
1835 if form.is_valid(): | 1859 if form.is_valid(): |
1836 data_url = _get_data_url(form) | 1860 data_url = _get_data_url(form) |
1837 if not form.is_valid(): | 1861 if not form.is_valid(): |
1838 return None | 1862 return None |
1839 account = models.Account.get_account_for_user(request.user) | 1863 account = models.Account.get_account_for_user(request.user) |
1840 if account.blocked: | 1864 if account.blocked: |
1841 return None | 1865 return None |
1842 if not issue.edit_allowed: | 1866 if not issue.edit_allowed: |
1843 # This check is done at each call site but check again as a safety measure. | 1867 # This check is done at each call site but check again as a safety measure. |
1844 return None | 1868 return None |
1845 data, url, separate_patches = data_url | 1869 data, url, separate_patches = data_url |
1846 message = form.cleaned_data[message_key] | 1870 message = form.cleaned_data[message_key] |
1847 ps_key = db.Key.from_path( | 1871 ps_key = db.Key.from_path( |
1848 models.PatchSet.kind(), | 1872 models.PatchSet.kind(), |
1849 db.allocate_ids(db.Key.from_path(models.PatchSet.kind(), 1, | 1873 db.allocate_ids(db.Key.from_path(models.PatchSet.kind(), 1, |
1850 parent=issue.key()), 1)[0], | 1874 parent=issue.key()), 1)[0], |
1851 parent=issue.key()) | 1875 parent=issue.key()) |
1852 patchset = models.PatchSet(issue=issue, message=message, data=data, url=url, | 1876 patchset = models.PatchSet(issue=issue, message=message, data=data, url=url, |
1853 key=ps_key) | 1877 key=ps_key) |
1854 patchset.put() | 1878 patchset.put() |
1855 | 1879 |
1880 commitPatch = _create_commit_message_patch(patchset, | |
1881 patchset.issue.description) | |
1882 commitPatch.put() | |
1883 | |
1856 if not separate_patches: | 1884 if not separate_patches: |
1857 try: | 1885 try: |
1858 patches = engine.ParsePatchSet(patchset) | 1886 patches = engine.ParsePatchSet(patchset) |
1859 except: | 1887 except: |
1860 logging.exception('Exception during patchset parsing') | 1888 logging.exception('Exception during patchset parsing') |
1861 patches = [] | 1889 patches = [] |
1862 if not patches: | 1890 if not patches: |
1863 patchset.delete() | 1891 patchset.delete() |
1864 errkey = url and 'url' or 'data' | 1892 errkey = url and 'url' or 'data' |
1865 form.errors[errkey] = ['Patch set contains no recognizable patches'] | 1893 form.errors[errkey] = ['Patch set contains no recognizable patches'] |
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2242 | 2270 |
2243 if form.is_valid() and not issue.local_base: | 2271 if form.is_valid() and not issue.local_base: |
2244 base = form.get_base() | 2272 base = form.get_base() |
2245 | 2273 |
2246 if not form.is_valid(): | 2274 if not form.is_valid(): |
2247 return respond(request, 'edit.html', {'issue': issue, 'form': form}) | 2275 return respond(request, 'edit.html', {'issue': issue, 'form': form}) |
2248 cleaned_data = form.cleaned_data | 2276 cleaned_data = form.cleaned_data |
2249 | 2277 |
2250 was_closed = issue.closed | 2278 was_closed = issue.closed |
2251 issue.subject = cleaned_data['subject'] | 2279 issue.subject = cleaned_data['subject'] |
2280 old_description = issue.description | |
2252 issue.description = cleaned_data['description'] | 2281 issue.description = cleaned_data['description'] |
2282 · | |
2283 # If the description was updated, it would get out of sync with the special | |
2284 # COMMIT_MSG file in the last pastchset. So we clone the last patchset, | |
2285 # modulo a new COMMIT_MSG patch.· | |
2286 if issue.description != old_description: | |
2287 | |
2288 def clone_without_key(obj, **extra_args): | |
2289 """ Clones an object, without copying the key """ | |
2290 klass = obj.__class__ | |
2291 props = {} | |
2292 for k, v in klass.properties().iteritems(): | |
2293 if not (type(v) == db.DateTimeProperty and | |
2294 (getattr(v, 'auto_now') or getattr(v, 'auto_now_add'))): | |
2295 if type(v) == db.ReferenceProperty: | |
2296 value = getattr(klass, k).get_value_for_datastore(obj) | |
2297 else: | |
2298 value = v.__get__(obj, klass) | |
2299 props[k] = value | |
2300 props.update(extra_args)···· | |
2301 return klass(**props)···· | |
2302 | |
2303 # Create a new patchset from the last one. | |
2304 patchsets = list(issue.patchset_set.order('created')) | |
2305 last_patchset = patchsets[-1] | |
2306 new_patchset_msg = 'Auto-generated patchset by description update.' | |
2307 new_patchset = clone_without_key(last_patchset, parent=issue, | |
2308 message=new_patchset_msg) | |
2309 new_patchset.put() | |
2310 · | |
2311 # Add the new commit message patch. | |
2312 commitPatch = _create_commit_message_patch(new_patchset, issue.description) | |
2313 commitPatch.put() | |
2314 | |
2315 # And copy all the patches over from last patchset. | |
2316 for patch in list(last_patchset.patch_set): | |
2317 # Skip the old commit message, since we just created a new one. | |
2318 if patch.filename == "COMMIT_MSG": | |
2319 continue | |
2320 new_patch = clone_without_key(patch, parent=new_patchset, | |
2321 patchset=new_patchset) | |
2322 new_patch.put() | |
2323 | |
2253 issue.closed = cleaned_data['closed'] | 2324 issue.closed = cleaned_data['closed'] |
2254 issue.private = cleaned_data.get('private', False) | 2325 issue.private = cleaned_data.get('private', False) |
2255 base_changed = (issue.base != base) | 2326 base_changed = (issue.base != base) |
2256 issue.base = base | 2327 issue.base = base |
2257 issue.reviewers = reviewers | 2328 issue.reviewers = reviewers |
2258 issue.cc = cc | 2329 issue.cc = cc |
2259 if base_changed: | 2330 if base_changed: |
2260 for patchset in issue.patchset_set: | 2331 for patchset in issue.patchset_set: |
2261 db.run_in_transaction(_delete_cached_contents, list(patchset.patch_set)) | 2332 db.run_in_transaction(_delete_cached_contents, list(patchset.patch_set)) |
2262 issue.calculate_updates_for() | 2333 issue.calculate_updates_for() |
(...skipping 2233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4496 if form.is_valid(): | 4567 if form.is_valid(): |
4497 client_id = form.cleaned_data['client_id'] | 4568 client_id = form.cleaned_data['client_id'] |
4498 client_secret = form.cleaned_data['client_secret'] | 4569 client_secret = form.cleaned_data['client_secret'] |
4499 additional_client_ids = form.cleaned_data['additional_client_ids'] | 4570 additional_client_ids = form.cleaned_data['additional_client_ids'] |
4500 auth_utils.SecretKey.set_config(client_id, client_secret, | 4571 auth_utils.SecretKey.set_config(client_id, client_secret, |
4501 additional_client_ids) | 4572 additional_client_ids) |
4502 return HttpResponseRedirect(reverse(set_client_id_and_secret)) | 4573 return HttpResponseRedirect(reverse(set_client_id_and_secret)) |
4503 else: | 4574 else: |
4504 form = ClientIDAndSecretForm() | 4575 form = ClientIDAndSecretForm() |
4505 return respond(request, 'set_client_id_and_secret.html', {'form': form}) | 4576 return respond(request, 'set_client_id_and_secret.html', {'form': form}) |
OLD | NEW |