source: peerreviewplugin/tags/0.12/3.1/codereview/admin.py

Last change on this file was 17268, checked in by Cinc-th, 5 years ago

PeerReviewPlugin: refresh of project files on the Modify Project Info admin page failed.

File size: 9.6 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# Copyright (C) 2016 Cinc
4# All rights reserved.
5#
6# This software is licensed as described in the file COPYING.txt, which
7# you should have received as part of this distribution.
8#
9# Author: Cinc
10#
11
12from trac.admin import IAdminPanelProvider
13from trac.core import Component, implements
14from trac.util.translation import _
15from trac.web.chrome import add_notice, add_script, add_script_data, add_stylesheet, add_warning
16from .model import ReviewDataModel, ReviewFileModel
17from .repo import insert_project_files, repo_path_exists
18
19__author__ = 'Cinc'
20__license__ = "BSD"
21
22class PeerReviewFileAdmin(Component):
23    """Admin panel to specify files belonging to a project.
24
25    [[BR]]
26    You may define a project identifier and a root folder from the repository holding all the files
27    of a project using this admin panel. When saving the information all the files in the folder hierarchy are hashed
28    and file name, revision, hash and project name are inserted in the database.
29
30    Using the file information it is possible to create reports (see TracReports for more information) like which
31    files may need a review and more.
32    """
33    implements(IAdminPanelProvider)
34
35    # IAdminPanelProvider methods
36
37    def get_admin_panels(self, req):
38        if 'CODE_REVIEW_DEV' in req.perm:
39            yield ('codereview', 'Code review', 'projectfiles', 'Project Files')
40
41    def render_admin_panel(self, req, cat, page, path_info):
42
43        def remove_project_info(rem_name):
44            # Remove project name info
45            rev_data = ReviewDataModel(self.env)
46            rev_data.clear_props()
47            rev_data['data'] = rem_name
48            rev_data['data_key'] = 'name'
49            for item in rev_data.list_matching_objects():
50                item.delete()
51            # Remove info about project like rootfolder, extensions, revision, repo
52            rev_data = ReviewDataModel(self.env)
53            rev_data.clear_props()
54            rev_data['data_key'] = rem_name
55            for item in rev_data.list_matching_objects():
56                item.delete()
57            ReviewFileModel.delete_files_by_project_name(self.env, rem_name)
58
59        def add_project_info():
60            def _insert_project_info(type_, key_, val):
61                rev_data = ReviewDataModel(self.env)
62                rev_data['type'] = type_
63                rev_data['data_key'] = key_
64                rev_data['data'] = val
65                rev_data.insert()
66            _insert_project_info('fileproject', 'name', name)
67            _insert_project_info('rootfolder', name, rootfolder)
68            _insert_project_info('extensions', name, exts)
69            _insert_project_info('repo', name, reponame)
70            _insert_project_info('revision', name, rev)
71
72        def create_ext_list(ext_str):
73            """Create a list of extensions from a string.
74
75            Double ',', trailing ',' and empty extensions are filtered out. Extensions not starting with '.'
76            are ignored.
77
78            @return: unfiltered extension list, filtered extension list
79            """
80            if not ext_str:
81                return [], []
82            ext_list = [ext.strip() for ext in ext_str.split(',') if ext.strip()]  # filter trailing ',', double ','and empty exts
83            return [ext for ext in ext_str.split(',') if ext], [ext.lower() for ext in ext_list if ext[0] == '.']
84
85        req.perm.require('CODE_REVIEW_DEV')
86
87        name = req.args.get('projectname') or path_info
88        rootfolder = req.args.get('rootfolder')
89        reponame = req.args.get('reponame', '')
90        rev = req.args.get('rev', None)
91        exts = req.args.get('extensions', '')
92        follow_ext = req.args.get('follow_ext', False)
93        ext_list, ext_filtered = create_ext_list(exts)
94        sel = req.args.get('sel', [])  # For removal
95        if type(sel) is not list:
96            sel = [sel]
97
98        all_proj = ReviewDataModel.all_file_project_data(self.env)
99
100        if req.method=='POST':
101            if req.args.get('add'):
102                def do_redirect():
103                    req.redirect(req.href.admin(cat, page, projectname=name,
104                                                rootfolder=rootfolder,
105                                                extensions=exts,
106                                                repo=reponame,
107                                                rev=rev,
108                                                error=1))
109                if not name:
110                    add_warning(req, _("You need to specify a project name."))
111                    do_redirect()
112                if name in all_proj:
113                    add_warning(req, _("The project identifier already exists."))
114                    do_redirect()
115                if not repo_path_exists(self.env, rootfolder, reponame):
116                    add_warning(req, _("The given root folder can't be found in the repository or it is a file."))
117                    do_redirect()
118                if len(ext_list) != len(ext_filtered):
119                    add_warning(req, _("Some extensions are not valid."))
120                    do_redirect()
121                add_project_info()
122                errors, num_files = insert_project_files(self, rootfolder, name, ext_filtered, follow_ext, rev=rev, reponame=reponame)
123                add_notice(req, _("The project has been added. %s files belonging to the project have been added "
124                                  "to the database"), num_files)
125                for err in errors:
126                    add_warning(req, err)
127            elif req.args.get('save'):
128                def do_redirect_save():
129                    req.redirect(req.href.admin(cat, page, path_info,
130                                                projectname=name,
131                                                rootfolder=rootfolder,
132                                                extensions=exts,
133                                                repo=reponame,
134                                                rev=rev,
135                                                error=1))
136
137                if not req.args.get('projectname'):
138                    add_warning(req, _("No project name given. The old name was inserted again."))
139                    add_warning(req, _("No changes have been saved."))
140                    do_redirect_save()
141                if name != path_info:
142                    if name in all_proj:
143                        add_warning(req, _("The project identifier already exists."))
144                        do_redirect_save()
145                if not repo_path_exists(self.env, rootfolder, reponame):
146                    add_warning(req, _("The given root folder %s can't be found in the repository or it is a file."),
147                                       rootfolder)
148                    do_redirect_save()
149                if len(ext_list) != len(ext_filtered):
150                    add_warning(req, _("Some extensions are not valid. %s"), exts)
151                    do_redirect_save()
152                # Handle change. We remove all data for old name and recreate it using the new one
153                remove_project_info(path_info)
154                add_project_info()
155                errors, num_files = insert_project_files(self, rootfolder, name, ext_filtered, follow_ext, rev=rev, reponame=reponame)
156                add_notice(req, _("Your changes have been changed. %s files belonging to the project have been added "
157                                  "to the database"), num_files)
158                for err in errors:
159                    add_warning(req, err)
160            elif req.args.get('remove'):
161                for rem_name in sel:
162                    remove_project_info(rem_name)
163
164            req.redirect(req.href.admin(cat, page))
165
166        all_proj_lst = [[key, value] for key, value in all_proj.items()]
167        data = {'view': 'detail' if path_info else 'list',
168                'projects': sorted(all_proj_lst, key=lambda item: item[0]),
169                'projectname': name,
170        }
171        if(path_info):
172            data['view_project'] = path_info
173            view_proj = all_proj[path_info]
174            # With V3.1 the following was added to the saved information for multi repo support.
175            # It isn't available for old projects.
176            if 'repo' not in view_proj:
177                view_proj['repo'] = ''
178            if 'revision' not in view_proj:
179                view_proj['revision'] = ''
180            data.update({
181                'rootfolder': rootfolder or view_proj['rootfolder'],
182                'extensions': exts or view_proj['extensions'],
183                'reponame': reponame or view_proj['repo'],
184                'revision': rev or view_proj['revision'],
185            })
186        else:
187            data.update({
188                'rootfolder': rootfolder,
189                'extensions': exts,
190                'reponame': reponame,
191                'revision': rev
192            })
193        add_stylesheet(req, 'common/css/browser.css')
194        add_stylesheet(req, 'hw/css/admin_file.css')
195        add_script_data(req, {'repo_browser': self.env.href.adminrepobrowser(data['rootfolder'],
196                                                                             repo=data['reponame'],
197                                                                             rev=data['revision']),
198                              'show_repo_idx': path_info == None if 'error' not in req.args else False}
199                        )
200        add_script(req, 'hw/js/admin_files.js')
201        return 'admin_files.html', data
Note: See TracBrowser for help on using the repository browser.