├── .gitignore ├── README.md ├── collect-users.py ├── gitlab_api ├── Connection.py └── __init__.py ├── gitlab_direct ├── Connection.py ├── __init__.py ├── model.py ├── model813.py ├── model815.py ├── model816.py ├── model817.py ├── model84.py ├── model85.py ├── model87.py └── model90.py ├── licences ├── GPL.txt └── LGPL.txt ├── migrate.cfg.example ├── migrate.py ├── pwiz.py ├── requirements.txt └── trac2down ├── Trac2Down.py └── __init__.py /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.cfg 3 | *.swp 4 | *.bak 5 | *.pyc 6 | *.*~ 7 | env 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | What 2 | ===== 3 | 4 | This script migrates milestones, issues and wiki pages from trac to GitLab. 5 | 6 | NOTE: This project is in [deprecated](https://github.com/moimael/trac-to-gitlab/issues/23#issuecomment-299425062), in favor of [tracboat/tracboat](https://github.com/tracboat/tracboat). 7 | 8 | Features 9 | -------- 10 | * Component & Issue-Type are converted to labels 11 | * Comments to issues are copied over 12 | * Supports two modes of tansfer: 13 | * Using GitLab web API 14 | * Direct access through GitLab's database and file system 15 | * In direct mode, attachments are transfered and the issues and notes dates and ownership are preserved 16 | * In API mode, attachments are not transfered, issues and notes are owned by a single user and their dates are the current date. 17 | 18 | How 19 | ==== 20 | 21 | Migrating a trac project to GitLab is a relatively complex process involving four steps: 22 | 23 | * Create a new project 24 | * Migrate the repository (can just be cloning a git repository if the trac project is already using git or could involve converting from subversion using git-svn) 25 | * Create the users for the project 26 | * Migrate issues and milestones 27 | * Migrate wiki pages 28 | 29 | This script takes care of the last two bullet points and provides help for the third one. 30 | 31 | Usage: 32 | 33 | 1. copy ```migrate.cfg.example``` to ```migrate.cfg``` 34 | 2. configure the values 35 | 3. run ```./collect-users.py``` to extract the user names from Trac 36 | 4. update ```migrate.cfg``` and create the users in GitLab 37 | 5. run (```./migrate.py```). Make sure you test it on a test project prior, if you run it twice against the same project you will get duplicated issues unless you're using direct access with overwrite set to yes. 38 | 39 | Issues and milestones are copied to GitLab. 40 | 41 | Wiki pages are copied to a folder on your machine and must be pushed into GitLab using wiki's git access. 42 | 43 | GitLab versions 44 | =============== 45 | 46 | The database model should correspond to the version of GitLab that you are using. 47 | 48 | This repo contains models for multiple versions (gitlab_direct/model.py) and the version number should be updated correspondingly in the imports in [gitlab_direct/__init__.py](gitlab_direct/__init__.py) and [gitlab_direct/Connection.py](gitlab_direct/Connection.py). 49 | 50 | To support a new version, use pwiz.py: 51 | 52 | ``` 53 | $ pwiz.py -e postgresql -u gitlab gitlabhq_production > gitlab_direct/model.py 54 | ``` 55 | 56 | Manual updates must then be applied, see for instance the [manual updates for 6.4](https://gitlab.dyomedea.com/vdv/trac-to-gitlab/commit/8a5592a7b996054849bf7ac21fd5fec267db1df9). 57 | 58 | Configuration 59 | ============= 60 | 61 | The configuration must be located in a file named "migrate.cfg" 62 | 63 | Source 64 | ------- 65 | 66 | * ```url``` - xmlrpc url to trac, e.g. ```https://user:secret@www.example.com/projects/thisismyproject/login/xmlrpc``` 67 | 68 | Target 69 | ------- 70 | 71 | * ```project_name``` - the destination project including the paths to it. Basically the rest of the clone url minus the ".git". E.g. ```jens.neuhalfen/task-ninja```. 72 | * ```method``` - direct or api 73 | 74 | ÄPI mode: 75 | 76 | * ```url``` - e.g. ```https://www.exmple.com/gitlab/api/v3``` 77 | * ```access_token``` - the access token of the user creating all the issues. Found on the account page, e.g. ```secretsecretsecret``` 78 | * ```ssl_verify``` - set to ```yes``` to verify SSL server certificates. 79 | 80 | Direct mode: 81 | 82 | * ```overwrite````- if set to yes, the milestones and issues are cleared for this projects and issues are recreated with their trac id (useful to preserve trac links) 83 | * ```db-name``` - MySQL database name 84 | * ```db-user``` - MySQL user name 85 | * ```db-password``` - MySQL password 86 | * ```uploads``` - GitLab uploads directory 87 | * ```usernames``` Comma separed list of username mappings such as: ```trac1->git1, trac2->git2``` 88 | 89 | Wiki 90 | ---- 91 | 92 | * ```migrate``` - Should the wiki pages be converted? 93 | * ```target-directory``` - Directory in which the wiki pages should be written 94 | 95 | Issues 96 | ------ 97 | 98 | * ```migrate``` - Should we migrate issues and milestones? 99 | 100 | Licenses 101 | ======== 102 | 103 | LGPL license version 3.0 (see the [licences directory](licences)). 104 | 105 | History 106 | ======= 107 | 108 | * The main program has been cloned from https://gitlab.dyomedea.com/vdv/trac-to-gitlab which itself has been cloned from https://github.com/neuhalje/hack-copy-track-issues-to-gitlab 109 | * Trac2down.py (the conversion of trac wiki markup to markdown) has been cloned from https://gist.github.com/sgk/1286682 and https://gist.github.com/tcchau/4628317 110 | 111 | Requirements 112 | ============== 113 | 114 | * Python 3.2, xmlrpclib, requests 115 | * Trac with [XML-RPC plugin](http://trac-hacks.org/wiki/XmlRpcPlugin) enabled 116 | * Gitlab 117 | 118 | And also, if you use the direct access to GitLab's database: 119 | * [peewee](https://github.com/coleifer/peewee) 120 | * [PyMySQl](https://github.com/PyMySQL/PyMySQL) 121 | -------------------------------------------------------------------------------- /collect-users.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # vim: autoindent tabstop=4 shiftwidth=4 expandtab softtabstop=4 filetype=python fileencoding=utf-8 3 | ''' 4 | Copyright © 2013 5 | Eric van der Vlist 6 | Jens Neuhalfen 7 | See license information at the bottom of this file 8 | ''' 9 | 10 | import re 11 | import os 12 | import ConfigParser 13 | import ast 14 | from datetime import datetime 15 | from re import MULTILINE 16 | import xmlrpclib 17 | import trac2down 18 | 19 | """ 20 | What 21 | ===== 22 | 23 | This script migrates issues from trac to gitlab. 24 | 25 | License 26 | ======== 27 | 28 | License: http://www.wtfpl.net/ 29 | 30 | Requirements 31 | ============== 32 | 33 | * Python 2, xmlrpclib, requests 34 | * Trac with xmlrpc plugin enabled 35 | * Peewee (direct method) 36 | * GitLab 37 | 38 | """ 39 | 40 | default_config = { 41 | 'ssl_verify': 'no', 42 | 'migrate' : 'true', 43 | 'overwrite' : 'true', 44 | 'exclude_authors' : 'trac', 45 | 'uploads' : '' 46 | } 47 | 48 | config = ConfigParser.ConfigParser(default_config) 49 | config.read('migrate.cfg') 50 | 51 | 52 | trac_url = config.get('source', 'url') 53 | dest_project_name = config.get('target', 'project_name') 54 | uploads_path = config.get('target', 'uploads') 55 | users_map = ast.literal_eval(config.get('target', 'usernames')) 56 | 57 | method = config.get('target', 'method') 58 | 59 | ticket_owners = set() 60 | ticket_reporters = set() 61 | ticket_message_posters = set() 62 | 63 | if (method == 'api'): 64 | from gitlab_api import Connection, Issues, Notes, Milestones 65 | gitlab_url = config.get('target', 'url') 66 | gitlab_access_token = config.get('target', 'access_token') 67 | dest_ssl_verify = config.getboolean('target', 'ssl_verify') 68 | elif (method == 'direct'): 69 | from gitlab_direct import Connection, Issues, Notes, Milestones 70 | db_name = config.get('target', 'db-name') 71 | db_password = config.get('target', 'db-password') 72 | db_user = config.get('target', 'db-user') 73 | db_path = config.get('target', 'db-path') 74 | 75 | 76 | def collect_users(source): 77 | 78 | get_all_tickets = xmlrpclib.MultiCall(source) 79 | 80 | for ticket in source.ticket.query("max=0&order=id"): 81 | get_all_tickets.ticket.get(ticket) 82 | 83 | ticket_index = 0 84 | 85 | for src_ticket in get_all_tickets(): 86 | src_ticket_id = src_ticket[0] 87 | src_ticket_data = src_ticket[3] 88 | 89 | print("ticket id: %s" % src_ticket_id) 90 | print("ticket index: %s" % ticket_index) 91 | print("owner: %s" % src_ticket_data['owner']) 92 | print("reporter: %s" % src_ticket_data['reporter']) 93 | ticket_owners.add(src_ticket_data['owner']) 94 | ticket_reporters.add(src_ticket_data['reporter']) 95 | 96 | changelog = source.ticket.changeLog(src_ticket_id) 97 | for change in changelog: 98 | change_type = change[2] 99 | if (change_type == "comment") and change[4] != '': 100 | print "ticket message poster: ", change[1] 101 | ticket_message_posters.add(change[1]) 102 | 103 | ticket_index += 1 104 | 105 | 106 | if __name__ == "__main__": 107 | 108 | if method == 'api': 109 | dest = Connection(gitlab_url,gitlab_access_token,dest_ssl_verify) 110 | elif method == 'direct': 111 | dest = Connection(db_name, db_user, db_password, db_path, uploads_path) 112 | 113 | for user in set(users_map.values()): 114 | try: 115 | gitlab_user = dest.get_user_id(user) 116 | except: 117 | print("User does not exist in GitLab: %s" % user) 118 | 119 | source = xmlrpclib.ServerProxy(trac_url) 120 | 121 | collect_users(source) 122 | 123 | print("--------") 124 | print("Ticket owners:") 125 | print(ticket_owners) 126 | print("Ticket reporters:") 127 | print(ticket_reporters) 128 | print("Ticket message posters:") 129 | print(ticket_message_posters) 130 | 131 | print("") 132 | print("--------") 133 | print("") 134 | print("User mappings (copy-paste it into the configuration file and fill in the missing values):") 135 | print("") 136 | print("usernames = {") 137 | for user in ticket_owners.union(ticket_reporters).union(ticket_message_posters): 138 | if user in users_map.keys(): 139 | print(" u'%s': u'%s'," % (user, users_map[user])) 140 | else: 141 | print(" u'%s': u''," % user) 142 | print(" }") 143 | 144 | ''' 145 | This file is part of . 146 | 147 | This sotfware is free software: you can redistribute it and/or modify 148 | it under the terms of the GNU Lesser General Public License as published by 149 | the Free Software Foundation, either version 3 of the License, or 150 | (at your option) any later version. 151 | 152 | This sotfware is distributed in the hope that it will be useful, 153 | but WITHOUT ANY WARRANTY; without even the implied warranty of 154 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 155 | GNU Lesser General Public License for more details. 156 | 157 | You should have received a copy of the GNU Lesser General Public License 158 | along with this library. If not, see . 159 | ''' 160 | -------------------------------------------------------------------------------- /gitlab_api/Connection.py: -------------------------------------------------------------------------------- 1 | # vim: autoindent tabstop=4 shiftwidth=4 expandtab softtabstop=4 filetype=python fileencoding=utf-8 2 | ''' 3 | Copyright © 2013 4 | Eric van der Vlist 5 | Jens Neuhalfen 6 | See license information at the bottom of this file 7 | ''' 8 | 9 | import json 10 | import requests 11 | import datetime 12 | import hashlib 13 | 14 | # See http://code.activestate.com/recipes/52308-the-simple-but-handy-collector-of-a-bunch-of-named/?in=user-97991 15 | class Bunch(object): 16 | def __init__(self, **kwds): 17 | self.__dict__.update(kwds) 18 | 19 | @staticmethod 20 | def create(dictionary): 21 | if not dictionary: 22 | return None 23 | bunch = Bunch() 24 | bunch.__dict__ = dictionary 25 | return bunch 26 | 27 | class Issues(Bunch): 28 | pass 29 | 30 | class Notes(Bunch): 31 | pass 32 | 33 | class Milestones(Bunch): 34 | pass 35 | 36 | class Connection(object): 37 | """ 38 | Connection to the gitlab API 39 | """ 40 | 41 | def __init__(self, url, access_token, ssl_verify): 42 | """ 43 | 44 | :param url: "https://www.neuhalfen.name/gitlab/api/v3" 45 | :param access_token: "secretsecretsecret" 46 | """ 47 | self.url = url 48 | self.access_token = access_token 49 | self.verify = ssl_verify 50 | self.impers_tokens = dict() #TODO would be nice to delete these tokens when finished 51 | self.user_ids = dict() # username to user_id mapping 52 | self.uploaded_files = dict() # md5-hash to upload-file response (dict) 53 | 54 | def milestone_by_name(self, project_id, milestone_name): 55 | milestones = self.get("/projects/:project_id/milestones",project_id=project_id) 56 | for milestone in milestones: 57 | if milestone['title'] == milestone_name: 58 | return milestone 59 | 60 | def get_user_id(self, username): 61 | users = self.get("/users") 62 | for user in users: 63 | if user['username'] == username: 64 | return user["id"] 65 | 66 | def project_by_name(self, project_name): 67 | projects = self.get("/projects") 68 | for project in projects: 69 | if project['path_with_namespace'] == project_name: 70 | return project 71 | 72 | def get(self, url_postfix, **keywords): 73 | return self._get(url_postfix, keywords) 74 | 75 | def _request_headers(self, keywords) : 76 | headers = dict() 77 | if 'token' in keywords : 78 | headers['PRIVATE-TOKEN'] = keywords['token'] 79 | else : 80 | headers['PRIVATE-TOKEN'] = self.access_token 81 | return headers 82 | 83 | def _get(self, url_postfix, keywords): 84 | """ 85 | :param url_postfix: e.g. "/projects/:id/issues" 86 | :param keywords: map, e.g. { "id" : 5 } 87 | :return: json of GET 88 | """ 89 | completed_url = self._complete_url(url_postfix, keywords)+"&per_page=50" 90 | r = requests.get(completed_url, verify=self.verify) 91 | json = r.json() 92 | return json 93 | 94 | def put(self, url_postfix, data, **keywords): 95 | completed_url = self._complete_url(url_postfix, keywords) 96 | r = requests.put(completed_url,data= data, verify=self.verify) 97 | j = r.json() 98 | return j 99 | 100 | def post(self, url_postfix, data, **keywords): 101 | completed_url = self._complete_url(url_postfix, keywords) 102 | files = keywords['files'] if 'files' in keywords else None 103 | while True : 104 | r = requests.post(completed_url, data = data, verify = self.verify, files = files) 105 | if r.status_code < 500 : 106 | break 107 | time.sleep(2) 108 | if r.status_code >= 400 : print(r.text) 109 | r.raise_for_status() 110 | j = r.json() if r.status_code >= 200 and r.status_code < 300 else None 111 | return j 112 | 113 | def put_json(self, url_postfix, data, **keywords): 114 | completed_url = self._complete_url(url_postfix, keywords) 115 | payload = json.dumps(data) 116 | r = requests.put(completed_url, data= payload, verify=self.verify) 117 | j = r.json() 118 | return j 119 | 120 | def post_json(self, url_postfix, data, **keywords): 121 | completed_url = self._complete_url(url_postfix, keywords) 122 | payload = json.dumps(data) 123 | r = requests.post(completed_url, data=data, verify=self.verify) 124 | j = r.json() 125 | return j 126 | 127 | def create_issue(self, dest_project_id, new_issue): 128 | if hasattr(new_issue, 'milestone'): 129 | new_issue.milestone_id = new_issue.milestone 130 | if hasattr(new_issue, 'assignee'): 131 | new_issue.assignee_id = new_issue.assignee 132 | new_ticket = self.post_json("/projects/:id/issues", new_issue.__dict__, id=dest_project_id) 133 | new_ticket_id = new_issue.iid 134 | # setting closed in create does not work -- limitation in gitlab 135 | if new_issue.state == 'closed': self.close_issue(dest_project_id,new_ticket_id) 136 | return Issues.create(new_ticket) 137 | 138 | def create_milestone(self, dest_project_id, new_milestone): 139 | if hasattr(new_milestone, 'due_date'): 140 | new_milestone.due_date = new_milestone.due_date.isoformat() 141 | existing = Milestones.create(self.milestone_by_name(dest_project_id, new_milestone.title)) 142 | if existing: 143 | new_milestone.id = existing.id 144 | return Milestones.create(self.put("/projects/:id/milestones/:milestone_id", new_milestone.__dict__, id=dest_project_id, milestone_id=existing.id)) 145 | else: 146 | return Milestones.create(self.post_json("/projects/:id/milestones", new_milestone.__dict__, id=dest_project_id)) 147 | 148 | def create_wiki(self, dest_project_id, content, title, author): 149 | token = self.get_user_imperstoken(author) 150 | new_wiki_data = { 151 | "id" : dest_project_id, 152 | "content" : content, 153 | "title" : title 154 | } 155 | self.post("/projects/:project_id/wikis", new_wiki_data, project_id = dest_project_id, token = token) 156 | 157 | def comment_issue(self ,project_id, ticket, note, binary_attachment): 158 | if hasattr(note, 'attachment_name') : 159 | # ensure file name will be in ascii (otherwise gitlab complain) 160 | origname = note.attachment_name 161 | note.attachment_name = note.attachment_name.encode("ascii", "replace") 162 | r = self.upload_file(project_id, note.author, note.attachment_name, binary_attachment) 163 | relative_path_start_index = r['markdown'].index('/') 164 | relative_path = r['markdown'][:relative_path_start_index] + '..' + r['markdown'][relative_path_start_index:] 165 | note.note = "Attachment added: " + relative_path + '\n\n' + note.note 166 | if origname != note.attachment_name : 167 | note.note += '\nFilename changed during trac to gitlab conversion. Original filename: ' + origname 168 | 169 | new_note_data = { 170 | "id" : project_id, 171 | "issue_id" :ticket.iid, 172 | "body" : note.note 173 | } 174 | self.post_json( "/projects/:project_id/issues/:issue_id/notes", new_note_data, project_id=project_id, issue_id=ticket.iid) 175 | 176 | def get_user_imperstoken(self, userid) : 177 | if userid in self.impers_tokens : 178 | return self.impers_tokens[userid]; 179 | data = { 180 | 'user_id' : userid, 181 | 'name' : 'trac2gitlab', 182 | 'expires_at' : (datetime.date.today() + datetime.timedelta(days = 1)).strftime('%Y-%m-%dT%H:%M:%S.%f'), 183 | 'scopes[]' : 'api' 184 | } 185 | r = self.post_json('/users/:user_id/impersonation_tokens', data, user_id = userid) 186 | self.impers_tokens[userid] = r['token']; 187 | return r['token'] 188 | 189 | def upload_file(self, project_id, author, filename, filedata) : 190 | token = self.get_user_imperstoken(author) 191 | 192 | h = hashlib.md5(filename + filedata).hexdigest() 193 | if h in self.uploaded_files : 194 | print ' use previous upload of file', filename 195 | return self.uploaded_files[h] 196 | 197 | print ' upload file', filename 198 | r = self.post("/projects/:project_id/uploads", None, files = {'file' : (filename, filedata)}, project_id = project_id, token = token) 199 | self.uploaded_files[h] = r; 200 | return r 201 | 202 | def close_issue(self,project_id,ticket_id): 203 | new_note_data = {"state_event": "close"} 204 | self.put("/projects/:project_id/issues/:issue_id", new_note_data, project_id=project_id, issue_id=ticket_id) 205 | 206 | def _complete_url(self, url_postfix, keywords): 207 | url_postfix_with_params = self._url_postfix_with_params(url_postfix, keywords) 208 | complete_url = "%s%s?private_token=%s" % (self.url, url_postfix_with_params, self.access_token) 209 | return complete_url 210 | 211 | def _url_postfix_with_params(self, url_postfix, keywords): 212 | """ 213 | 214 | :param url_postfix: "/projects/:id/issues" 215 | :param keywords: map, e.g. { "id" : 5 } 216 | :return: "/projects/5/issues" 217 | """ 218 | 219 | result = url_postfix 220 | for key, value in keywords.items(): 221 | k = ":" + str(key) 222 | v = str(value) 223 | result = result.replace(k, v) 224 | return result 225 | 226 | ''' 227 | This file is part of . 228 | 229 | This sotfware is free software: you can redistribute it and/or modify 230 | it under the terms of the GNU Lesser General Public License as published by 231 | the Free Software Foundation, either version 3 of the License, or 232 | (at your option) any later version. 233 | 234 | This sotfware is distributed in the hope that it will be useful, 235 | but WITHOUT ANY WARRANTY; without even the implied warranty of 236 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 237 | GNU Lesser General Public License for more details. 238 | 239 | You should have received a copy of the GNU Lesser General Public License 240 | along with this library. If not, see . 241 | ''' 242 | -------------------------------------------------------------------------------- /gitlab_api/__init__.py: -------------------------------------------------------------------------------- 1 | from .Connection import Connection, Issues, Notes, Milestones 2 | -------------------------------------------------------------------------------- /gitlab_direct/Connection.py: -------------------------------------------------------------------------------- 1 | # vim: autoindent tabstop=4 shiftwidth=4 expandtab softtabstop=4 filetype=python fileencoding=utf-8 2 | ''' 3 | Copyright © 2013 - 2017 4 | Eric van der Vlist 5 | Jens Neuhalfen 6 | See license information at the bottom of this file 7 | ''' 8 | 9 | 10 | from peewee import PostgresqlDatabase 11 | from .model import * 12 | import os 13 | import shutil 14 | from datetime import datetime 15 | from io import open 16 | 17 | 18 | class Connection(object): 19 | """ 20 | Connection to the gitlab database 21 | """ 22 | 23 | def __init__(self, db_name, db_user, db_password, db_path, uploads_path): 24 | """ 25 | """ 26 | db = PostgresqlDatabase(db_name, user= db_user, host=db_path) 27 | database_proxy.initialize(db) 28 | self.uploads_path = uploads_path 29 | 30 | def clear_issues(self, project_id): 31 | 32 | # Delete all the uses of the labels of the project. 33 | for label in Labels.select().where( Labels.project == project_id ): 34 | LabelLinks.delete().where( LabelLinks.label == label.id ).execute() 35 | ## You probably do not want to delete the labels themselves, otherwise you'd need to 36 | ## set their colour every time when you re-run the migration. 37 | #label.delete_instance() 38 | 39 | # Delete issues and everything that goes with them... 40 | for issue in Issues.select().where(Issues.project == project_id): 41 | for note in Notes.select().where( (Notes.project == project_id) & (Notes.noteable_type == 'Issue') & (Notes.noteable == issue.id)): 42 | if note.attachment != None: 43 | directory = os.path.join(self.uploads_path, 'note/attachment/%s' % note.id) 44 | try: 45 | shutil.rmtree(directory) 46 | except: 47 | pass 48 | Events.delete().where( (Events.project == project_id) & (Events.target_type == 'Note' ) & (Events.target == note.id) ).execute() 49 | note.delete_instance() 50 | 51 | Events.delete().where( (Events.project == project_id) & (Events.target_type == 'Issue' ) & (Events.target == issue.id) ).execute() 52 | issue.delete_instance() 53 | 54 | Milestones.delete().where( Milestones.project == project_id ).execute() 55 | 56 | def clear_wiki_attachments(self, project_id): 57 | for note in Notes.select().where( (Notes.project == project_id) & (Notes.noteable_type >> None) & (Notes.note % 'Wiki attachment %')): 58 | directory = os.path.join(self.uploads_path, 'note/attachment/%s' % note.id) 59 | try: 60 | shutil.rmtree(directory) 61 | except: 62 | pass 63 | Events.delete().where( (Events.project == project_id) & (Events.target_type == 'Note' ) & (Events.target == note.id) ).execute() 64 | note.delete_instance() 65 | 66 | def milestone_by_name(self, project_id, milestone_name): 67 | for milestone in Milestones.select().where((Milestones.title == milestone_name) & (Milestones.project == project_id)): 68 | return milestone._data 69 | return None 70 | 71 | def project_by_name(self, project_name): 72 | (namespace, name) = project_name.split('/') 73 | print(name) 74 | for project in Projects.select().join(Namespaces, on=(Projects.namespace == Namespaces.id )).where((Projects.path == name) & (Namespaces.path == namespace)): 75 | print(project._data) 76 | return project._data 77 | return None 78 | 79 | def get_user_id(self, username): 80 | return Users.get(Users.username == username).id 81 | 82 | def get_issues_iid(self, dest_project_id): 83 | return Issues.select().where(Issues.project == dest_project_id).aggregate(fn.Count(Issues.id)) + 1 84 | 85 | def create_milestone(self, dest_project_id, new_milestone): 86 | try: 87 | existing = Milestones.get((Milestones.title == new_milestone.title) & (Milestones.project == dest_project_id)) 88 | for k in new_milestone._data: 89 | if (k not in ('id', 'iid')): 90 | existing._data[k] = new_milestone._data[k] 91 | new_milestone = existing 92 | except: 93 | new_milestone.iid = Milestones.select().where(Milestones.project == dest_project_id).aggregate(fn.Count(Milestones.id)) + 1 94 | new_milestone.created_at = datetime.now() 95 | new_milestone.updated_at = datetime.now() 96 | new_milestone.save() 97 | return new_milestone 98 | 99 | 100 | def create_issue(self, dest_project_id, new_issue): 101 | new_issue.save() 102 | event = Events.create( 103 | action = 1, 104 | author = new_issue.author, 105 | created_at = new_issue.created_at, 106 | project = dest_project_id, 107 | target = new_issue.id, 108 | target_type = 'Issue', 109 | updated_at = new_issue.created_at 110 | ) 111 | event.save() 112 | for title in set(new_issue.labels.split(',')): 113 | if (title == ''): 114 | continue 115 | try: 116 | label = Labels.get((Labels.title == title) & (Labels.project == dest_project_id)) 117 | except: 118 | label = Labels.create( 119 | title = title, 120 | color = '#0000FF', 121 | project = dest_project_id, 122 | type = 'ProjectLabel', 123 | created_at = new_issue.created_at, 124 | update_at = new_issue.created_at 125 | ) 126 | label.save() 127 | label_link = LabelLinks.create( 128 | label = label.id, 129 | target = new_issue.id, 130 | target_type = 'Issue', 131 | created_at = new_issue.created_at, 132 | update_at = new_issue.created_at 133 | ) 134 | label_link.save() 135 | return new_issue 136 | 137 | def comment_issue(self ,project_id, ticket, note, binary_attachment): 138 | note.project = project_id 139 | note.noteable = ticket.id 140 | note.noteable_type = 'Issue' 141 | note.save() 142 | 143 | if binary_attachment: 144 | directory = os.path.join(self.uploads_path, 'note/attachment/%s' % note.id) 145 | if not os.path.exists(directory): 146 | os.makedirs(directory) 147 | path = os.path.join(directory, note.attachment) 148 | file = open(path.encode('utf-8'),"wb") 149 | file.write(binary_attachment) 150 | file.close() 151 | 152 | event = Events.create( 153 | action = 1, 154 | author = note.author, 155 | created_at = note.created_at, 156 | project = project_id, 157 | target = note.id, 158 | target_type = 'Note', 159 | updated_at = note.created_at 160 | ) 161 | event.save() 162 | 163 | def create_wiki_attachment(self, project_id, user, last_modified, path, binary): 164 | note = Notes.create( 165 | project = project_id, 166 | note = 'Wiki attachment %s' % path, 167 | user = user, 168 | created_at = last_modified, 169 | updated_at = last_modified, 170 | attachment = path 171 | ) 172 | note.save() 173 | full_path = os.path.join(self.uploads_path, 'note/attachment/%s' % note.id, path) 174 | directory = os.path.dirname(full_path) 175 | if not os.path.exists(directory): 176 | os.makedirs(directory) 177 | file = open(full_path,"wb") 178 | file.write(binary) 179 | file.close() 180 | 181 | event = Events.create( 182 | action = 1, 183 | author = note.author, 184 | created_at = note.created_at, 185 | project = project_id, 186 | target = note.id, 187 | target_type = 'Note', 188 | updated_at = note.created_at 189 | ) 190 | event.save() 191 | 192 | return '/files/note/%s/%s' % (note.id, path) 193 | 194 | ''' 195 | This file is part of . 196 | 197 | This sotfware is free software: you can redistribute it and/or modify 198 | it under the terms of the GNU Lesser General Public License as published by 199 | the Free Software Foundation, either version 3 of the License, or 200 | (at your option) any later version. 201 | 202 | This sotfware is distributed in the hope that it will be useful, 203 | but WITHOUT ANY WARRANTY; without even the implied warranty of 204 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 205 | GNU Lesser General Public License for more details. 206 | 207 | You should have received a copy of the GNU Lesser General Public License 208 | along with this library. If not, see . 209 | ''' 210 | -------------------------------------------------------------------------------- /gitlab_direct/__init__.py: -------------------------------------------------------------------------------- 1 | from .Connection import Connection 2 | from .model import Issues, Notes, Milestones 3 | -------------------------------------------------------------------------------- /gitlab_direct/model.py: -------------------------------------------------------------------------------- 1 | # proxy class to import current scheme 2 | 3 | import os 4 | import importlib 5 | try: 6 | version = os.environ['MODEL_VERSION'] 7 | except KeyError: 8 | version = '90' 9 | 10 | exec "from .model%s import *" % version 11 | -------------------------------------------------------------------------------- /gitlab_direct/model84.py: -------------------------------------------------------------------------------- 1 | from peewee import * 2 | 3 | database_proxy = Proxy() 4 | 5 | class UnknownField(object): 6 | pass 7 | 8 | class BaseModel(Model): 9 | class Meta: 10 | database = database_proxy 11 | 12 | class AbuseReports(BaseModel): 13 | created_at = DateTimeField(null=True) 14 | message = TextField(null=True) 15 | reporter = IntegerField(db_column='reporter_id', null=True) 16 | updated_at = DateTimeField(null=True) 17 | user = IntegerField(db_column='user_id', null=True) 18 | 19 | class Meta: 20 | db_table = 'abuse_reports' 21 | 22 | class ApplicationSettings(BaseModel): 23 | admin_notification_email = CharField(null=True) 24 | after_sign_out_path = CharField(null=True) 25 | created_at = DateTimeField(null=True) 26 | default_branch_protection = IntegerField(null=True) 27 | default_project_visibility = IntegerField(null=True) 28 | default_projects_limit = IntegerField(null=True) 29 | default_snippet_visibility = IntegerField(null=True) 30 | dnsbl_servers_list = TextField(null=True) 31 | gravatar_enabled = BooleanField(null=True) 32 | help_page_text = TextField(null=True) 33 | home_page_url = CharField(null=True) 34 | import_sources = TextField(null=True) 35 | ip_blocking_enabled = BooleanField(null=True) 36 | max_artifacts_size = IntegerField() 37 | max_attachment_size = IntegerField() 38 | metrics_enabled = BooleanField(null=True) 39 | metrics_host = CharField(null=True) 40 | metrics_method_call_threshold = IntegerField(null=True) 41 | metrics_pool_size = IntegerField(null=True) 42 | metrics_port = IntegerField(null=True) 43 | metrics_sample_interval = IntegerField(null=True) 44 | metrics_timeout = IntegerField(null=True) 45 | recaptcha_enabled = BooleanField(null=True) 46 | recaptcha_private_key = CharField(null=True) 47 | recaptcha_site_key = CharField(null=True) 48 | require_two_factor_authentication = BooleanField(null=True) 49 | restricted_signup_domains = TextField(null=True) 50 | restricted_visibility_levels = TextField(null=True) 51 | runners_registration_token = CharField(null=True) 52 | sentry_dsn = CharField(null=True) 53 | sentry_enabled = BooleanField(null=True) 54 | session_expire_delay = IntegerField() 55 | shared_runners_enabled = BooleanField() 56 | sign_in_text = TextField(null=True) 57 | signin_enabled = BooleanField(null=True) 58 | signup_enabled = BooleanField(null=True) 59 | twitter_sharing_enabled = BooleanField(null=True) 60 | two_factor_grace_period = IntegerField(null=True) 61 | updated_at = DateTimeField(null=True) 62 | user_oauth_applications = BooleanField(null=True) 63 | version_check_enabled = BooleanField(null=True) 64 | 65 | class Meta: 66 | db_table = 'application_settings' 67 | 68 | class AuditEvents(BaseModel): 69 | author = IntegerField(db_column='author_id', index=True) 70 | created_at = DateTimeField(null=True) 71 | details = TextField(null=True) 72 | entity = IntegerField(db_column='entity_id') 73 | entity_type = CharField() 74 | type = CharField(index=True) 75 | updated_at = DateTimeField(null=True) 76 | 77 | class Meta: 78 | db_table = 'audit_events' 79 | indexes = ( 80 | (('entity', 'entity_type'), False), 81 | ) 82 | 83 | class BroadcastMessages(BaseModel): 84 | color = CharField(null=True) 85 | created_at = DateTimeField(null=True) 86 | ends_at = DateTimeField(null=True) 87 | font = CharField(null=True) 88 | message = TextField() 89 | starts_at = DateTimeField(null=True) 90 | updated_at = DateTimeField(null=True) 91 | 92 | class Meta: 93 | db_table = 'broadcast_messages' 94 | 95 | class CiApplicationSettings(BaseModel): 96 | add_pusher = BooleanField(null=True) 97 | all_broken_builds = BooleanField(null=True) 98 | created_at = DateTimeField(null=True) 99 | updated_at = DateTimeField(null=True) 100 | 101 | class Meta: 102 | db_table = 'ci_application_settings' 103 | 104 | class CiBuilds(BaseModel): 105 | allow_failure = BooleanField() 106 | artifacts_file = TextField(null=True) 107 | artifacts_metadata = TextField(null=True) 108 | commands = TextField(null=True) 109 | commit = IntegerField(db_column='commit_id', index=True, null=True) 110 | coverage = FloatField(null=True) 111 | created_at = DateTimeField(null=True) 112 | deploy = BooleanField(null=True) 113 | description = CharField(null=True) 114 | finished_at = DateTimeField(null=True) 115 | gl_project = IntegerField(db_column='gl_project_id', index=True, null=True) 116 | job = IntegerField(db_column='job_id', null=True) 117 | name = CharField(null=True) 118 | options = TextField(null=True) 119 | project = IntegerField(db_column='project_id', index=True, null=True) 120 | ref = CharField(null=True) 121 | runner = IntegerField(db_column='runner_id', index=True, null=True) 122 | stage = CharField(null=True) 123 | stage_idx = IntegerField(null=True) 124 | started_at = DateTimeField(null=True) 125 | status = CharField(index=True, null=True) 126 | tag = BooleanField(null=True) 127 | target_url = CharField(null=True) 128 | trace = TextField(null=True) 129 | trigger_request = IntegerField(db_column='trigger_request_id', null=True) 130 | type = CharField(index=True, null=True) 131 | updated_at = DateTimeField(null=True) 132 | user = IntegerField(db_column='user_id', null=True) 133 | 134 | class Meta: 135 | db_table = 'ci_builds' 136 | indexes = ( 137 | (('commit', 'created_at', 'stage_idx'), False), 138 | (('commit', 'name', 'ref', 'type'), False), 139 | (('commit', 'project'), False), 140 | (('type', 'commit', 'status'), False), 141 | (('type', 'ref', 'commit'), False), 142 | ) 143 | 144 | class CiCommits(BaseModel): 145 | before_sha = CharField(null=True) 146 | committed_at = DateTimeField(null=True) 147 | created_at = DateTimeField(null=True) 148 | gl_project = IntegerField(db_column='gl_project_id', index=True, null=True) 149 | project = IntegerField(db_column='project_id', index=True, null=True) 150 | push_data = TextField(null=True) 151 | ref = CharField(null=True) 152 | sha = CharField(index=True, null=True) 153 | tag = BooleanField(null=True) 154 | updated_at = DateTimeField(null=True) 155 | yaml_errors = TextField(null=True) 156 | 157 | class Meta: 158 | db_table = 'ci_commits' 159 | indexes = ( 160 | (('committed_at', 'project'), False), 161 | (('id', 'project', 'committed_at'), False), 162 | (('sha', 'project'), False), 163 | ) 164 | 165 | class CiEvents(BaseModel): 166 | created_at = DateTimeField(index=True, null=True) 167 | description = TextField(null=True) 168 | is_admin = IntegerField(index=True, null=True) 169 | project = IntegerField(db_column='project_id', index=True, null=True) 170 | updated_at = DateTimeField(null=True) 171 | user = IntegerField(db_column='user_id', null=True) 172 | 173 | class Meta: 174 | db_table = 'ci_events' 175 | 176 | class CiJobs(BaseModel): 177 | active = BooleanField() 178 | build_branches = BooleanField() 179 | build_tags = BooleanField() 180 | commands = TextField(null=True) 181 | created_at = DateTimeField(null=True) 182 | deleted_at = DateTimeField(index=True, null=True) 183 | job_type = CharField(null=True) 184 | name = CharField(null=True) 185 | project = IntegerField(db_column='project_id', index=True) 186 | refs = CharField(null=True) 187 | updated_at = DateTimeField(null=True) 188 | 189 | class Meta: 190 | db_table = 'ci_jobs' 191 | 192 | class CiProjects(BaseModel): 193 | allow_git_fetch = BooleanField() 194 | always_build = BooleanField() 195 | coverage_regex = CharField(null=True) 196 | created_at = DateTimeField(null=True) 197 | default_ref = CharField(null=True) 198 | email_add_pusher = BooleanField() 199 | email_only_broken_builds = BooleanField() 200 | email_recipients = CharField() 201 | generated_yaml_config = TextField(null=True) 202 | gitlab = IntegerField(db_column='gitlab_id', index=True, null=True) 203 | name = CharField(null=True) 204 | path = CharField(null=True) 205 | polling_interval = IntegerField(null=True) 206 | public = BooleanField() 207 | shared_runners_enabled = BooleanField(index=True, null=True) 208 | skip_refs = CharField(null=True) 209 | ssh_url_to_repo = CharField(null=True) 210 | timeout = IntegerField() 211 | token = CharField(null=True) 212 | updated_at = DateTimeField(null=True) 213 | 214 | class Meta: 215 | db_table = 'ci_projects' 216 | 217 | class CiRunnerProjects(BaseModel): 218 | created_at = DateTimeField(null=True) 219 | gl_project = IntegerField(db_column='gl_project_id', index=True, null=True) 220 | project = IntegerField(db_column='project_id', null=True) 221 | runner = IntegerField(db_column='runner_id', index=True) 222 | updated_at = DateTimeField(null=True) 223 | 224 | class Meta: 225 | db_table = 'ci_runner_projects' 226 | 227 | class CiRunners(BaseModel): 228 | active = BooleanField() 229 | architecture = CharField(null=True) 230 | contacted_at = DateTimeField(null=True) 231 | created_at = DateTimeField(null=True) 232 | description = CharField(null=True) 233 | is_shared = BooleanField(null=True) 234 | name = CharField(null=True) 235 | platform = CharField(null=True) 236 | revision = CharField(null=True) 237 | token = CharField(null=True) 238 | updated_at = DateTimeField(null=True) 239 | version = CharField(null=True) 240 | 241 | class Meta: 242 | db_table = 'ci_runners' 243 | 244 | class CiServices(BaseModel): 245 | active = BooleanField() 246 | created_at = DateTimeField(null=True) 247 | project = IntegerField(db_column='project_id', index=True) 248 | properties = TextField(null=True) 249 | title = CharField(null=True) 250 | type = CharField(null=True) 251 | updated_at = DateTimeField(null=True) 252 | 253 | class Meta: 254 | db_table = 'ci_services' 255 | 256 | class CiSessions(BaseModel): 257 | created_at = DateTimeField(null=True) 258 | data = TextField(null=True) 259 | session = CharField(db_column='session_id', index=True) 260 | updated_at = DateTimeField(index=True, null=True) 261 | 262 | class Meta: 263 | db_table = 'ci_sessions' 264 | 265 | class CiTaggings(BaseModel): 266 | context = CharField(null=True) 267 | created_at = DateTimeField(null=True) 268 | tag = IntegerField(db_column='tag_id', null=True) 269 | taggable = IntegerField(db_column='taggable_id', null=True) 270 | taggable_type = CharField(null=True) 271 | tagger = IntegerField(db_column='tagger_id', null=True) 272 | tagger_type = CharField(null=True) 273 | 274 | class Meta: 275 | db_table = 'ci_taggings' 276 | indexes = ( 277 | (('context', 'taggable_type', 'taggable'), False), 278 | (('tagger', 'context', 'tagger_type', 'tag', 'taggable', 'taggable_type'), True), 279 | ) 280 | 281 | class CiTags(BaseModel): 282 | name = CharField(null=True, unique=True) 283 | taggings_count = IntegerField(null=True) 284 | 285 | class Meta: 286 | db_table = 'ci_tags' 287 | 288 | class CiTriggerRequests(BaseModel): 289 | commit = IntegerField(db_column='commit_id', null=True) 290 | created_at = DateTimeField(null=True) 291 | trigger = IntegerField(db_column='trigger_id') 292 | updated_at = DateTimeField(null=True) 293 | variables = TextField(null=True) 294 | 295 | class Meta: 296 | db_table = 'ci_trigger_requests' 297 | 298 | class CiTriggers(BaseModel): 299 | created_at = DateTimeField(null=True) 300 | deleted_at = DateTimeField(index=True, null=True) 301 | gl_project = IntegerField(db_column='gl_project_id', index=True, null=True) 302 | project = IntegerField(db_column='project_id', null=True) 303 | token = CharField(null=True) 304 | updated_at = DateTimeField(null=True) 305 | 306 | class Meta: 307 | db_table = 'ci_triggers' 308 | 309 | class CiVariables(BaseModel): 310 | encrypted_value = TextField(null=True) 311 | encrypted_value_iv = CharField(null=True) 312 | encrypted_value_salt = CharField(null=True) 313 | gl_project = IntegerField(db_column='gl_project_id', index=True, null=True) 314 | key = CharField(null=True) 315 | project = IntegerField(db_column='project_id', null=True) 316 | value = TextField(null=True) 317 | 318 | class Meta: 319 | db_table = 'ci_variables' 320 | 321 | class CiWebHooks(BaseModel): 322 | created_at = DateTimeField(null=True) 323 | project = IntegerField(db_column='project_id') 324 | updated_at = DateTimeField(null=True) 325 | url = CharField() 326 | 327 | class Meta: 328 | db_table = 'ci_web_hooks' 329 | 330 | class DeployKeysProjects(BaseModel): 331 | created_at = DateTimeField(null=True) 332 | deploy_key = IntegerField(db_column='deploy_key_id') 333 | project = IntegerField(db_column='project_id', index=True) 334 | updated_at = DateTimeField(null=True) 335 | 336 | class Meta: 337 | db_table = 'deploy_keys_projects' 338 | 339 | class Emails(BaseModel): 340 | created_at = DateTimeField(null=True) 341 | email = CharField(unique=True) 342 | updated_at = DateTimeField(null=True) 343 | user = IntegerField(db_column='user_id', index=True) 344 | 345 | class Meta: 346 | db_table = 'emails' 347 | 348 | class Events(BaseModel): 349 | action = IntegerField(index=True, null=True) 350 | author = IntegerField(db_column='author_id', index=True, null=True) 351 | created_at = DateTimeField(index=True, null=True) 352 | data = TextField(null=True) 353 | project = IntegerField(db_column='project_id', index=True, null=True) 354 | target = IntegerField(db_column='target_id', index=True, null=True) 355 | target_type = CharField(index=True, null=True) 356 | title = CharField(null=True) 357 | updated_at = DateTimeField(null=True) 358 | 359 | class Meta: 360 | db_table = 'events' 361 | 362 | class ForkedProjectLinks(BaseModel): 363 | created_at = DateTimeField(null=True) 364 | forked_from_project = IntegerField(db_column='forked_from_project_id') 365 | forked_to_project = IntegerField(db_column='forked_to_project_id', unique=True) 366 | updated_at = DateTimeField(null=True) 367 | 368 | class Meta: 369 | db_table = 'forked_project_links' 370 | 371 | class Identities(BaseModel): 372 | created_at = DateTimeField(null=True) 373 | extern_uid = CharField(null=True) 374 | provider = CharField(null=True) 375 | updated_at = DateTimeField(null=True) 376 | user = IntegerField(db_column='user_id', index=True, null=True) 377 | 378 | class Meta: 379 | db_table = 'identities' 380 | indexes = ( 381 | (('id', 'created_at'), False), 382 | ) 383 | 384 | class Issues(BaseModel): 385 | assignee = IntegerField(db_column='assignee_id', index=True, null=True) 386 | author = IntegerField(db_column='author_id', index=True, null=True) 387 | branch_name = CharField(null=True) 388 | created_at = DateTimeField(index=True, null=True) 389 | description = TextField(null=True) 390 | iid = IntegerField(null=True) 391 | milestone = IntegerField(db_column='milestone_id', index=True, null=True) 392 | position = IntegerField(null=True) 393 | project = IntegerField(db_column='project_id', index=True, null=True) 394 | state = CharField(index=True, null=True) 395 | title = CharField(index=True, null=True) 396 | updated_at = DateTimeField(null=True) 397 | updated_by = IntegerField(db_column='updated_by_id', null=True) 398 | 399 | class Meta: 400 | db_table = 'issues' 401 | indexes = ( 402 | (('id', 'created_at'), False), 403 | (('project', 'iid'), True), 404 | ) 405 | 406 | class Keys(BaseModel): 407 | created_at = DateTimeField(null=True) 408 | fingerprint = CharField(null=True) 409 | key = TextField(null=True) 410 | public = BooleanField() 411 | title = CharField(null=True) 412 | type = CharField(null=True) 413 | updated_at = DateTimeField(null=True) 414 | user = IntegerField(db_column='user_id', index=True, null=True) 415 | 416 | class Meta: 417 | db_table = 'keys' 418 | indexes = ( 419 | (('id', 'created_at'), False), 420 | ) 421 | 422 | class LabelLinks(BaseModel): 423 | created_at = DateTimeField(null=True) 424 | label = IntegerField(db_column='label_id', index=True, null=True) 425 | target = IntegerField(db_column='target_id', null=True) 426 | target_type = CharField(null=True) 427 | updated_at = DateTimeField(null=True) 428 | 429 | class Meta: 430 | db_table = 'label_links' 431 | indexes = ( 432 | (('target', 'target_type'), False), 433 | ) 434 | 435 | class Labels(BaseModel): 436 | color = CharField(null=True) 437 | created_at = DateTimeField(null=True) 438 | project = IntegerField(db_column='project_id', index=True, null=True) 439 | template = BooleanField(null=True) 440 | title = CharField(null=True) 441 | updated_at = DateTimeField(null=True) 442 | 443 | class Meta: 444 | db_table = 'labels' 445 | 446 | class LfsObjects(BaseModel): 447 | created_at = DateTimeField(null=True) 448 | file = CharField(null=True) 449 | oid = CharField(unique=True) 450 | size = IntegerField() 451 | updated_at = DateTimeField(null=True) 452 | 453 | class Meta: 454 | db_table = 'lfs_objects' 455 | 456 | class LfsObjectsProjects(BaseModel): 457 | created_at = DateTimeField(null=True) 458 | lfs_object = IntegerField(db_column='lfs_object_id') 459 | project = IntegerField(db_column='project_id', index=True) 460 | updated_at = DateTimeField(null=True) 461 | 462 | class Meta: 463 | db_table = 'lfs_objects_projects' 464 | 465 | class Members(BaseModel): 466 | access_level = IntegerField(index=True) 467 | created_at = DateTimeField(null=True) 468 | created_by = IntegerField(db_column='created_by_id', null=True) 469 | invite_accepted_at = DateTimeField(null=True) 470 | invite_email = CharField(null=True) 471 | invite_token = CharField(null=True, unique=True) 472 | notification_level = IntegerField() 473 | source = IntegerField(db_column='source_id') 474 | source_type = CharField() 475 | type = CharField(index=True, null=True) 476 | updated_at = DateTimeField(null=True) 477 | user = IntegerField(db_column='user_id', index=True, null=True) 478 | 479 | class Meta: 480 | db_table = 'members' 481 | indexes = ( 482 | (('id', 'created_at'), False), 483 | (('source', 'source_type'), False), 484 | ) 485 | 486 | class MergeRequestDiffs(BaseModel): 487 | base_commit_sha = CharField(null=True) 488 | created_at = DateTimeField(null=True) 489 | merge_request = IntegerField(db_column='merge_request_id', unique=True) 490 | st_commits = TextField(null=True) 491 | st_diffs = TextField(null=True) 492 | state = CharField(null=True) 493 | updated_at = DateTimeField(null=True) 494 | 495 | class Meta: 496 | db_table = 'merge_request_diffs' 497 | 498 | class MergeRequests(BaseModel): 499 | assignee = IntegerField(db_column='assignee_id', index=True, null=True) 500 | author = IntegerField(db_column='author_id', index=True, null=True) 501 | created_at = DateTimeField(index=True, null=True) 502 | description = TextField(null=True) 503 | iid = IntegerField(null=True) 504 | locked_at = DateTimeField(null=True) 505 | merge_error = CharField(null=True) 506 | merge_params = TextField(null=True) 507 | merge_status = CharField(null=True) 508 | merge_user = IntegerField(db_column='merge_user_id', null=True) 509 | merge_when_build_succeeds = BooleanField() 510 | milestone = IntegerField(db_column='milestone_id', index=True, null=True) 511 | position = IntegerField(null=True) 512 | source_branch = CharField(index=True) 513 | source_project = IntegerField(db_column='source_project_id', index=True) 514 | state = CharField(null=True) 515 | target_branch = CharField(index=True) 516 | target_project = IntegerField(db_column='target_project_id') 517 | title = CharField(index=True, null=True) 518 | updated_at = DateTimeField(null=True) 519 | updated_by = IntegerField(db_column='updated_by_id', null=True) 520 | 521 | class Meta: 522 | db_table = 'merge_requests' 523 | indexes = ( 524 | (('created_at', 'id'), False), 525 | (('target_project', 'iid'), True), 526 | ) 527 | 528 | class Milestones(BaseModel): 529 | created_at = DateTimeField(null=True) 530 | description = TextField(null=True) 531 | due_date = DateField(index=True, null=True) 532 | iid = IntegerField(null=True) 533 | project = IntegerField(db_column='project_id', index=True) 534 | state = CharField(null=True) 535 | title = CharField(index=True) 536 | updated_at = DateTimeField(null=True) 537 | 538 | class Meta: 539 | db_table = 'milestones' 540 | indexes = ( 541 | (('id', 'created_at'), False), 542 | (('project', 'iid'), True), 543 | ) 544 | 545 | class Namespaces(BaseModel): 546 | avatar = CharField(null=True) 547 | created_at = DateTimeField(null=True) 548 | description = CharField() 549 | name = CharField(unique=True) 550 | owner = IntegerField(db_column='owner_id', index=True, null=True) 551 | path = CharField(unique=True) 552 | type = CharField(index=True, null=True) 553 | updated_at = DateTimeField(null=True) 554 | 555 | class Meta: 556 | db_table = 'namespaces' 557 | indexes = ( 558 | (('id', 'created_at'), False), 559 | ) 560 | 561 | class Notes(BaseModel): 562 | attachment = CharField(null=True) 563 | author = IntegerField(db_column='author_id', index=True, null=True) 564 | commit = CharField(db_column='commit_id', index=True, null=True) 565 | created_at = DateTimeField(index=True, null=True) 566 | is_award = BooleanField(index=True) 567 | line_code = CharField(index=True, null=True) 568 | note = TextField(null=True) 569 | noteable = IntegerField(db_column='noteable_id', null=True) 570 | noteable_type = CharField(index=True, null=True) 571 | project = IntegerField(db_column='project_id', index=True, null=True) 572 | st_diff = TextField(null=True) 573 | system = BooleanField() 574 | updated_at = DateTimeField(index=True, null=True) 575 | updated_by = IntegerField(db_column='updated_by_id', null=True) 576 | 577 | class Meta: 578 | db_table = 'notes' 579 | indexes = ( 580 | (('created_at', 'id'), False), 581 | (('noteable_type', 'noteable'), False), 582 | (('project', 'noteable_type'), False), 583 | ) 584 | 585 | class OauthAccessGrants(BaseModel): 586 | application = IntegerField(db_column='application_id') 587 | created_at = DateTimeField() 588 | expires_in = IntegerField() 589 | redirect_uri = TextField() 590 | resource_owner = IntegerField(db_column='resource_owner_id') 591 | revoked_at = DateTimeField(null=True) 592 | scopes = CharField(null=True) 593 | token = CharField(unique=True) 594 | 595 | class Meta: 596 | db_table = 'oauth_access_grants' 597 | 598 | class OauthAccessTokens(BaseModel): 599 | application = IntegerField(db_column='application_id', null=True) 600 | created_at = DateTimeField() 601 | expires_in = IntegerField(null=True) 602 | refresh_token = CharField(null=True, unique=True) 603 | resource_owner = IntegerField(db_column='resource_owner_id', index=True, null=True) 604 | revoked_at = DateTimeField(null=True) 605 | scopes = CharField(null=True) 606 | token = CharField(unique=True) 607 | 608 | class Meta: 609 | db_table = 'oauth_access_tokens' 610 | 611 | class OauthApplications(BaseModel): 612 | created_at = DateTimeField(null=True) 613 | name = CharField() 614 | owner = IntegerField(db_column='owner_id', null=True) 615 | owner_type = CharField(null=True) 616 | redirect_uri = TextField() 617 | scopes = CharField() 618 | secret = CharField() 619 | uid = CharField(unique=True) 620 | updated_at = DateTimeField(null=True) 621 | 622 | class Meta: 623 | db_table = 'oauth_applications' 624 | indexes = ( 625 | (('owner', 'owner_type'), False), 626 | ) 627 | 628 | class ProjectImportData(BaseModel): 629 | data = TextField(null=True) 630 | project = IntegerField(db_column='project_id', null=True) 631 | 632 | class Meta: 633 | db_table = 'project_import_data' 634 | 635 | class Projects(BaseModel): 636 | archived = BooleanField() 637 | avatar = CharField(null=True) 638 | build_allow_git_fetch = BooleanField() 639 | build_coverage_regex = CharField(null=True) 640 | build_timeout = IntegerField() 641 | builds_enabled = BooleanField(index=True) 642 | ci = IntegerField(db_column='ci_id', index=True, null=True) 643 | commit_count = IntegerField(null=True) 644 | created_at = DateTimeField(null=True) 645 | creator = IntegerField(db_column='creator_id', index=True, null=True) 646 | description = TextField(null=True) 647 | import_error = TextField(null=True) 648 | import_source = CharField(null=True) 649 | import_status = CharField(null=True) 650 | import_type = CharField(null=True) 651 | import_url = CharField(null=True) 652 | issues_enabled = BooleanField() 653 | issues_tracker = CharField() 654 | issues_tracker_id = CharField(null=True) 655 | last_activity_at = DateTimeField(index=True, null=True) 656 | merge_requests_enabled = BooleanField() 657 | name = CharField(null=True) 658 | namespace = IntegerField(db_column='namespace_id', index=True, null=True) 659 | path = CharField(index=True, null=True) 660 | repository_size = FloatField(null=True) 661 | runners_token = CharField(index=True, null=True) 662 | shared_runners_enabled = BooleanField() 663 | snippets_enabled = BooleanField() 664 | star_count = IntegerField(index=True) 665 | updated_at = DateTimeField(null=True) 666 | visibility_level = IntegerField(index=True) 667 | wall_enabled = BooleanField() 668 | wiki_enabled = BooleanField() 669 | 670 | class Meta: 671 | db_table = 'projects' 672 | indexes = ( 673 | (('id', 'created_at'), False), 674 | (('shared_runners_enabled', 'builds_enabled'), False), 675 | ) 676 | 677 | class ProtectedBranches(BaseModel): 678 | created_at = DateTimeField(null=True) 679 | developers_can_push = BooleanField() 680 | name = CharField() 681 | project = IntegerField(db_column='project_id', index=True) 682 | updated_at = DateTimeField(null=True) 683 | 684 | class Meta: 685 | db_table = 'protected_branches' 686 | 687 | class Releases(BaseModel): 688 | created_at = DateTimeField(null=True) 689 | description = TextField(null=True) 690 | project = IntegerField(db_column='project_id', index=True, null=True) 691 | tag = CharField(null=True) 692 | updated_at = DateTimeField(null=True) 693 | 694 | class Meta: 695 | db_table = 'releases' 696 | indexes = ( 697 | (('tag', 'project'), False), 698 | ) 699 | 700 | class SchemaMigrations(BaseModel): 701 | version = CharField(unique=True) 702 | 703 | class Meta: 704 | db_table = 'schema_migrations' 705 | 706 | class SentNotifications(BaseModel): 707 | commit = CharField(db_column='commit_id', null=True) 708 | line_code = CharField(null=True) 709 | noteable = IntegerField(db_column='noteable_id', null=True) 710 | noteable_type = CharField(null=True) 711 | project = IntegerField(db_column='project_id', null=True) 712 | recipient = IntegerField(db_column='recipient_id', null=True) 713 | reply_key = CharField(unique=True) 714 | 715 | class Meta: 716 | db_table = 'sent_notifications' 717 | 718 | class Services(BaseModel): 719 | active = BooleanField() 720 | build_events = BooleanField() 721 | category = CharField(index=True) 722 | created_at = DateTimeField(null=True) 723 | default = BooleanField(index=True, null=True) 724 | issues_events = BooleanField(null=True) 725 | merge_requests_events = BooleanField(null=True) 726 | note_events = BooleanField() 727 | project = IntegerField(db_column='project_id', index=True, null=True) 728 | properties = TextField(null=True) 729 | push_events = BooleanField(null=True) 730 | tag_push_events = BooleanField(null=True) 731 | template = BooleanField(index=True, null=True) 732 | title = CharField(null=True) 733 | type = CharField(null=True) 734 | updated_at = DateTimeField(null=True) 735 | 736 | class Meta: 737 | db_table = 'services' 738 | indexes = ( 739 | (('created_at', 'id'), False), 740 | ) 741 | 742 | class Snippets(BaseModel): 743 | author = IntegerField(db_column='author_id', index=True) 744 | content = TextField(null=True) 745 | created_at = DateTimeField(index=True, null=True) 746 | expires_at = DateTimeField(index=True, null=True) 747 | file_name = CharField(null=True) 748 | project = IntegerField(db_column='project_id', index=True, null=True) 749 | title = CharField(null=True) 750 | type = CharField(null=True) 751 | updated_at = DateTimeField(null=True) 752 | visibility_level = IntegerField(index=True) 753 | 754 | class Meta: 755 | db_table = 'snippets' 756 | indexes = ( 757 | (('id', 'created_at'), False), 758 | ) 759 | 760 | class Subscriptions(BaseModel): 761 | created_at = DateTimeField(null=True) 762 | subscribable = IntegerField(db_column='subscribable_id', null=True) 763 | subscribable_type = CharField(null=True) 764 | subscribed = BooleanField(null=True) 765 | updated_at = DateTimeField(null=True) 766 | user = IntegerField(db_column='user_id', null=True) 767 | 768 | class Meta: 769 | db_table = 'subscriptions' 770 | indexes = ( 771 | (('user', 'subscribable', 'subscribable_type'), True), 772 | ) 773 | 774 | class Taggings(BaseModel): 775 | context = CharField(null=True) 776 | created_at = DateTimeField(null=True) 777 | tag = IntegerField(db_column='tag_id', null=True) 778 | taggable = IntegerField(db_column='taggable_id', null=True) 779 | taggable_type = CharField(null=True) 780 | tagger = IntegerField(db_column='tagger_id', null=True) 781 | tagger_type = CharField(null=True) 782 | 783 | class Meta: 784 | db_table = 'taggings' 785 | indexes = ( 786 | (('context', 'taggable_type', 'taggable'), False), 787 | (('tagger', 'context', 'tagger_type', 'tag', 'taggable', 'taggable_type'), True), 788 | ) 789 | 790 | class Tags(BaseModel): 791 | name = CharField(null=True, unique=True) 792 | taggings_count = IntegerField(null=True) 793 | 794 | class Meta: 795 | db_table = 'tags' 796 | 797 | class Users(BaseModel): 798 | admin = BooleanField(index=True) 799 | authentication_token = CharField(null=True, unique=True) 800 | avatar = CharField(null=True) 801 | bio = CharField(null=True) 802 | can_create_group = BooleanField() 803 | can_create_team = BooleanField() 804 | color_scheme = IntegerField(db_column='color_scheme_id') 805 | confirmation_sent_at = DateTimeField(null=True) 806 | confirmation_token = CharField(null=True, unique=True) 807 | confirmed_at = DateTimeField(null=True) 808 | consumed_timestep = IntegerField(null=True) 809 | created_at = DateTimeField(null=True) 810 | created_by = IntegerField(db_column='created_by_id', null=True) 811 | current_sign_in_at = DateTimeField(index=True, null=True) 812 | current_sign_in_ip = CharField(null=True) 813 | dashboard = IntegerField(null=True) 814 | email = CharField(unique=True) 815 | encrypted_otp_secret = CharField(null=True) 816 | encrypted_otp_secret_iv = CharField(null=True) 817 | encrypted_otp_secret_salt = CharField(null=True) 818 | encrypted_password = CharField() 819 | failed_attempts = IntegerField(null=True) 820 | hide_no_password = BooleanField(null=True) 821 | hide_no_ssh_key = BooleanField(null=True) 822 | hide_project_limit = BooleanField(null=True) 823 | last_credential_check_at = DateTimeField(null=True) 824 | last_sign_in_at = DateTimeField(null=True) 825 | last_sign_in_ip = CharField(null=True) 826 | layout = IntegerField(null=True) 827 | ldap_email = BooleanField() 828 | linkedin = CharField() 829 | location = CharField(null=True) 830 | locked_at = DateTimeField(null=True) 831 | name = CharField(index=True, null=True) 832 | notification_email = CharField(null=True) 833 | notification_level = IntegerField() 834 | otp_backup_codes = TextField(null=True) 835 | otp_grace_period_started_at = DateTimeField(null=True) 836 | otp_required_for_login = BooleanField() 837 | password_automatically_set = BooleanField(null=True) 838 | password_expires_at = DateTimeField(null=True) 839 | project_view = IntegerField(null=True) 840 | projects_limit = IntegerField(null=True) 841 | public_email = CharField() 842 | remember_created_at = DateTimeField(null=True) 843 | reset_password_sent_at = DateTimeField(null=True) 844 | reset_password_token = CharField(null=True, unique=True) 845 | sign_in_count = IntegerField(null=True) 846 | skype = CharField() 847 | state = CharField(null=True) 848 | theme = IntegerField(db_column='theme_id') 849 | twitter = CharField() 850 | unconfirmed_email = CharField(null=True) 851 | unlock_token = CharField(null=True) 852 | updated_at = DateTimeField(null=True) 853 | username = CharField(index=True, null=True) 854 | website_url = CharField() 855 | 856 | class Meta: 857 | db_table = 'users' 858 | indexes = ( 859 | (('id', 'created_at'), False), 860 | ) 861 | 862 | class UsersStarProjects(BaseModel): 863 | created_at = DateTimeField(null=True) 864 | project = IntegerField(db_column='project_id', index=True) 865 | updated_at = DateTimeField(null=True) 866 | user = IntegerField(db_column='user_id', index=True) 867 | 868 | class Meta: 869 | db_table = 'users_star_projects' 870 | indexes = ( 871 | (('project', 'user'), True), 872 | ) 873 | 874 | class WebHooks(BaseModel): 875 | build_events = BooleanField() 876 | created_at = DateTimeField(null=True) 877 | enable_ssl_verification = BooleanField(null=True) 878 | issues_events = BooleanField() 879 | merge_requests_events = BooleanField() 880 | note_events = BooleanField() 881 | project = IntegerField(db_column='project_id', index=True, null=True) 882 | push_events = BooleanField() 883 | service = IntegerField(db_column='service_id', null=True) 884 | tag_push_events = BooleanField(null=True) 885 | type = CharField(null=True) 886 | updated_at = DateTimeField(null=True) 887 | url = CharField(null=True) 888 | 889 | class Meta: 890 | db_table = 'web_hooks' 891 | indexes = ( 892 | (('id', 'created_at'), False), 893 | ) 894 | -------------------------------------------------------------------------------- /gitlab_direct/model85.py: -------------------------------------------------------------------------------- 1 | from peewee import * 2 | 3 | database_proxy = Proxy() 4 | 5 | class UnknownField(object): 6 | pass 7 | 8 | class BaseModel(Model): 9 | class Meta: 10 | database = database_proxy 11 | 12 | class AbuseReports(BaseModel): 13 | created_at = DateTimeField(null=True) 14 | message = TextField(null=True) 15 | reporter = IntegerField(db_column='reporter_id', null=True) 16 | updated_at = DateTimeField(null=True) 17 | user = IntegerField(db_column='user_id', null=True) 18 | 19 | class Meta: 20 | db_table = 'abuse_reports' 21 | 22 | class ApplicationSettings(BaseModel): 23 | admin_notification_email = CharField(null=True) 24 | after_sign_out_path = CharField(null=True) 25 | akismet_api_key = CharField(null=True) 26 | akismet_enabled = BooleanField(null=True) 27 | created_at = DateTimeField(null=True) 28 | default_branch_protection = IntegerField(null=True) 29 | default_project_visibility = IntegerField(null=True) 30 | default_projects_limit = IntegerField(null=True) 31 | default_snippet_visibility = IntegerField(null=True) 32 | email_author_in_body = BooleanField(null=True) 33 | gravatar_enabled = BooleanField(null=True) 34 | help_page_text = TextField(null=True) 35 | home_page_url = CharField(null=True) 36 | import_sources = TextField(null=True) 37 | max_artifacts_size = IntegerField() 38 | max_attachment_size = IntegerField() 39 | metrics_enabled = BooleanField(null=True) 40 | metrics_host = CharField(null=True) 41 | metrics_method_call_threshold = IntegerField(null=True) 42 | metrics_pool_size = IntegerField(null=True) 43 | metrics_port = IntegerField(null=True) 44 | metrics_sample_interval = IntegerField(null=True) 45 | metrics_timeout = IntegerField(null=True) 46 | recaptcha_enabled = BooleanField(null=True) 47 | recaptcha_private_key = CharField(null=True) 48 | recaptcha_site_key = CharField(null=True) 49 | require_two_factor_authentication = BooleanField(null=True) 50 | restricted_signup_domains = TextField(null=True) 51 | restricted_visibility_levels = TextField(null=True) 52 | runners_registration_token = CharField(null=True) 53 | sentry_dsn = CharField(null=True) 54 | sentry_enabled = BooleanField(null=True) 55 | session_expire_delay = IntegerField() 56 | shared_runners_enabled = BooleanField() 57 | sign_in_text = TextField(null=True) 58 | signin_enabled = BooleanField(null=True) 59 | signup_enabled = BooleanField(null=True) 60 | twitter_sharing_enabled = BooleanField(null=True) 61 | two_factor_grace_period = IntegerField(null=True) 62 | updated_at = DateTimeField(null=True) 63 | user_oauth_applications = BooleanField(null=True) 64 | version_check_enabled = BooleanField(null=True) 65 | 66 | class Meta: 67 | db_table = 'application_settings' 68 | 69 | class AuditEvents(BaseModel): 70 | author = IntegerField(db_column='author_id', index=True) 71 | created_at = DateTimeField(null=True) 72 | details = TextField(null=True) 73 | entity = IntegerField(db_column='entity_id') 74 | entity_type = CharField() 75 | type = CharField(index=True) 76 | updated_at = DateTimeField(null=True) 77 | 78 | class Meta: 79 | db_table = 'audit_events' 80 | indexes = ( 81 | (('entity', 'entity_type'), False), 82 | ) 83 | 84 | class BroadcastMessages(BaseModel): 85 | color = CharField(null=True) 86 | created_at = DateTimeField(null=True) 87 | ends_at = DateTimeField(null=True) 88 | font = CharField(null=True) 89 | message = TextField() 90 | starts_at = DateTimeField(null=True) 91 | updated_at = DateTimeField(null=True) 92 | 93 | class Meta: 94 | db_table = 'broadcast_messages' 95 | 96 | class CiApplicationSettings(BaseModel): 97 | add_pusher = BooleanField(null=True) 98 | all_broken_builds = BooleanField(null=True) 99 | created_at = DateTimeField(null=True) 100 | updated_at = DateTimeField(null=True) 101 | 102 | class Meta: 103 | db_table = 'ci_application_settings' 104 | 105 | class CiBuilds(BaseModel): 106 | allow_failure = BooleanField() 107 | artifacts_file = TextField(null=True) 108 | artifacts_metadata = TextField(null=True) 109 | commands = TextField(null=True) 110 | commit = IntegerField(db_column='commit_id', index=True, null=True) 111 | coverage = FloatField(null=True) 112 | created_at = DateTimeField(null=True) 113 | deploy = BooleanField(null=True) 114 | description = CharField(null=True) 115 | erased_at = DateTimeField(null=True) 116 | erased_by = IntegerField(db_column='erased_by_id', index=True, null=True) 117 | finished_at = DateTimeField(null=True) 118 | gl_project = IntegerField(db_column='gl_project_id', index=True, null=True) 119 | job = IntegerField(db_column='job_id', null=True) 120 | name = CharField(null=True) 121 | options = TextField(null=True) 122 | project = IntegerField(db_column='project_id', index=True, null=True) 123 | ref = CharField(null=True) 124 | runner = IntegerField(db_column='runner_id', index=True, null=True) 125 | stage = CharField(null=True) 126 | stage_idx = IntegerField(null=True) 127 | started_at = DateTimeField(null=True) 128 | status = CharField(index=True, null=True) 129 | tag = BooleanField(null=True) 130 | target_url = CharField(null=True) 131 | trace = TextField(null=True) 132 | trigger_request = IntegerField(db_column='trigger_request_id', null=True) 133 | type = CharField(index=True, null=True) 134 | updated_at = DateTimeField(null=True) 135 | user = IntegerField(db_column='user_id', null=True) 136 | 137 | class Meta: 138 | db_table = 'ci_builds' 139 | indexes = ( 140 | (('commit', 'created_at', 'stage_idx'), False), 141 | (('project', 'commit'), False), 142 | (('type', 'commit', 'ref'), False), 143 | (('type', 'commit', 'status'), False), 144 | (('type', 'name', 'ref', 'commit'), False), 145 | ) 146 | 147 | class CiCommits(BaseModel): 148 | before_sha = CharField(null=True) 149 | committed_at = DateTimeField(null=True) 150 | created_at = DateTimeField(null=True) 151 | gl_project = IntegerField(db_column='gl_project_id', index=True, null=True) 152 | project = IntegerField(db_column='project_id', index=True, null=True) 153 | push_data = TextField(null=True) 154 | ref = CharField(null=True) 155 | sha = CharField(index=True, null=True) 156 | tag = BooleanField(null=True) 157 | updated_at = DateTimeField(null=True) 158 | yaml_errors = TextField(null=True) 159 | 160 | class Meta: 161 | db_table = 'ci_commits' 162 | indexes = ( 163 | (('committed_at', 'project'), False), 164 | (('id', 'project', 'committed_at'), False), 165 | (('sha', 'project'), False), 166 | ) 167 | 168 | class CiEvents(BaseModel): 169 | created_at = DateTimeField(index=True, null=True) 170 | description = TextField(null=True) 171 | is_admin = IntegerField(index=True, null=True) 172 | project = IntegerField(db_column='project_id', index=True, null=True) 173 | updated_at = DateTimeField(null=True) 174 | user = IntegerField(db_column='user_id', null=True) 175 | 176 | class Meta: 177 | db_table = 'ci_events' 178 | 179 | class CiJobs(BaseModel): 180 | active = BooleanField() 181 | build_branches = BooleanField() 182 | build_tags = BooleanField() 183 | commands = TextField(null=True) 184 | created_at = DateTimeField(null=True) 185 | deleted_at = DateTimeField(index=True, null=True) 186 | job_type = CharField(null=True) 187 | name = CharField(null=True) 188 | project = IntegerField(db_column='project_id', index=True) 189 | refs = CharField(null=True) 190 | updated_at = DateTimeField(null=True) 191 | 192 | class Meta: 193 | db_table = 'ci_jobs' 194 | 195 | class CiProjects(BaseModel): 196 | allow_git_fetch = BooleanField() 197 | always_build = BooleanField() 198 | coverage_regex = CharField(null=True) 199 | created_at = DateTimeField(null=True) 200 | default_ref = CharField(null=True) 201 | email_add_pusher = BooleanField() 202 | email_only_broken_builds = BooleanField() 203 | email_recipients = CharField() 204 | generated_yaml_config = TextField(null=True) 205 | gitlab = IntegerField(db_column='gitlab_id', index=True, null=True) 206 | name = CharField(null=True) 207 | path = CharField(null=True) 208 | polling_interval = IntegerField(null=True) 209 | public = BooleanField() 210 | shared_runners_enabled = BooleanField(index=True, null=True) 211 | skip_refs = CharField(null=True) 212 | ssh_url_to_repo = CharField(null=True) 213 | timeout = IntegerField() 214 | token = CharField(null=True) 215 | updated_at = DateTimeField(null=True) 216 | 217 | class Meta: 218 | db_table = 'ci_projects' 219 | 220 | class CiRunnerProjects(BaseModel): 221 | created_at = DateTimeField(null=True) 222 | gl_project = IntegerField(db_column='gl_project_id', index=True, null=True) 223 | project = IntegerField(db_column='project_id', null=True) 224 | runner = IntegerField(db_column='runner_id', index=True) 225 | updated_at = DateTimeField(null=True) 226 | 227 | class Meta: 228 | db_table = 'ci_runner_projects' 229 | 230 | class CiRunners(BaseModel): 231 | active = BooleanField() 232 | architecture = CharField(null=True) 233 | contacted_at = DateTimeField(null=True) 234 | created_at = DateTimeField(null=True) 235 | description = CharField(null=True) 236 | is_shared = BooleanField(null=True) 237 | name = CharField(null=True) 238 | platform = CharField(null=True) 239 | revision = CharField(null=True) 240 | token = CharField(null=True) 241 | updated_at = DateTimeField(null=True) 242 | version = CharField(null=True) 243 | 244 | class Meta: 245 | db_table = 'ci_runners' 246 | 247 | class CiServices(BaseModel): 248 | active = BooleanField() 249 | created_at = DateTimeField(null=True) 250 | project = IntegerField(db_column='project_id', index=True) 251 | properties = TextField(null=True) 252 | title = CharField(null=True) 253 | type = CharField(null=True) 254 | updated_at = DateTimeField(null=True) 255 | 256 | class Meta: 257 | db_table = 'ci_services' 258 | 259 | class CiSessions(BaseModel): 260 | created_at = DateTimeField(null=True) 261 | data = TextField(null=True) 262 | session = CharField(db_column='session_id', index=True) 263 | updated_at = DateTimeField(index=True, null=True) 264 | 265 | class Meta: 266 | db_table = 'ci_sessions' 267 | 268 | class CiTaggings(BaseModel): 269 | context = CharField(null=True) 270 | created_at = DateTimeField(null=True) 271 | tag = IntegerField(db_column='tag_id', null=True) 272 | taggable = IntegerField(db_column='taggable_id', null=True) 273 | taggable_type = CharField(null=True) 274 | tagger = IntegerField(db_column='tagger_id', null=True) 275 | tagger_type = CharField(null=True) 276 | 277 | class Meta: 278 | db_table = 'ci_taggings' 279 | indexes = ( 280 | (('context', 'taggable_type', 'taggable'), False), 281 | (('tagger', 'context', 'tagger_type', 'tag', 'taggable', 'taggable_type'), True), 282 | ) 283 | 284 | class CiTags(BaseModel): 285 | name = CharField(null=True, unique=True) 286 | taggings_count = IntegerField(null=True) 287 | 288 | class Meta: 289 | db_table = 'ci_tags' 290 | 291 | class CiTriggerRequests(BaseModel): 292 | commit = IntegerField(db_column='commit_id', null=True) 293 | created_at = DateTimeField(null=True) 294 | trigger = IntegerField(db_column='trigger_id') 295 | updated_at = DateTimeField(null=True) 296 | variables = TextField(null=True) 297 | 298 | class Meta: 299 | db_table = 'ci_trigger_requests' 300 | 301 | class CiTriggers(BaseModel): 302 | created_at = DateTimeField(null=True) 303 | deleted_at = DateTimeField(index=True, null=True) 304 | gl_project = IntegerField(db_column='gl_project_id', index=True, null=True) 305 | project = IntegerField(db_column='project_id', null=True) 306 | token = CharField(null=True) 307 | updated_at = DateTimeField(null=True) 308 | 309 | class Meta: 310 | db_table = 'ci_triggers' 311 | 312 | class CiVariables(BaseModel): 313 | encrypted_value = TextField(null=True) 314 | encrypted_value_iv = CharField(null=True) 315 | encrypted_value_salt = CharField(null=True) 316 | gl_project = IntegerField(db_column='gl_project_id', index=True, null=True) 317 | key = CharField(null=True) 318 | project = IntegerField(db_column='project_id', null=True) 319 | value = TextField(null=True) 320 | 321 | class Meta: 322 | db_table = 'ci_variables' 323 | 324 | class CiWebHooks(BaseModel): 325 | created_at = DateTimeField(null=True) 326 | project = IntegerField(db_column='project_id') 327 | updated_at = DateTimeField(null=True) 328 | url = CharField() 329 | 330 | class Meta: 331 | db_table = 'ci_web_hooks' 332 | 333 | class DeployKeysProjects(BaseModel): 334 | created_at = DateTimeField(null=True) 335 | deploy_key = IntegerField(db_column='deploy_key_id') 336 | project = IntegerField(db_column='project_id', index=True) 337 | updated_at = DateTimeField(null=True) 338 | 339 | class Meta: 340 | db_table = 'deploy_keys_projects' 341 | 342 | class Emails(BaseModel): 343 | created_at = DateTimeField(null=True) 344 | email = CharField(unique=True) 345 | updated_at = DateTimeField(null=True) 346 | user = IntegerField(db_column='user_id', index=True) 347 | 348 | class Meta: 349 | db_table = 'emails' 350 | 351 | class Events(BaseModel): 352 | action = IntegerField(index=True, null=True) 353 | author = IntegerField(db_column='author_id', index=True, null=True) 354 | created_at = DateTimeField(index=True, null=True) 355 | data = TextField(null=True) 356 | project = IntegerField(db_column='project_id', index=True, null=True) 357 | target = IntegerField(db_column='target_id', index=True, null=True) 358 | target_type = CharField(index=True, null=True) 359 | title = CharField(null=True) 360 | updated_at = DateTimeField(null=True) 361 | 362 | class Meta: 363 | db_table = 'events' 364 | 365 | class ForkedProjectLinks(BaseModel): 366 | created_at = DateTimeField(null=True) 367 | forked_from_project = IntegerField(db_column='forked_from_project_id') 368 | forked_to_project = IntegerField(db_column='forked_to_project_id', unique=True) 369 | updated_at = DateTimeField(null=True) 370 | 371 | class Meta: 372 | db_table = 'forked_project_links' 373 | 374 | class Identities(BaseModel): 375 | created_at = DateTimeField(null=True) 376 | extern_uid = CharField(null=True) 377 | provider = CharField(null=True) 378 | updated_at = DateTimeField(null=True) 379 | user = IntegerField(db_column='user_id', index=True, null=True) 380 | 381 | class Meta: 382 | db_table = 'identities' 383 | indexes = ( 384 | (('id', 'created_at'), False), 385 | ) 386 | 387 | class Issues(BaseModel): 388 | assignee = IntegerField(db_column='assignee_id', index=True, null=True) 389 | author = IntegerField(db_column='author_id', index=True, null=True) 390 | branch_name = CharField(null=True) 391 | created_at = DateTimeField(index=True, null=True) 392 | description = TextField(null=True) 393 | iid = IntegerField(null=True) 394 | milestone = IntegerField(db_column='milestone_id', index=True, null=True) 395 | position = IntegerField(null=True) 396 | project = IntegerField(db_column='project_id', index=True, null=True) 397 | state = CharField(index=True, null=True) 398 | title = CharField(index=True, null=True) 399 | updated_at = DateTimeField(null=True) 400 | updated_by = IntegerField(db_column='updated_by_id', null=True) 401 | 402 | class Meta: 403 | db_table = 'issues' 404 | indexes = ( 405 | (('id', 'created_at'), False), 406 | (('project', 'iid'), True), 407 | ) 408 | 409 | class Keys(BaseModel): 410 | created_at = DateTimeField(null=True) 411 | fingerprint = CharField(null=True) 412 | key = TextField(null=True) 413 | public = BooleanField() 414 | title = CharField(null=True) 415 | type = CharField(null=True) 416 | updated_at = DateTimeField(null=True) 417 | user = IntegerField(db_column='user_id', index=True, null=True) 418 | 419 | class Meta: 420 | db_table = 'keys' 421 | indexes = ( 422 | (('id', 'created_at'), False), 423 | ) 424 | 425 | class LabelLinks(BaseModel): 426 | created_at = DateTimeField(null=True) 427 | label = IntegerField(db_column='label_id', index=True, null=True) 428 | target = IntegerField(db_column='target_id', null=True) 429 | target_type = CharField(null=True) 430 | updated_at = DateTimeField(null=True) 431 | 432 | class Meta: 433 | db_table = 'label_links' 434 | indexes = ( 435 | (('target', 'target_type'), False), 436 | ) 437 | 438 | class Labels(BaseModel): 439 | color = CharField(null=True) 440 | created_at = DateTimeField(null=True) 441 | description = CharField(null=True) 442 | project = IntegerField(db_column='project_id', index=True, null=True) 443 | template = BooleanField(null=True) 444 | title = CharField(null=True) 445 | updated_at = DateTimeField(null=True) 446 | 447 | class Meta: 448 | db_table = 'labels' 449 | 450 | class LfsObjects(BaseModel): 451 | created_at = DateTimeField(null=True) 452 | file = CharField(null=True) 453 | oid = CharField(unique=True) 454 | size = BigIntegerField() 455 | updated_at = DateTimeField(null=True) 456 | 457 | class Meta: 458 | db_table = 'lfs_objects' 459 | 460 | class LfsObjectsProjects(BaseModel): 461 | created_at = DateTimeField(null=True) 462 | lfs_object = IntegerField(db_column='lfs_object_id') 463 | project = IntegerField(db_column='project_id', index=True) 464 | updated_at = DateTimeField(null=True) 465 | 466 | class Meta: 467 | db_table = 'lfs_objects_projects' 468 | 469 | class Members(BaseModel): 470 | access_level = IntegerField(index=True) 471 | created_at = DateTimeField(null=True) 472 | created_by = IntegerField(db_column='created_by_id', null=True) 473 | invite_accepted_at = DateTimeField(null=True) 474 | invite_email = CharField(null=True) 475 | invite_token = CharField(null=True, unique=True) 476 | notification_level = IntegerField() 477 | source = IntegerField(db_column='source_id') 478 | source_type = CharField() 479 | type = CharField(index=True, null=True) 480 | updated_at = DateTimeField(null=True) 481 | user = IntegerField(db_column='user_id', index=True, null=True) 482 | 483 | class Meta: 484 | db_table = 'members' 485 | indexes = ( 486 | (('id', 'created_at'), False), 487 | (('source', 'source_type'), False), 488 | ) 489 | 490 | class MergeRequestDiffs(BaseModel): 491 | base_commit_sha = CharField(null=True) 492 | created_at = DateTimeField(null=True) 493 | merge_request = IntegerField(db_column='merge_request_id', unique=True) 494 | st_commits = TextField(null=True) 495 | st_diffs = TextField(null=True) 496 | state = CharField(null=True) 497 | updated_at = DateTimeField(null=True) 498 | 499 | class Meta: 500 | db_table = 'merge_request_diffs' 501 | 502 | class MergeRequests(BaseModel): 503 | assignee = IntegerField(db_column='assignee_id', index=True, null=True) 504 | author = IntegerField(db_column='author_id', index=True, null=True) 505 | created_at = DateTimeField(index=True, null=True) 506 | description = TextField(null=True) 507 | iid = IntegerField(null=True) 508 | locked_at = DateTimeField(null=True) 509 | merge_commit_sha = CharField(null=True) 510 | merge_error = CharField(null=True) 511 | merge_params = TextField(null=True) 512 | merge_status = CharField(null=True) 513 | merge_user = IntegerField(db_column='merge_user_id', null=True) 514 | merge_when_build_succeeds = BooleanField() 515 | milestone = IntegerField(db_column='milestone_id', index=True, null=True) 516 | position = IntegerField(null=True) 517 | source_branch = CharField(index=True) 518 | source_project = IntegerField(db_column='source_project_id', index=True) 519 | state = CharField(null=True) 520 | target_branch = CharField(index=True) 521 | target_project = IntegerField(db_column='target_project_id') 522 | title = CharField(index=True, null=True) 523 | updated_at = DateTimeField(null=True) 524 | updated_by = IntegerField(db_column='updated_by_id', null=True) 525 | 526 | class Meta: 527 | db_table = 'merge_requests' 528 | indexes = ( 529 | (('created_at', 'id'), False), 530 | (('target_project', 'iid'), True), 531 | ) 532 | 533 | class Milestones(BaseModel): 534 | created_at = DateTimeField(null=True) 535 | description = TextField(null=True) 536 | due_date = DateField(index=True, null=True) 537 | iid = IntegerField(null=True) 538 | project = IntegerField(db_column='project_id', index=True) 539 | state = CharField(null=True) 540 | title = CharField(index=True) 541 | updated_at = DateTimeField(null=True) 542 | 543 | class Meta: 544 | db_table = 'milestones' 545 | indexes = ( 546 | (('id', 'created_at'), False), 547 | (('project', 'iid'), True), 548 | ) 549 | 550 | class Namespaces(BaseModel): 551 | avatar = CharField(null=True) 552 | created_at = DateTimeField(null=True) 553 | description = CharField() 554 | name = CharField(unique=True) 555 | owner = IntegerField(db_column='owner_id', index=True, null=True) 556 | path = CharField(unique=True) 557 | type = CharField(index=True, null=True) 558 | updated_at = DateTimeField(null=True) 559 | 560 | class Meta: 561 | db_table = 'namespaces' 562 | indexes = ( 563 | (('id', 'created_at'), False), 564 | ) 565 | 566 | class Notes(BaseModel): 567 | attachment = CharField(null=True) 568 | author = IntegerField(db_column='author_id', index=True, null=True) 569 | commit = CharField(db_column='commit_id', index=True, null=True) 570 | created_at = DateTimeField(index=True, null=True) 571 | is_award = BooleanField(index=True) 572 | line_code = CharField(index=True, null=True) 573 | note = TextField(null=True) 574 | noteable = IntegerField(db_column='noteable_id', null=True) 575 | noteable_type = CharField(index=True, null=True) 576 | project = IntegerField(db_column='project_id', index=True, null=True) 577 | st_diff = TextField(null=True) 578 | system = BooleanField() 579 | updated_at = DateTimeField(index=True, null=True) 580 | updated_by = IntegerField(db_column='updated_by_id', null=True) 581 | 582 | class Meta: 583 | db_table = 'notes' 584 | indexes = ( 585 | (('created_at', 'id'), False), 586 | (('noteable_type', 'noteable'), False), 587 | (('project', 'noteable_type'), False), 588 | ) 589 | 590 | class OauthAccessGrants(BaseModel): 591 | application = IntegerField(db_column='application_id') 592 | created_at = DateTimeField() 593 | expires_in = IntegerField() 594 | redirect_uri = TextField() 595 | resource_owner = IntegerField(db_column='resource_owner_id') 596 | revoked_at = DateTimeField(null=True) 597 | scopes = CharField(null=True) 598 | token = CharField(unique=True) 599 | 600 | class Meta: 601 | db_table = 'oauth_access_grants' 602 | 603 | class OauthAccessTokens(BaseModel): 604 | application = IntegerField(db_column='application_id', null=True) 605 | created_at = DateTimeField() 606 | expires_in = IntegerField(null=True) 607 | refresh_token = CharField(null=True, unique=True) 608 | resource_owner = IntegerField(db_column='resource_owner_id', index=True, null=True) 609 | revoked_at = DateTimeField(null=True) 610 | scopes = CharField(null=True) 611 | token = CharField(unique=True) 612 | 613 | class Meta: 614 | db_table = 'oauth_access_tokens' 615 | 616 | class OauthApplications(BaseModel): 617 | created_at = DateTimeField(null=True) 618 | name = CharField() 619 | owner = IntegerField(db_column='owner_id', null=True) 620 | owner_type = CharField(null=True) 621 | redirect_uri = TextField() 622 | scopes = CharField() 623 | secret = CharField() 624 | uid = CharField(unique=True) 625 | updated_at = DateTimeField(null=True) 626 | 627 | class Meta: 628 | db_table = 'oauth_applications' 629 | indexes = ( 630 | (('owner', 'owner_type'), False), 631 | ) 632 | 633 | class ProjectImportData(BaseModel): 634 | data = TextField(null=True) 635 | project = IntegerField(db_column='project_id', null=True) 636 | 637 | class Meta: 638 | db_table = 'project_import_data' 639 | 640 | class Projects(BaseModel): 641 | archived = BooleanField() 642 | avatar = CharField(null=True) 643 | build_allow_git_fetch = BooleanField() 644 | build_coverage_regex = CharField(null=True) 645 | build_timeout = IntegerField() 646 | builds_enabled = BooleanField(index=True) 647 | ci = IntegerField(db_column='ci_id', index=True, null=True) 648 | commit_count = IntegerField(null=True) 649 | created_at = DateTimeField(null=True) 650 | creator = IntegerField(db_column='creator_id', index=True, null=True) 651 | description = TextField(null=True) 652 | import_error = TextField(null=True) 653 | import_source = CharField(null=True) 654 | import_status = CharField(null=True) 655 | import_type = CharField(null=True) 656 | import_url = CharField(null=True) 657 | issues_enabled = BooleanField() 658 | issues_tracker = CharField() 659 | issues_tracker_id = CharField(null=True) 660 | last_activity_at = DateTimeField(index=True, null=True) 661 | merge_requests_enabled = BooleanField() 662 | name = CharField(null=True) 663 | namespace = IntegerField(db_column='namespace_id', index=True, null=True) 664 | path = CharField(index=True, null=True) 665 | pending_delete = BooleanField(null=True) 666 | public_builds = BooleanField() 667 | repository_size = FloatField(null=True) 668 | runners_token = CharField(index=True, null=True) 669 | shared_runners_enabled = BooleanField() 670 | snippets_enabled = BooleanField() 671 | star_count = IntegerField(index=True) 672 | updated_at = DateTimeField(null=True) 673 | visibility_level = IntegerField(index=True) 674 | wall_enabled = BooleanField() 675 | wiki_enabled = BooleanField() 676 | 677 | class Meta: 678 | db_table = 'projects' 679 | indexes = ( 680 | (('id', 'created_at'), False), 681 | (('shared_runners_enabled', 'builds_enabled'), False), 682 | ) 683 | 684 | class ProtectedBranches(BaseModel): 685 | created_at = DateTimeField(null=True) 686 | developers_can_push = BooleanField() 687 | name = CharField() 688 | project = IntegerField(db_column='project_id', index=True) 689 | updated_at = DateTimeField(null=True) 690 | 691 | class Meta: 692 | db_table = 'protected_branches' 693 | 694 | class Releases(BaseModel): 695 | created_at = DateTimeField(null=True) 696 | description = TextField(null=True) 697 | project = IntegerField(db_column='project_id', index=True, null=True) 698 | tag = CharField(null=True) 699 | updated_at = DateTimeField(null=True) 700 | 701 | class Meta: 702 | db_table = 'releases' 703 | indexes = ( 704 | (('tag', 'project'), False), 705 | ) 706 | 707 | class SchemaMigrations(BaseModel): 708 | version = CharField(unique=True) 709 | 710 | class Meta: 711 | db_table = 'schema_migrations' 712 | 713 | class SentNotifications(BaseModel): 714 | commit = CharField(db_column='commit_id', null=True) 715 | line_code = CharField(null=True) 716 | noteable = IntegerField(db_column='noteable_id', null=True) 717 | noteable_type = CharField(null=True) 718 | project = IntegerField(db_column='project_id', null=True) 719 | recipient = IntegerField(db_column='recipient_id', null=True) 720 | reply_key = CharField(unique=True) 721 | 722 | class Meta: 723 | db_table = 'sent_notifications' 724 | 725 | class Services(BaseModel): 726 | active = BooleanField() 727 | build_events = BooleanField() 728 | category = CharField(index=True) 729 | created_at = DateTimeField() 730 | default = BooleanField(index=True, null=True) 731 | issues_events = BooleanField(null=True) 732 | merge_requests_events = BooleanField(null=True) 733 | note_events = BooleanField() 734 | project = IntegerField(db_column='project_id', index=True, null=True) 735 | properties = TextField(null=True) 736 | push_events = BooleanField(null=True) 737 | tag_push_events = BooleanField(null=True) 738 | template = BooleanField(index=True, null=True) 739 | title = CharField(null=True) 740 | type = CharField(null=True) 741 | updated_at = DateTimeField() 742 | 743 | class Meta: 744 | db_table = 'services' 745 | indexes = ( 746 | (('id', 'created_at'), False), 747 | ) 748 | 749 | class Snippets(BaseModel): 750 | author = IntegerField(db_column='author_id', index=True) 751 | content = TextField(null=True) 752 | created_at = DateTimeField(index=True, null=True) 753 | expires_at = DateTimeField(index=True, null=True) 754 | file_name = CharField(null=True) 755 | project = IntegerField(db_column='project_id', index=True, null=True) 756 | title = CharField(null=True) 757 | type = CharField(null=True) 758 | updated_at = DateTimeField(index=True, null=True) 759 | visibility_level = IntegerField(index=True) 760 | 761 | class Meta: 762 | db_table = 'snippets' 763 | indexes = ( 764 | (('id', 'created_at'), False), 765 | ) 766 | 767 | class SpamLogs(BaseModel): 768 | created_at = DateTimeField() 769 | description = TextField(null=True) 770 | noteable_type = CharField(null=True) 771 | project = IntegerField(db_column='project_id', null=True) 772 | source_ip = CharField(null=True) 773 | title = CharField(null=True) 774 | updated_at = DateTimeField() 775 | user_agent = CharField(null=True) 776 | user = IntegerField(db_column='user_id', null=True) 777 | via_api = BooleanField(null=True) 778 | 779 | class Meta: 780 | db_table = 'spam_logs' 781 | 782 | class Subscriptions(BaseModel): 783 | created_at = DateTimeField(null=True) 784 | subscribable = IntegerField(db_column='subscribable_id', null=True) 785 | subscribable_type = CharField(null=True) 786 | subscribed = BooleanField(null=True) 787 | updated_at = DateTimeField(null=True) 788 | user = IntegerField(db_column='user_id', null=True) 789 | 790 | class Meta: 791 | db_table = 'subscriptions' 792 | indexes = ( 793 | (('user', 'subscribable', 'subscribable_type'), True), 794 | ) 795 | 796 | class Taggings(BaseModel): 797 | context = CharField(null=True) 798 | created_at = DateTimeField(null=True) 799 | tag = IntegerField(db_column='tag_id', null=True) 800 | taggable = IntegerField(db_column='taggable_id', null=True) 801 | taggable_type = CharField(null=True) 802 | tagger = IntegerField(db_column='tagger_id', null=True) 803 | tagger_type = CharField(null=True) 804 | 805 | class Meta: 806 | db_table = 'taggings' 807 | indexes = ( 808 | (('context', 'taggable_type', 'taggable'), False), 809 | (('tagger', 'context', 'tagger_type', 'tag', 'taggable', 'taggable_type'), True), 810 | ) 811 | 812 | class Tags(BaseModel): 813 | name = CharField(null=True, unique=True) 814 | taggings_count = IntegerField(null=True) 815 | 816 | class Meta: 817 | db_table = 'tags' 818 | 819 | class Todos(BaseModel): 820 | action = IntegerField() 821 | author = IntegerField(db_column='author_id', index=True, null=True) 822 | created_at = DateTimeField(null=True) 823 | note = IntegerField(db_column='note_id', index=True, null=True) 824 | project = IntegerField(db_column='project_id', index=True) 825 | state = CharField(index=True) 826 | target = IntegerField(db_column='target_id') 827 | target_type = CharField() 828 | updated_at = DateTimeField(null=True) 829 | user = IntegerField(db_column='user_id', index=True) 830 | 831 | class Meta: 832 | db_table = 'todos' 833 | indexes = ( 834 | (('target', 'target_type'), False), 835 | ) 836 | 837 | class Users(BaseModel): 838 | admin = BooleanField(index=True) 839 | authentication_token = CharField(null=True, unique=True) 840 | avatar = CharField(null=True) 841 | bio = CharField(null=True) 842 | can_create_group = BooleanField() 843 | can_create_team = BooleanField() 844 | color_scheme = IntegerField(db_column='color_scheme_id') 845 | confirmation_sent_at = DateTimeField(null=True) 846 | confirmation_token = CharField(null=True, unique=True) 847 | confirmed_at = DateTimeField(null=True) 848 | consumed_timestep = IntegerField(null=True) 849 | created_at = DateTimeField(null=True) 850 | created_by = IntegerField(db_column='created_by_id', null=True) 851 | current_sign_in_at = DateTimeField(index=True, null=True) 852 | current_sign_in_ip = CharField(null=True) 853 | dashboard = IntegerField(null=True) 854 | email = CharField(unique=True) 855 | encrypted_otp_secret = CharField(null=True) 856 | encrypted_otp_secret_iv = CharField(null=True) 857 | encrypted_otp_secret_salt = CharField(null=True) 858 | encrypted_password = CharField() 859 | failed_attempts = IntegerField(null=True) 860 | hide_no_password = BooleanField(null=True) 861 | hide_no_ssh_key = BooleanField(null=True) 862 | hide_project_limit = BooleanField(null=True) 863 | last_credential_check_at = DateTimeField(null=True) 864 | last_sign_in_at = DateTimeField(null=True) 865 | last_sign_in_ip = CharField(null=True) 866 | layout = IntegerField(null=True) 867 | ldap_email = BooleanField() 868 | linkedin = CharField() 869 | location = CharField(null=True) 870 | locked_at = DateTimeField(null=True) 871 | name = CharField(index=True, null=True) 872 | notification_email = CharField(null=True) 873 | notification_level = IntegerField() 874 | otp_backup_codes = TextField(null=True) 875 | otp_grace_period_started_at = DateTimeField(null=True) 876 | otp_required_for_login = BooleanField() 877 | password_automatically_set = BooleanField(null=True) 878 | password_expires_at = DateTimeField(null=True) 879 | project_view = IntegerField(null=True) 880 | projects_limit = IntegerField(null=True) 881 | public_email = CharField() 882 | remember_created_at = DateTimeField(null=True) 883 | reset_password_sent_at = DateTimeField(null=True) 884 | reset_password_token = CharField(null=True, unique=True) 885 | sign_in_count = IntegerField(null=True) 886 | skype = CharField() 887 | state = CharField(null=True) 888 | theme = IntegerField(db_column='theme_id') 889 | twitter = CharField() 890 | unconfirmed_email = CharField(null=True) 891 | unlock_token = CharField(null=True) 892 | updated_at = DateTimeField(null=True) 893 | username = CharField(index=True, null=True) 894 | website_url = CharField() 895 | 896 | class Meta: 897 | db_table = 'users' 898 | indexes = ( 899 | (('id', 'created_at'), False), 900 | ) 901 | 902 | class UsersStarProjects(BaseModel): 903 | created_at = DateTimeField(null=True) 904 | project = IntegerField(db_column='project_id', index=True) 905 | updated_at = DateTimeField(null=True) 906 | user = IntegerField(db_column='user_id', index=True) 907 | 908 | class Meta: 909 | db_table = 'users_star_projects' 910 | indexes = ( 911 | (('project', 'user'), True), 912 | ) 913 | 914 | class WebHooks(BaseModel): 915 | build_events = BooleanField() 916 | created_at = DateTimeField(null=True) 917 | enable_ssl_verification = BooleanField(null=True) 918 | issues_events = BooleanField() 919 | merge_requests_events = BooleanField() 920 | note_events = BooleanField() 921 | project = IntegerField(db_column='project_id', index=True, null=True) 922 | push_events = BooleanField() 923 | service = IntegerField(db_column='service_id', null=True) 924 | tag_push_events = BooleanField(null=True) 925 | type = CharField(null=True) 926 | updated_at = DateTimeField(null=True) 927 | url = CharField(null=True) 928 | 929 | class Meta: 930 | db_table = 'web_hooks' 931 | indexes = ( 932 | (('id', 'created_at'), False), 933 | ) 934 | -------------------------------------------------------------------------------- /gitlab_direct/model87.py: -------------------------------------------------------------------------------- 1 | from peewee import * 2 | 3 | database_proxy = Proxy() 4 | 5 | class UnknownField(object): 6 | pass 7 | 8 | class BaseModel(Model): 9 | class Meta: 10 | database = database_proxy 11 | 12 | class AbuseReports(BaseModel): 13 | created_at = DateTimeField(null=True) 14 | message = TextField(null=True) 15 | reporter = IntegerField(db_column='reporter_id', null=True) 16 | updated_at = DateTimeField(null=True) 17 | user = IntegerField(db_column='user_id', null=True) 18 | 19 | class Meta: 20 | db_table = 'abuse_reports' 21 | 22 | class Appearances(BaseModel): 23 | created_at = DateTimeField() 24 | description = TextField(null=True) 25 | header_logo = CharField(null=True) 26 | logo = CharField(null=True) 27 | title = CharField(null=True) 28 | updated_at = DateTimeField() 29 | 30 | class Meta: 31 | db_table = 'appearances' 32 | 33 | class ApplicationSettings(BaseModel): 34 | admin_notification_email = CharField(null=True) 35 | after_sign_out_path = CharField(null=True) 36 | akismet_api_key = CharField(null=True) 37 | akismet_enabled = BooleanField(null=True) 38 | created_at = DateTimeField(null=True) 39 | default_branch_protection = IntegerField(null=True) 40 | default_group_visibility = IntegerField(null=True) 41 | default_project_visibility = IntegerField(null=True) 42 | default_projects_limit = IntegerField(null=True) 43 | default_snippet_visibility = IntegerField(null=True) 44 | email_author_in_body = BooleanField(null=True) 45 | gravatar_enabled = BooleanField(null=True) 46 | help_page_text = TextField(null=True) 47 | home_page_url = CharField(null=True) 48 | import_sources = TextField(null=True) 49 | max_artifacts_size = IntegerField() 50 | max_attachment_size = IntegerField() 51 | metrics_enabled = BooleanField(null=True) 52 | metrics_host = CharField(null=True) 53 | metrics_method_call_threshold = IntegerField(null=True) 54 | metrics_packet_size = IntegerField(null=True) 55 | metrics_pool_size = IntegerField(null=True) 56 | metrics_port = IntegerField(null=True) 57 | metrics_sample_interval = IntegerField(null=True) 58 | metrics_timeout = IntegerField(null=True) 59 | recaptcha_enabled = BooleanField(null=True) 60 | recaptcha_private_key = CharField(null=True) 61 | recaptcha_site_key = CharField(null=True) 62 | repository_checks_enabled = BooleanField(null=True) 63 | require_two_factor_authentication = BooleanField(null=True) 64 | restricted_signup_domains = TextField(null=True) 65 | restricted_visibility_levels = TextField(null=True) 66 | runners_registration_token = CharField(null=True) 67 | sentry_dsn = CharField(null=True) 68 | sentry_enabled = BooleanField(null=True) 69 | session_expire_delay = IntegerField() 70 | shared_runners_enabled = BooleanField() 71 | shared_runners_text = TextField(null=True) 72 | sign_in_text = TextField(null=True) 73 | signin_enabled = BooleanField(null=True) 74 | signup_enabled = BooleanField(null=True) 75 | two_factor_grace_period = IntegerField(null=True) 76 | updated_at = DateTimeField(null=True) 77 | user_oauth_applications = BooleanField(null=True) 78 | version_check_enabled = BooleanField(null=True) 79 | 80 | class Meta: 81 | db_table = 'application_settings' 82 | 83 | class AuditEvents(BaseModel): 84 | author = IntegerField(db_column='author_id', index=True) 85 | created_at = DateTimeField(null=True) 86 | details = TextField(null=True) 87 | entity = IntegerField(db_column='entity_id') 88 | entity_type = CharField() 89 | type = CharField(index=True) 90 | updated_at = DateTimeField(null=True) 91 | 92 | class Meta: 93 | db_table = 'audit_events' 94 | indexes = ( 95 | (('entity', 'entity_type'), False), 96 | ) 97 | 98 | class BroadcastMessages(BaseModel): 99 | color = CharField(null=True) 100 | created_at = DateTimeField(null=True) 101 | ends_at = DateTimeField(null=True) 102 | font = CharField(null=True) 103 | message = TextField() 104 | starts_at = DateTimeField(null=True) 105 | updated_at = DateTimeField(null=True) 106 | 107 | class Meta: 108 | db_table = 'broadcast_messages' 109 | 110 | class CiApplicationSettings(BaseModel): 111 | add_pusher = BooleanField(null=True) 112 | all_broken_builds = BooleanField(null=True) 113 | created_at = DateTimeField(null=True) 114 | updated_at = DateTimeField(null=True) 115 | 116 | class Meta: 117 | db_table = 'ci_application_settings' 118 | 119 | class CiBuilds(BaseModel): 120 | allow_failure = BooleanField() 121 | artifacts_file = TextField(null=True) 122 | artifacts_metadata = TextField(null=True) 123 | commands = TextField(null=True) 124 | commit = IntegerField(db_column='commit_id', index=True, null=True) 125 | coverage = FloatField(null=True) 126 | created_at = DateTimeField(null=True) 127 | deploy = BooleanField(null=True) 128 | description = CharField(null=True) 129 | erased_at = DateTimeField(null=True) 130 | erased_by = IntegerField(db_column='erased_by_id', index=True, null=True) 131 | finished_at = DateTimeField(null=True) 132 | gl_project = IntegerField(db_column='gl_project_id', index=True, null=True) 133 | job = IntegerField(db_column='job_id', null=True) 134 | name = CharField(null=True) 135 | options = TextField(null=True) 136 | project = IntegerField(db_column='project_id', index=True, null=True) 137 | ref = CharField(null=True) 138 | runner = IntegerField(db_column='runner_id', index=True, null=True) 139 | stage = CharField(null=True) 140 | stage_idx = IntegerField(null=True) 141 | started_at = DateTimeField(null=True) 142 | status = CharField(index=True, null=True) 143 | tag = BooleanField(null=True) 144 | target_url = CharField(null=True) 145 | trace = TextField(null=True) 146 | trigger_request = IntegerField(db_column='trigger_request_id', null=True) 147 | type = CharField(index=True, null=True) 148 | updated_at = DateTimeField(null=True) 149 | user = IntegerField(db_column='user_id', null=True) 150 | 151 | class Meta: 152 | db_table = 'ci_builds' 153 | indexes = ( 154 | (('commit', 'name', 'ref', 'type'), False), 155 | (('commit', 'type', 'status'), False), 156 | (('created_at', 'stage_idx', 'commit'), False), 157 | (('project', 'commit'), False), 158 | (('type', 'ref', 'commit'), False), 159 | ) 160 | 161 | class CiCommits(BaseModel): 162 | before_sha = CharField(null=True) 163 | committed_at = DateTimeField(null=True) 164 | created_at = DateTimeField(null=True) 165 | gl_project = IntegerField(db_column='gl_project_id', index=True, null=True) 166 | project = IntegerField(db_column='project_id', index=True, null=True) 167 | push_data = TextField(null=True) 168 | ref = CharField(null=True) 169 | sha = CharField(index=True, null=True) 170 | tag = BooleanField(null=True) 171 | updated_at = DateTimeField(null=True) 172 | yaml_errors = TextField(null=True) 173 | 174 | class Meta: 175 | db_table = 'ci_commits' 176 | indexes = ( 177 | (('committed_at', 'id', 'project'), False), 178 | (('project', 'committed_at'), False), 179 | (('sha', 'project'), False), 180 | ) 181 | 182 | class CiEvents(BaseModel): 183 | created_at = DateTimeField(index=True, null=True) 184 | description = TextField(null=True) 185 | is_admin = IntegerField(index=True, null=True) 186 | project = IntegerField(db_column='project_id', index=True, null=True) 187 | updated_at = DateTimeField(null=True) 188 | user = IntegerField(db_column='user_id', null=True) 189 | 190 | class Meta: 191 | db_table = 'ci_events' 192 | 193 | class CiJobs(BaseModel): 194 | active = BooleanField() 195 | build_branches = BooleanField() 196 | build_tags = BooleanField() 197 | commands = TextField(null=True) 198 | created_at = DateTimeField(null=True) 199 | deleted_at = DateTimeField(index=True, null=True) 200 | job_type = CharField(null=True) 201 | name = CharField(null=True) 202 | project = IntegerField(db_column='project_id', index=True) 203 | refs = CharField(null=True) 204 | updated_at = DateTimeField(null=True) 205 | 206 | class Meta: 207 | db_table = 'ci_jobs' 208 | 209 | class CiProjects(BaseModel): 210 | allow_git_fetch = BooleanField() 211 | always_build = BooleanField() 212 | coverage_regex = CharField(null=True) 213 | created_at = DateTimeField(null=True) 214 | default_ref = CharField(null=True) 215 | email_add_pusher = BooleanField() 216 | email_only_broken_builds = BooleanField() 217 | email_recipients = CharField() 218 | generated_yaml_config = TextField(null=True) 219 | gitlab = IntegerField(db_column='gitlab_id', index=True, null=True) 220 | name = CharField(null=True) 221 | path = CharField(null=True) 222 | polling_interval = IntegerField(null=True) 223 | public = BooleanField() 224 | shared_runners_enabled = BooleanField(index=True, null=True) 225 | skip_refs = CharField(null=True) 226 | ssh_url_to_repo = CharField(null=True) 227 | timeout = IntegerField() 228 | token = CharField(null=True) 229 | updated_at = DateTimeField(null=True) 230 | 231 | class Meta: 232 | db_table = 'ci_projects' 233 | 234 | class CiRunnerProjects(BaseModel): 235 | created_at = DateTimeField(null=True) 236 | gl_project = IntegerField(db_column='gl_project_id', index=True, null=True) 237 | project = IntegerField(db_column='project_id', null=True) 238 | runner = IntegerField(db_column='runner_id', index=True) 239 | updated_at = DateTimeField(null=True) 240 | 241 | class Meta: 242 | db_table = 'ci_runner_projects' 243 | 244 | class CiRunners(BaseModel): 245 | active = BooleanField() 246 | architecture = CharField(null=True) 247 | contacted_at = DateTimeField(null=True) 248 | created_at = DateTimeField(null=True) 249 | description = CharField(index=True, null=True) 250 | is_shared = BooleanField(null=True) 251 | name = CharField(null=True) 252 | platform = CharField(null=True) 253 | revision = CharField(null=True) 254 | token = CharField(index=True, null=True) 255 | updated_at = DateTimeField(null=True) 256 | version = CharField(null=True) 257 | 258 | class Meta: 259 | db_table = 'ci_runners' 260 | 261 | class CiServices(BaseModel): 262 | active = BooleanField() 263 | created_at = DateTimeField(null=True) 264 | project = IntegerField(db_column='project_id', index=True) 265 | properties = TextField(null=True) 266 | title = CharField(null=True) 267 | type = CharField(null=True) 268 | updated_at = DateTimeField(null=True) 269 | 270 | class Meta: 271 | db_table = 'ci_services' 272 | 273 | class CiSessions(BaseModel): 274 | created_at = DateTimeField(null=True) 275 | data = TextField(null=True) 276 | session = CharField(db_column='session_id', index=True) 277 | updated_at = DateTimeField(index=True, null=True) 278 | 279 | class Meta: 280 | db_table = 'ci_sessions' 281 | 282 | class CiTaggings(BaseModel): 283 | context = CharField(null=True) 284 | created_at = DateTimeField(null=True) 285 | tag = IntegerField(db_column='tag_id', null=True) 286 | taggable = IntegerField(db_column='taggable_id', null=True) 287 | taggable_type = CharField(null=True) 288 | tagger = IntegerField(db_column='tagger_id', null=True) 289 | tagger_type = CharField(null=True) 290 | 291 | class Meta: 292 | db_table = 'ci_taggings' 293 | indexes = ( 294 | (('context', 'taggable_type', 'taggable'), False), 295 | (('tagger', 'context', 'tagger_type', 'tag', 'taggable', 'taggable_type'), True), 296 | ) 297 | 298 | class CiTags(BaseModel): 299 | name = CharField(null=True, unique=True) 300 | taggings_count = IntegerField(null=True) 301 | 302 | class Meta: 303 | db_table = 'ci_tags' 304 | 305 | class CiTriggerRequests(BaseModel): 306 | commit = IntegerField(db_column='commit_id', null=True) 307 | created_at = DateTimeField(null=True) 308 | trigger = IntegerField(db_column='trigger_id') 309 | updated_at = DateTimeField(null=True) 310 | variables = TextField(null=True) 311 | 312 | class Meta: 313 | db_table = 'ci_trigger_requests' 314 | 315 | class CiTriggers(BaseModel): 316 | created_at = DateTimeField(null=True) 317 | deleted_at = DateTimeField(index=True, null=True) 318 | gl_project = IntegerField(db_column='gl_project_id', index=True, null=True) 319 | project = IntegerField(db_column='project_id', null=True) 320 | token = CharField(null=True) 321 | updated_at = DateTimeField(null=True) 322 | 323 | class Meta: 324 | db_table = 'ci_triggers' 325 | 326 | class CiVariables(BaseModel): 327 | encrypted_value = TextField(null=True) 328 | encrypted_value_iv = CharField(null=True) 329 | encrypted_value_salt = CharField(null=True) 330 | gl_project = IntegerField(db_column='gl_project_id', index=True, null=True) 331 | key = CharField(null=True) 332 | project = IntegerField(db_column='project_id', null=True) 333 | value = TextField(null=True) 334 | 335 | class Meta: 336 | db_table = 'ci_variables' 337 | 338 | class CiWebHooks(BaseModel): 339 | created_at = DateTimeField(null=True) 340 | project = IntegerField(db_column='project_id') 341 | updated_at = DateTimeField(null=True) 342 | url = CharField() 343 | 344 | class Meta: 345 | db_table = 'ci_web_hooks' 346 | 347 | class DeployKeysProjects(BaseModel): 348 | created_at = DateTimeField(null=True) 349 | deploy_key = IntegerField(db_column='deploy_key_id') 350 | project = IntegerField(db_column='project_id', index=True) 351 | updated_at = DateTimeField(null=True) 352 | 353 | class Meta: 354 | db_table = 'deploy_keys_projects' 355 | 356 | class Emails(BaseModel): 357 | created_at = DateTimeField(null=True) 358 | email = CharField(unique=True) 359 | updated_at = DateTimeField(null=True) 360 | user = IntegerField(db_column='user_id', index=True) 361 | 362 | class Meta: 363 | db_table = 'emails' 364 | 365 | class Events(BaseModel): 366 | action = IntegerField(index=True, null=True) 367 | author = IntegerField(db_column='author_id', index=True, null=True) 368 | created_at = DateTimeField(index=True, null=True) 369 | data = TextField(null=True) 370 | project = IntegerField(db_column='project_id', index=True, null=True) 371 | target = IntegerField(db_column='target_id', index=True, null=True) 372 | target_type = CharField(index=True, null=True) 373 | title = CharField(null=True) 374 | updated_at = DateTimeField(null=True) 375 | 376 | class Meta: 377 | db_table = 'events' 378 | 379 | class ForkedProjectLinks(BaseModel): 380 | created_at = DateTimeField(null=True) 381 | forked_from_project = IntegerField(db_column='forked_from_project_id') 382 | forked_to_project = IntegerField(db_column='forked_to_project_id', unique=True) 383 | updated_at = DateTimeField(null=True) 384 | 385 | class Meta: 386 | db_table = 'forked_project_links' 387 | 388 | class Identities(BaseModel): 389 | created_at = DateTimeField(null=True) 390 | extern_uid = CharField(null=True) 391 | provider = CharField(null=True) 392 | updated_at = DateTimeField(null=True) 393 | user = IntegerField(db_column='user_id', index=True, null=True) 394 | 395 | class Meta: 396 | db_table = 'identities' 397 | indexes = ( 398 | (('id', 'created_at'), False), 399 | ) 400 | 401 | class Issues(BaseModel): 402 | assignee = IntegerField(db_column='assignee_id', index=True, null=True) 403 | author = IntegerField(db_column='author_id', index=True, null=True) 404 | branch_name = CharField(null=True) 405 | confidential = BooleanField(index=True, null=True) 406 | created_at = DateTimeField(index=True, null=True) 407 | deleted_at = DateTimeField(index=True, null=True) 408 | description = TextField(index=True, null=True) 409 | due_date = DateField(index=True, null=True) 410 | iid = IntegerField(null=True) 411 | milestone = IntegerField(db_column='milestone_id', index=True, null=True) 412 | moved_to = IntegerField(db_column='moved_to_id', null=True) 413 | position = IntegerField(null=True) 414 | project = IntegerField(db_column='project_id', index=True, null=True) 415 | state = CharField(index=True, null=True) 416 | title = CharField(index=True, null=True) 417 | updated_at = DateTimeField(null=True) 418 | updated_by = IntegerField(db_column='updated_by_id', null=True) 419 | 420 | class Meta: 421 | db_table = 'issues' 422 | indexes = ( 423 | (('id', 'created_at'), False), 424 | (('project', 'iid'), True), 425 | ) 426 | 427 | class Keys(BaseModel): 428 | created_at = DateTimeField(null=True) 429 | fingerprint = CharField(null=True) 430 | key = TextField(null=True) 431 | public = BooleanField() 432 | title = CharField(null=True) 433 | type = CharField(null=True) 434 | updated_at = DateTimeField(null=True) 435 | user = IntegerField(db_column='user_id', index=True, null=True) 436 | 437 | class Meta: 438 | db_table = 'keys' 439 | indexes = ( 440 | (('id', 'created_at'), False), 441 | ) 442 | 443 | class LabelLinks(BaseModel): 444 | created_at = DateTimeField(null=True) 445 | label = IntegerField(db_column='label_id', index=True, null=True) 446 | target = IntegerField(db_column='target_id', null=True) 447 | target_type = CharField(null=True) 448 | updated_at = DateTimeField(null=True) 449 | 450 | class Meta: 451 | db_table = 'label_links' 452 | indexes = ( 453 | (('target', 'target_type'), False), 454 | ) 455 | 456 | class Labels(BaseModel): 457 | color = CharField(null=True) 458 | created_at = DateTimeField(null=True) 459 | description = CharField(null=True) 460 | project = IntegerField(db_column='project_id', index=True, null=True) 461 | template = BooleanField(null=True) 462 | title = CharField(null=True) 463 | updated_at = DateTimeField(null=True) 464 | 465 | class Meta: 466 | db_table = 'labels' 467 | 468 | class LfsObjects(BaseModel): 469 | created_at = DateTimeField(null=True) 470 | file = CharField(null=True) 471 | oid = CharField(unique=True) 472 | size = BigIntegerField() 473 | updated_at = DateTimeField(null=True) 474 | 475 | class Meta: 476 | db_table = 'lfs_objects' 477 | 478 | class LfsObjectsProjects(BaseModel): 479 | created_at = DateTimeField(null=True) 480 | lfs_object = IntegerField(db_column='lfs_object_id') 481 | project = IntegerField(db_column='project_id', index=True) 482 | updated_at = DateTimeField(null=True) 483 | 484 | class Meta: 485 | db_table = 'lfs_objects_projects' 486 | 487 | class Members(BaseModel): 488 | access_level = IntegerField(index=True) 489 | created_at = DateTimeField(null=True) 490 | created_by = IntegerField(db_column='created_by_id', null=True) 491 | invite_accepted_at = DateTimeField(null=True) 492 | invite_email = CharField(null=True) 493 | invite_token = CharField(null=True, unique=True) 494 | notification_level = IntegerField() 495 | source = IntegerField(db_column='source_id') 496 | source_type = CharField() 497 | type = CharField(index=True, null=True) 498 | updated_at = DateTimeField(null=True) 499 | user = IntegerField(db_column='user_id', index=True, null=True) 500 | 501 | class Meta: 502 | db_table = 'members' 503 | indexes = ( 504 | (('id', 'created_at'), False), 505 | (('source', 'source_type'), False), 506 | ) 507 | 508 | class MergeRequestDiffs(BaseModel): 509 | base_commit_sha = CharField(null=True) 510 | created_at = DateTimeField(null=True) 511 | merge_request = IntegerField(db_column='merge_request_id', unique=True) 512 | real_size = CharField(null=True) 513 | st_commits = TextField(null=True) 514 | st_diffs = TextField(null=True) 515 | state = CharField(null=True) 516 | updated_at = DateTimeField(null=True) 517 | 518 | class Meta: 519 | db_table = 'merge_request_diffs' 520 | 521 | class MergeRequests(BaseModel): 522 | assignee = IntegerField(db_column='assignee_id', index=True, null=True) 523 | author = IntegerField(db_column='author_id', index=True, null=True) 524 | created_at = DateTimeField(index=True, null=True) 525 | deleted_at = DateTimeField(index=True, null=True) 526 | description = TextField(index=True, null=True) 527 | iid = IntegerField(null=True) 528 | locked_at = DateTimeField(null=True) 529 | merge_commit_sha = CharField(null=True) 530 | merge_error = CharField(null=True) 531 | merge_params = TextField(null=True) 532 | merge_status = CharField(null=True) 533 | merge_user = IntegerField(db_column='merge_user_id', null=True) 534 | merge_when_build_succeeds = BooleanField() 535 | milestone = IntegerField(db_column='milestone_id', index=True, null=True) 536 | position = IntegerField(null=True) 537 | source_branch = CharField(index=True) 538 | source_project = IntegerField(db_column='source_project_id', index=True) 539 | state = CharField(null=True) 540 | target_branch = CharField(index=True) 541 | target_project = IntegerField(db_column='target_project_id') 542 | title = CharField(index=True, null=True) 543 | updated_at = DateTimeField(null=True) 544 | updated_by = IntegerField(db_column='updated_by_id', null=True) 545 | 546 | class Meta: 547 | db_table = 'merge_requests' 548 | indexes = ( 549 | (('id', 'created_at'), False), 550 | (('target_project', 'iid'), True), 551 | ) 552 | 553 | class Milestones(BaseModel): 554 | created_at = DateTimeField(null=True) 555 | description = TextField(index=True, null=True) 556 | due_date = DateField(index=True, null=True) 557 | iid = IntegerField(null=True) 558 | project = IntegerField(db_column='project_id', index=True) 559 | state = CharField(null=True) 560 | title = CharField(index=True) 561 | updated_at = DateTimeField(null=True) 562 | 563 | class Meta: 564 | db_table = 'milestones' 565 | indexes = ( 566 | (('created_at', 'id'), False), 567 | (('project', 'iid'), True), 568 | ) 569 | 570 | class Namespaces(BaseModel): 571 | avatar = CharField(null=True) 572 | created_at = DateTimeField(null=True) 573 | description = CharField() 574 | name = CharField(index=True) 575 | owner = IntegerField(db_column='owner_id', index=True, null=True) 576 | path = CharField(index=True) 577 | share_with_group_lock = BooleanField(null=True) 578 | type = CharField(index=True, null=True) 579 | updated_at = DateTimeField(null=True) 580 | visibility_level = IntegerField(index=True) 581 | 582 | class Meta: 583 | db_table = 'namespaces' 584 | indexes = ( 585 | (('created_at', 'id'), False), 586 | ) 587 | 588 | class Notes(BaseModel): 589 | attachment = CharField(null=True) 590 | author = IntegerField(db_column='author_id', index=True, null=True) 591 | commit = CharField(db_column='commit_id', index=True, null=True) 592 | created_at = DateTimeField(index=True, null=True) 593 | is_award = BooleanField(index=True) 594 | line_code = CharField(index=True, null=True) 595 | note = TextField(index=True, null=True) 596 | noteable = IntegerField(db_column='noteable_id', null=True) 597 | noteable_type = CharField(index=True, null=True) 598 | project = IntegerField(db_column='project_id', index=True, null=True) 599 | st_diff = TextField(null=True) 600 | system = BooleanField() 601 | updated_at = DateTimeField(index=True, null=True) 602 | updated_by = IntegerField(db_column='updated_by_id', null=True) 603 | 604 | class Meta: 605 | db_table = 'notes' 606 | indexes = ( 607 | (('created_at', 'id'), False), 608 | (('noteable', 'noteable_type'), False), 609 | (('noteable_type', 'project'), False), 610 | ) 611 | 612 | class NotificationSettings(BaseModel): 613 | created_at = DateTimeField() 614 | level = IntegerField() 615 | source = IntegerField(db_column='source_id') 616 | source_type = CharField() 617 | updated_at = DateTimeField() 618 | user = IntegerField(db_column='user_id', index=True) 619 | 620 | class Meta: 621 | db_table = 'notification_settings' 622 | indexes = ( 623 | (('source', 'source_type'), False), 624 | ) 625 | 626 | class OauthAccessGrants(BaseModel): 627 | application = IntegerField(db_column='application_id') 628 | created_at = DateTimeField() 629 | expires_in = IntegerField() 630 | redirect_uri = TextField() 631 | resource_owner = IntegerField(db_column='resource_owner_id') 632 | revoked_at = DateTimeField(null=True) 633 | scopes = CharField(null=True) 634 | token = CharField(unique=True) 635 | 636 | class Meta: 637 | db_table = 'oauth_access_grants' 638 | 639 | class OauthAccessTokens(BaseModel): 640 | application = IntegerField(db_column='application_id', null=True) 641 | created_at = DateTimeField() 642 | expires_in = IntegerField(null=True) 643 | refresh_token = CharField(null=True, unique=True) 644 | resource_owner = IntegerField(db_column='resource_owner_id', index=True, null=True) 645 | revoked_at = DateTimeField(null=True) 646 | scopes = CharField(null=True) 647 | token = CharField(unique=True) 648 | 649 | class Meta: 650 | db_table = 'oauth_access_tokens' 651 | 652 | class OauthApplications(BaseModel): 653 | created_at = DateTimeField(null=True) 654 | name = CharField() 655 | owner = IntegerField(db_column='owner_id', null=True) 656 | owner_type = CharField(null=True) 657 | redirect_uri = TextField() 658 | scopes = CharField() 659 | secret = CharField() 660 | uid = CharField(unique=True) 661 | updated_at = DateTimeField(null=True) 662 | 663 | class Meta: 664 | db_table = 'oauth_applications' 665 | indexes = ( 666 | (('owner', 'owner_type'), False), 667 | ) 668 | 669 | class ProjectGroupLinks(BaseModel): 670 | created_at = DateTimeField(null=True) 671 | group_access = IntegerField() 672 | group = IntegerField(db_column='group_id') 673 | project = IntegerField(db_column='project_id') 674 | updated_at = DateTimeField(null=True) 675 | 676 | class Meta: 677 | db_table = 'project_group_links' 678 | 679 | class ProjectImportData(BaseModel): 680 | data = TextField(null=True) 681 | encrypted_credentials = TextField(null=True) 682 | encrypted_credentials_iv = CharField(null=True) 683 | encrypted_credentials_salt = CharField(null=True) 684 | project = IntegerField(db_column='project_id', null=True) 685 | 686 | class Meta: 687 | db_table = 'project_import_data' 688 | 689 | class Projects(BaseModel): 690 | archived = BooleanField() 691 | avatar = CharField(null=True) 692 | build_allow_git_fetch = BooleanField() 693 | build_coverage_regex = CharField(null=True) 694 | build_timeout = IntegerField() 695 | builds_enabled = BooleanField(index=True) 696 | ci = IntegerField(db_column='ci_id', index=True, null=True) 697 | commit_count = IntegerField(null=True) 698 | created_at = DateTimeField(null=True) 699 | creator = IntegerField(db_column='creator_id', index=True, null=True) 700 | description = TextField(index=True, null=True) 701 | import_error = TextField(null=True) 702 | import_source = CharField(null=True) 703 | import_status = CharField(null=True) 704 | import_type = CharField(null=True) 705 | import_url = CharField(null=True) 706 | issues_enabled = BooleanField() 707 | issues_tracker = CharField() 708 | issues_tracker_id = CharField(null=True) 709 | last_activity_at = DateTimeField(index=True, null=True) 710 | last_repository_check_at = DateTimeField(null=True) 711 | last_repository_check_failed = BooleanField(index=True, null=True) 712 | main_language = CharField(null=True) 713 | merge_requests_enabled = BooleanField() 714 | name = CharField(index=True, null=True) 715 | namespace = IntegerField(db_column='namespace_id', index=True, null=True) 716 | path = CharField(index=True, null=True) 717 | pending_delete = BooleanField(index=True, null=True) 718 | public_builds = BooleanField() 719 | pushes_since_gc = IntegerField(null=True) 720 | repository_size = FloatField(null=True) 721 | runners_token = CharField(index=True, null=True) 722 | shared_runners_enabled = BooleanField() 723 | snippets_enabled = BooleanField() 724 | star_count = IntegerField(index=True) 725 | updated_at = DateTimeField(null=True) 726 | visibility_level = IntegerField(index=True) 727 | wall_enabled = BooleanField() 728 | wiki_enabled = BooleanField() 729 | 730 | class Meta: 731 | db_table = 'projects' 732 | indexes = ( 733 | (('created_at', 'id'), False), 734 | (('shared_runners_enabled', 'builds_enabled'), False), 735 | ) 736 | 737 | class ProtectedBranches(BaseModel): 738 | created_at = DateTimeField(null=True) 739 | developers_can_push = BooleanField() 740 | name = CharField() 741 | project = IntegerField(db_column='project_id', index=True) 742 | updated_at = DateTimeField(null=True) 743 | 744 | class Meta: 745 | db_table = 'protected_branches' 746 | 747 | class Releases(BaseModel): 748 | created_at = DateTimeField(null=True) 749 | description = TextField(null=True) 750 | project = IntegerField(db_column='project_id', index=True, null=True) 751 | tag = CharField(null=True) 752 | updated_at = DateTimeField(null=True) 753 | 754 | class Meta: 755 | db_table = 'releases' 756 | indexes = ( 757 | (('tag', 'project'), False), 758 | ) 759 | 760 | class SchemaMigrations(BaseModel): 761 | version = CharField(unique=True) 762 | 763 | class Meta: 764 | db_table = 'schema_migrations' 765 | 766 | class SentNotifications(BaseModel): 767 | commit = CharField(db_column='commit_id', null=True) 768 | line_code = CharField(null=True) 769 | noteable = IntegerField(db_column='noteable_id', null=True) 770 | noteable_type = CharField(null=True) 771 | project = IntegerField(db_column='project_id', null=True) 772 | recipient = IntegerField(db_column='recipient_id', null=True) 773 | reply_key = CharField(unique=True) 774 | 775 | class Meta: 776 | db_table = 'sent_notifications' 777 | 778 | class Services(BaseModel): 779 | active = BooleanField() 780 | build_events = BooleanField() 781 | category = CharField(index=True) 782 | created_at = DateTimeField() 783 | default = BooleanField(index=True, null=True) 784 | issues_events = BooleanField(null=True) 785 | merge_requests_events = BooleanField(null=True) 786 | note_events = BooleanField() 787 | project = IntegerField(db_column='project_id', index=True, null=True) 788 | properties = TextField(null=True) 789 | push_events = BooleanField(null=True) 790 | tag_push_events = BooleanField(null=True) 791 | template = BooleanField(index=True, null=True) 792 | title = CharField(null=True) 793 | type = CharField(null=True) 794 | updated_at = DateTimeField() 795 | wiki_page_events = BooleanField(null=True) 796 | 797 | class Meta: 798 | db_table = 'services' 799 | indexes = ( 800 | (('id', 'created_at'), False), 801 | ) 802 | 803 | class Snippets(BaseModel): 804 | author = IntegerField(db_column='author_id', index=True) 805 | content = TextField(null=True) 806 | created_at = DateTimeField(index=True, null=True) 807 | file_name = CharField(index=True, null=True) 808 | project = IntegerField(db_column='project_id', index=True, null=True) 809 | title = CharField(index=True, null=True) 810 | type = CharField(null=True) 811 | updated_at = DateTimeField(index=True, null=True) 812 | visibility_level = IntegerField(index=True) 813 | 814 | class Meta: 815 | db_table = 'snippets' 816 | indexes = ( 817 | (('id', 'created_at'), False), 818 | ) 819 | 820 | class SpamLogs(BaseModel): 821 | created_at = DateTimeField() 822 | description = TextField(null=True) 823 | noteable_type = CharField(null=True) 824 | project = IntegerField(db_column='project_id', null=True) 825 | source_ip = CharField(null=True) 826 | title = CharField(null=True) 827 | updated_at = DateTimeField() 828 | user_agent = CharField(null=True) 829 | user = IntegerField(db_column='user_id', null=True) 830 | via_api = BooleanField(null=True) 831 | 832 | class Meta: 833 | db_table = 'spam_logs' 834 | 835 | class Subscriptions(BaseModel): 836 | created_at = DateTimeField(null=True) 837 | subscribable = IntegerField(db_column='subscribable_id', null=True) 838 | subscribable_type = CharField(null=True) 839 | subscribed = BooleanField(null=True) 840 | updated_at = DateTimeField(null=True) 841 | user = IntegerField(db_column='user_id', null=True) 842 | 843 | class Meta: 844 | db_table = 'subscriptions' 845 | indexes = ( 846 | (('user', 'subscribable', 'subscribable_type'), True), 847 | ) 848 | 849 | class Taggings(BaseModel): 850 | context = CharField(null=True) 851 | created_at = DateTimeField(null=True) 852 | tag = IntegerField(db_column='tag_id', null=True) 853 | taggable = IntegerField(db_column='taggable_id', null=True) 854 | taggable_type = CharField(null=True) 855 | tagger = IntegerField(db_column='tagger_id', null=True) 856 | tagger_type = CharField(null=True) 857 | 858 | class Meta: 859 | db_table = 'taggings' 860 | indexes = ( 861 | (('tag', 'taggable', 'taggable_type', 'tagger', 'tagger_type', 'context'), True), 862 | (('taggable', 'taggable_type', 'context'), False), 863 | ) 864 | 865 | class Tags(BaseModel): 866 | name = CharField(null=True, unique=True) 867 | taggings_count = IntegerField(null=True) 868 | 869 | class Meta: 870 | db_table = 'tags' 871 | 872 | class Todos(BaseModel): 873 | action = IntegerField() 874 | author = IntegerField(db_column='author_id', index=True, null=True) 875 | commit = CharField(db_column='commit_id', index=True, null=True) 876 | created_at = DateTimeField(null=True) 877 | note = IntegerField(db_column='note_id', index=True, null=True) 878 | project = IntegerField(db_column='project_id', index=True) 879 | state = CharField(index=True) 880 | target = IntegerField(db_column='target_id', null=True) 881 | target_type = CharField() 882 | updated_at = DateTimeField(null=True) 883 | user = IntegerField(db_column='user_id', index=True) 884 | 885 | class Meta: 886 | db_table = 'todos' 887 | indexes = ( 888 | (('target_type', 'target'), False), 889 | ) 890 | 891 | class Users(BaseModel): 892 | admin = BooleanField(index=True) 893 | authentication_token = CharField(null=True, unique=True) 894 | avatar = CharField(null=True) 895 | bio = CharField(null=True) 896 | can_create_group = BooleanField() 897 | can_create_team = BooleanField() 898 | color_scheme = IntegerField(db_column='color_scheme_id') 899 | confirmation_sent_at = DateTimeField(null=True) 900 | confirmation_token = CharField(null=True, unique=True) 901 | confirmed_at = DateTimeField(null=True) 902 | consumed_timestep = IntegerField(null=True) 903 | created_at = DateTimeField(null=True) 904 | created_by = IntegerField(db_column='created_by_id', null=True) 905 | current_sign_in_at = DateTimeField(index=True, null=True) 906 | current_sign_in_ip = CharField(null=True) 907 | dashboard = IntegerField(null=True) 908 | email = CharField(index=True) 909 | encrypted_otp_secret = CharField(null=True) 910 | encrypted_otp_secret_iv = CharField(null=True) 911 | encrypted_otp_secret_salt = CharField(null=True) 912 | encrypted_password = CharField() 913 | external = BooleanField(null=True) 914 | failed_attempts = IntegerField(null=True) 915 | hide_no_password = BooleanField(null=True) 916 | hide_no_ssh_key = BooleanField(null=True) 917 | hide_project_limit = BooleanField(null=True) 918 | last_credential_check_at = DateTimeField(null=True) 919 | last_sign_in_at = DateTimeField(null=True) 920 | last_sign_in_ip = CharField(null=True) 921 | layout = IntegerField(null=True) 922 | ldap_email = BooleanField() 923 | linkedin = CharField() 924 | location = CharField(null=True) 925 | locked_at = DateTimeField(null=True) 926 | name = CharField(index=True, null=True) 927 | notification_email = CharField(null=True) 928 | notification_level = IntegerField() 929 | otp_backup_codes = TextField(null=True) 930 | otp_grace_period_started_at = DateTimeField(null=True) 931 | otp_required_for_login = BooleanField() 932 | password_automatically_set = BooleanField(null=True) 933 | password_expires_at = DateTimeField(null=True) 934 | project_view = IntegerField(null=True) 935 | projects_limit = IntegerField(null=True) 936 | public_email = CharField() 937 | remember_created_at = DateTimeField(null=True) 938 | reset_password_sent_at = DateTimeField(null=True) 939 | reset_password_token = CharField(null=True, unique=True) 940 | sign_in_count = IntegerField(null=True) 941 | skype = CharField() 942 | state = CharField(null=True) 943 | theme = IntegerField(db_column='theme_id') 944 | twitter = CharField() 945 | unconfirmed_email = CharField(null=True) 946 | unlock_token = CharField(null=True) 947 | updated_at = DateTimeField(null=True) 948 | username = CharField(index=True, null=True) 949 | website_url = CharField() 950 | 951 | class Meta: 952 | db_table = 'users' 953 | indexes = ( 954 | (('created_at', 'id'), False), 955 | ) 956 | 957 | class UsersStarProjects(BaseModel): 958 | created_at = DateTimeField(null=True) 959 | project = IntegerField(db_column='project_id', index=True) 960 | updated_at = DateTimeField(null=True) 961 | user = IntegerField(db_column='user_id', index=True) 962 | 963 | class Meta: 964 | db_table = 'users_star_projects' 965 | indexes = ( 966 | (('project', 'user'), True), 967 | ) 968 | 969 | class WebHooks(BaseModel): 970 | build_events = BooleanField() 971 | created_at = DateTimeField(null=True) 972 | enable_ssl_verification = BooleanField(null=True) 973 | issues_events = BooleanField() 974 | merge_requests_events = BooleanField() 975 | note_events = BooleanField() 976 | project = IntegerField(db_column='project_id', index=True, null=True) 977 | push_events = BooleanField() 978 | service = IntegerField(db_column='service_id', null=True) 979 | tag_push_events = BooleanField(null=True) 980 | type = CharField(null=True) 981 | updated_at = DateTimeField(null=True) 982 | url = CharField(null=True) 983 | wiki_page_events = BooleanField() 984 | 985 | class Meta: 986 | db_table = 'web_hooks' 987 | indexes = ( 988 | (('id', 'created_at'), False), 989 | ) 990 | 991 | -------------------------------------------------------------------------------- /licences/GPL.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /licences/LGPL.txt: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | 167 | -------------------------------------------------------------------------------- /migrate.cfg.example: -------------------------------------------------------------------------------- 1 | # Sample configuration file, update to meet your needs 2 | 3 | [source] 4 | 5 | # URL of the XML-RPC trac endpoint 6 | url: http://username:password@example.com/trac/login/xmlrpc 7 | 8 | 9 | [target] 10 | 11 | # Trac to GitLab user mappings 12 | usernames = { 13 | 'trac1': 'git1', 14 | 'trac2': 'git2' 15 | } 16 | 17 | # Fallback user to use if not present in mapping 18 | default_user: bot 19 | 20 | # project's path 21 | project_name: foo/bar 22 | 23 | # Method to use: api or direct 24 | method: direct 25 | 26 | # URL of the GitLab web API (if method = api) 27 | url: https://gitlab.example.com/api/v3 28 | 29 | # API access token (if method = api) 30 | access_token: secretsecret 31 | 32 | # Uncomment to verify SSL keys (default = no ) (if method = api) 33 | # ssl_verify: yes 34 | 35 | # Overwrite existing project's data in the database (if method = direct, default = yes) 36 | overwrite: yes 37 | 38 | # database name (if method = direct) 39 | db-name: gitlabhq_production 40 | 41 | # database user (if method = direct) 42 | db-user: gitlab 43 | 44 | # database password (if method = direct) 45 | # Not set in recent GitLab installation. You need to create a PostgreSQL user for the 46 | # user that runs the migration and map it to the gitlab user in /var/opt/gitlab/postgresql/data/pg_ident.conf 47 | db-password: 48 | 49 | # database socket path (if method = direct) 50 | # Override this if not using the Gitlab builtin PostgreSQL, to specify the path 51 | # to the PostgreSQL control socket (e.g. /run/postgresql) 52 | db-path: /var/opt/gitlab/postgresql/ 53 | 54 | # Path to the gitlab uploads directory (if method = direct) 55 | uploads: /var/opt/gitlab/gitlab-rails/uploads 56 | 57 | 58 | [wiki] 59 | 60 | # Should we migrate the wiki (default = yes) 61 | # migrate: yes 62 | 63 | # Comma separated list of authors to exclude (default=trac) 64 | # exclude_authors: trac 65 | 66 | # Directory where the wiki pages should be written 67 | target-directory: /tmp/test.wiki/ 68 | 69 | 70 | [issues] 71 | 72 | # Should we migrate the issues (default = yes) 73 | # migrate: yes 74 | 75 | # If defined, import only these issues 76 | # only_issues: [ 509, 561, 564, 626, 631, 792, 830] 77 | 78 | # If defined, do not import these issues 79 | # blacklist_issues: [ 268, 843 ] 80 | 81 | # Add a label to all migrated issues 82 | # add_label: Websites 83 | 84 | # Trac component to migrate issues from 85 | component_filter: [ 86 | u'Vorbis Core - documentation', 87 | u'Vorbis Core - libvorbis', 88 | u'Vorbis Core - libvorbisenc', 89 | u'Vorbis Core - libvorbisfile' 90 | ] 91 | 92 | # Migrate keywords 93 | migrate_keywords: no 94 | 95 | # Migrate milestones 96 | migrate_milestones: no 97 | 98 | # Add the trac component as label to the Gitlab issue 99 | add_component_as_label: no 100 | 101 | # Add a header with original poster and date to issues and comments 102 | # (useful for api mode where this information is lost) 103 | add_header: no 104 | -------------------------------------------------------------------------------- /migrate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # vim: autoindent tabstop=4 shiftwidth=4 expandtab softtabstop=4 filetype=python fileencoding=utf-8 3 | ''' 4 | Copyright © 2013 5 | Eric van der Vlist 6 | Jens Neuhalfen 7 | See license information at the bottom of this file 8 | ''' 9 | 10 | import re 11 | import os 12 | import ConfigParser 13 | import ast 14 | from datetime import datetime 15 | from re import MULTILINE 16 | import xmlrpclib 17 | import trac2down 18 | 19 | """ 20 | What 21 | ===== 22 | 23 | This script migrates issues from trac to gitlab. 24 | 25 | License 26 | ======== 27 | 28 | License: http://www.wtfpl.net/ 29 | 30 | Requirements 31 | ============== 32 | 33 | * Python 2, xmlrpclib, requests 34 | * Trac with xmlrpc plugin enabled 35 | * Peewee (direct method) 36 | * GitLab 37 | 38 | """ 39 | 40 | default_config = { 41 | 'ssl_verify': 'no', 42 | 'migrate' : 'true', 43 | 'overwrite' : 'true', 44 | 'exclude_authors' : 'trac', 45 | 'uploads' : '' 46 | } 47 | 48 | config = ConfigParser.ConfigParser(default_config) 49 | config.read('migrate.cfg') 50 | 51 | 52 | trac_url = config.get('source', 'url') 53 | dest_project_name = config.get('target', 'project_name') 54 | uploads_path = config.get('target', 'uploads') 55 | 56 | method = config.get('target', 'method') 57 | 58 | 59 | if (method == 'api'): 60 | from gitlab_api import Connection, Issues, Notes, Milestones 61 | print("importing api") 62 | gitlab_url = config.get('target', 'url') 63 | gitlab_access_token = config.get('target', 'access_token') 64 | dest_ssl_verify = config.getboolean('target', 'ssl_verify') 65 | overwrite = False 66 | elif (method == 'direct'): 67 | print("importing direct") 68 | from gitlab_direct import Connection, Issues, Notes, Milestones 69 | db_name = config.get('target', 'db-name') 70 | db_password = config.get('target', 'db-password') 71 | db_user = config.get('target', 'db-user') 72 | db_path = config.get('target', 'db-path') 73 | overwrite = config.getboolean('target', 'overwrite') 74 | 75 | 76 | users_map = ast.literal_eval(config.get('target', 'usernames')) 77 | default_user = config.get('target', 'default_user') 78 | must_convert_issues = config.getboolean('issues', 'migrate') 79 | only_issues = None 80 | if config.has_option('issues', 'only_issues'): 81 | only_issues = ast.literal_eval(config.get('issues', 'only_issues')) 82 | blacklist_issues = None 83 | if config.has_option('issues', 'blacklist_issues'): 84 | blacklist_issues = ast.literal_eval(config.get('issues', 'blacklist_issues')) 85 | must_convert_wiki = config.getboolean('wiki', 'migrate') 86 | migrate_keywords = config.getboolean('issues', 'migrate_keywords') 87 | migrate_milestones = config.getboolean('issues', 'migrate_milestones') 88 | add_component_as_label = config.getboolean('issues', 'add_component_as_label') 89 | component_filter = None 90 | if config.has_option('issues', 'component_filter'): 91 | component_filter = ast.literal_eval(config.get('issues', 'component_filter')) 92 | add_label = None 93 | if config.has_option('issues', 'add_label'): 94 | add_label = config.get('issues', 'add_label') 95 | add_issue_header = config.getboolean('issues', 'add_header') 96 | 97 | pattern_changeset = r'(?sm)In \[changeset:"([^"/]+?)(?:/[^"]+)?"\]:\n\{\{\{(\n#![^\n]+)?\n(.*?)\n\}\}\}' 98 | matcher_changeset = re.compile(pattern_changeset) 99 | 100 | pattern_changeset2 = r'\[changeset:([a-zA-Z0-9]+)\]' 101 | matcher_changeset2 = re.compile(pattern_changeset2) 102 | 103 | 104 | def convert_xmlrpc_datetime(dt): 105 | return datetime.strptime(str(dt), "%Y%m%dT%H:%M:%S") 106 | 107 | 108 | def format_changeset_comment(m): 109 | return 'In changeset ' + m.group(1) + ':\n> ' + m.group(3).replace('\n', '\n> ') 110 | 111 | 112 | def fix_wiki_syntax(markup): 113 | markup = matcher_changeset.sub(format_changeset_comment, markup) 114 | markup = matcher_changeset2.sub(r'\1', markup) 115 | return markup 116 | 117 | def get_dest_project_id(dest, dest_project_name): 118 | dest_project = dest.project_by_name(dest_project_name) 119 | if not dest_project: 120 | raise ValueError("Project '%s' not found" % dest_project_name) 121 | return dest_project["id"] 122 | 123 | def get_dest_milestone_id(dest, dest_project_id,milestone_name): 124 | dest_milestone_id = dest.milestone_by_name(dest_project_id,milestone_name ) 125 | if not dest_milestone_id: 126 | raise ValueError("Milestone '%s' of project '%s' not found" % (milestone_name, dest_project_name)) 127 | return dest_milestone_id["id"] 128 | 129 | def create_issue_header(author, created, updated=None, is_comment=False): 130 | if not add_issue_header: 131 | return '' 132 | 133 | intro = 'Original comment posted' if is_comment else 'Original issue created' 134 | modified = ', last modified on {}'.format(convert_xmlrpc_datetime(updated).strftime('%Y-%m-%d at %X')) if updated else '' 135 | 136 | return '> {} by {} on {}{}\n\n---\n'.format( 137 | intro, 138 | '@' + users_map[author] if author in users_map else '**' + author + '**', 139 | convert_xmlrpc_datetime(created).strftime('%Y-%m-%d at %X'), 140 | modified) 141 | 142 | def convert_issues(source, dest, dest_project_id, only_issues=None, blacklist_issues=None): 143 | if overwrite and (method == 'direct'): 144 | dest.clear_issues(dest_project_id) 145 | 146 | milestone_map_id={} 147 | 148 | if migrate_milestones: 149 | milestone_id=0; 150 | for milestone_name in source.ticket.milestone.getAll(): 151 | milestone = source.ticket.milestone.get(milestone_name) 152 | print(milestone) 153 | new_milestone = Milestones( 154 | description = trac2down.convert(fix_wiki_syntax(milestone['description']), '/milestones/', False), 155 | title = milestone['name'], 156 | state = 'active' if str(milestone['completed']) == '0' else 'closed' 157 | ) 158 | if method == 'direct': 159 | new_milestone.project = dest_project_id 160 | if milestone['due']: 161 | new_milestone.due_date = convert_xmlrpc_datetime(milestone['due']) 162 | new_milestone = dest.create_milestone(dest_project_id, new_milestone) 163 | if new_milestone.id: 164 | milestone_map_id[milestone_name] = new_milestone.id 165 | milestone_id = new_milestone.id + 1; 166 | else: 167 | milestone_map_id[milestone_name] = milestone_id; 168 | milestone_id = milestone_id + 1; 169 | 170 | get_all_tickets = xmlrpclib.MultiCall(source) 171 | 172 | for ticket in source.ticket.query("max=0&order=id"): 173 | get_all_tickets.ticket.get(ticket) 174 | 175 | for src_ticket in get_all_tickets(): 176 | src_ticket_id = src_ticket[0] 177 | if only_issues and src_ticket_id not in only_issues: 178 | print("SKIP unwanted ticket #%s" % src_ticket_id) 179 | continue 180 | if blacklist_issues and src_ticket_id in blacklist_issues: 181 | print("SKIP blacklisted ticket #%s" % src_ticket_id) 182 | continue 183 | 184 | src_ticket_data = src_ticket[3] 185 | src_ticket_reporter = src_ticket_data['reporter'] 186 | src_ticket_priority = 'normal' 187 | if 'priority' in src_ticket_data: 188 | src_ticket_priority = src_ticket_data['priority'] 189 | src_ticket_resolution = src_ticket_data['resolution'] 190 | src_ticket_severity = src_ticket_data.get('severity') 191 | src_ticket_status = src_ticket_data['status'] 192 | src_ticket_component = src_ticket_data.get('component', '') 193 | src_ticket_keywords = src_ticket_data['keywords'] 194 | if (component_filter and src_ticket_component not in component_filter): 195 | continue 196 | 197 | new_labels = [] 198 | if src_ticket_priority == 'high': 199 | new_labels.append('high priority') 200 | elif src_ticket_priority == 'medium': 201 | pass 202 | elif src_ticket_priority == 'low': 203 | new_labels.append('low priority') 204 | 205 | if src_ticket_resolution == '': 206 | # active ticket 207 | pass 208 | elif src_ticket_resolution == 'fixed': 209 | pass 210 | elif src_ticket_resolution == 'invalid': 211 | new_labels.append('invalid') 212 | elif src_ticket_resolution == 'wontfix': 213 | new_labels.append("won't fix") 214 | elif src_ticket_resolution == 'duplicate': 215 | new_labels.append('duplicate') 216 | elif src_ticket_resolution == 'worksforme': 217 | new_labels.append('works for me') 218 | 219 | if src_ticket_severity == 'high': 220 | new_labels.append('critical') 221 | elif src_ticket_severity == 'medium': 222 | pass 223 | elif src_ticket_severity == 'low': 224 | new_labels.append("minor") 225 | 226 | # Current ticket types are: enhancement, defect, compilation, performance, style, scientific, task, requirement 227 | # new_labels.append(src_ticket_type) 228 | 229 | if add_component_as_label and src_ticket_component != '': 230 | for component in src_ticket_component.split(','): 231 | new_labels.append(component.strip()) 232 | 233 | if add_label: 234 | new_labels.append(add_label) 235 | 236 | if src_ticket_keywords != '' and migrate_keywords: 237 | for keyword in src_ticket_keywords.split(','): 238 | new_labels.append(keyword.strip()) 239 | 240 | print("new labels: %s" % new_labels) 241 | 242 | new_state = '' 243 | if src_ticket_status == 'new': 244 | new_state = 'opened' 245 | elif src_ticket_status == 'assigned': 246 | new_state = 'opened' 247 | elif src_ticket_status == 'reopened': 248 | new_state = 'reopened' 249 | elif src_ticket_status == 'closed': 250 | new_state = 'closed' 251 | else: 252 | print("!!! unknown ticket status: %s" % src_ticket_status) 253 | 254 | new_description = (create_issue_header(author=src_ticket_reporter, created=src_ticket[1], updated=src_ticket[2]) 255 | + trac2down.convert(fix_wiki_syntax(src_ticket_data['description']), '/issues/', False)) 256 | 257 | # Minimal parameters 258 | new_issue = Issues( 259 | title=(src_ticket_data['summary'][:245] + '...') if len(src_ticket_data['summary']) > 245 else src_ticket_data['summary'], 260 | description=new_description, 261 | state=new_state, 262 | labels=",".join(new_labels) 263 | ) 264 | 265 | if src_ticket_data['owner'] != '': 266 | try: 267 | new_issue.assignee = dest.get_user_id(users_map[src_ticket_data['owner']]) 268 | except KeyError: 269 | new_issue.assignee = dest.get_user_id(default_user) 270 | # Additional parameters for direct access 271 | if (method == 'direct'): 272 | new_issue.created_at = convert_xmlrpc_datetime(src_ticket[1]) 273 | new_issue.updated_at = convert_xmlrpc_datetime(src_ticket[2]) 274 | new_issue.project = dest_project_id 275 | new_issue.state = new_state 276 | new_issue.author = dest.get_user_id(users_map.get(src_ticket_reporter, default_user)) 277 | if overwrite: 278 | new_issue.iid = src_ticket_id 279 | else: 280 | new_issue.iid = dest.get_issues_iid(dest_project_id) 281 | # Set correct issue id 282 | new_issue.iid = src_ticket_id 283 | if 'milestone' in src_ticket_data: 284 | milestone = src_ticket_data['milestone'] 285 | if milestone and milestone in milestone_map_id: 286 | new_issue.milestone = milestone_map_id[milestone] 287 | new_ticket = dest.create_issue(dest_project_id, new_issue) 288 | 289 | changelog = source.ticket.changeLog(src_ticket_id) 290 | is_attachment = False 291 | attachment = None 292 | binary_attachment = None 293 | newowner = None 294 | for change in changelog: 295 | # New line 296 | change_time = str(convert_xmlrpc_datetime(change[0])) 297 | change_type = change[2] 298 | print((" %s by %s (%s -> %s)" % (change_type, change[1], change[3][:40].replace("\n", " "), change[4][:40].replace("\n", " "))).encode("ascii", "replace")) 299 | #assert attachment is None or change_type == "comment", "an attachment must be followed by a comment" 300 | author = dest.get_user_id(users_map[change[1]]) 301 | if change_type == "attachment": 302 | # The attachment will be described in the next change! 303 | is_attachment = True 304 | attachment = change 305 | if (change_type == "comment"): 306 | desc = change[4] 307 | if (desc == '' and is_attachment == False): 308 | continue 309 | if (desc != ''): 310 | desc = fix_wiki_syntax(change[4]) 311 | note = Notes( 312 | note=create_issue_header(author=change[1], created=change[0], is_comment=True) + trac2down.convert(desc, '/issues/', False) 313 | ) 314 | if attachment is not None : 315 | note.attachment_name = attachment[4] # name of attachment 316 | binary_attachment = source.ticket.getAttachment(src_ticket_id, attachment[4].encode('utf8')).data 317 | try: 318 | note.author = dest.get_user_id(users_map[change[1]]) 319 | if note.author == None: 320 | note.author = dest.get_user_id(default_user) 321 | except KeyError: 322 | note.author = dest.get_user_id(default_user) 323 | if (method == 'direct'): 324 | note.created_at = convert_xmlrpc_datetime(change[0]) 325 | note.updated_at = convert_xmlrpc_datetime(change[0]) 326 | try: 327 | note.author = dest.get_user_id(users_map[change[1]]) 328 | except KeyError: 329 | note.author = dest.get_user_id(default_user) 330 | if (is_attachment): 331 | note.attachment = attachment[4] 332 | binary_attachment = source.ticket.getAttachment(src_ticket_id, attachment[4].encode('utf8')).data 333 | dest.comment_issue(dest_project_id, new_ticket, note, binary_attachment) 334 | is_attachment = False 335 | if change_type == "status" : 336 | if change[3] == 'vendor' : 337 | # remove label 'vendor' 338 | new_ticket.labels.remove('vendor') 339 | # workaround #3 dest.update_issue_property(dest_project_id, issue, author, change_time, 'labels') 340 | 341 | # we map here the various statii we have in trac to just 2 statii in gitlab (open or close), so loose some information 342 | if change[4] in ['new', 'assigned', 'analyzed', 'vendor', 'reopened'] : 343 | newstate = 'open' 344 | elif change[4] in ['closed'] : 345 | newstate = 'closed' 346 | else : 347 | raise(" unknown ticket status: " + change[4]) 348 | 349 | if new_ticket.state != newstate : 350 | new_ticket.state = newstate 351 | 352 | if change[4] == 'vendor' : 353 | # add label 'vendor' 354 | new_ticket.labels.append('vendor') 355 | dest.ensure_label(dest_project_id, 'vendor', labelcolor['vendor']) 356 | 357 | if newstate == 'closed' : 358 | dest.close_issue(dest_project_id,new_ticket.iid); 359 | 360 | dest.comment_issue(dest_project_id, new_ticket, Notes(note = 'Changing status from ' + change[3] + ' to ' + change[4] + '.', created_at = change_time, author = author), binary_attachment) 361 | 362 | def convert_wiki(source, dest, dest_project_id): 363 | if overwrite and (method == 'direct'): 364 | dest.clear_wiki_attachments(dest_project_id) 365 | 366 | exclude_authors = [a.strip() for a in config.get('wiki', 'exclude_authors').split(',')] 367 | target_directory = config.get('wiki', 'target-directory') 368 | server = xmlrpclib.MultiCall(source) 369 | for name in source.wiki.getAllPages(): 370 | info = source.wiki.getPageInfo(name) 371 | if (info['author'] not in exclude_authors): 372 | page = source.wiki.getPage(name) 373 | print("Page %s:%s" % (name, info)) 374 | if (name == 'WikiStart'): 375 | name = 'home' 376 | converted = trac2down.convert(page, os.path.dirname('/wikis/%s' % name)) 377 | try: 378 | wikiauthor = dest.get_user_id(users_map[info['author']]) 379 | if wikiauthor == None: 380 | wikiauthor = dest.get_user_id(default_user) 381 | except KeyError: 382 | wikiauthor = dest.get_user_id(default_user) 383 | dest.create_wiki(dest_project_id, converted, name, wikiauthor) 384 | if method == 'direct': 385 | for attachment in source.wiki.listAttachments(name): 386 | print(attachment) 387 | binary_attachment = source.wiki.getAttachment(attachment).data 388 | try: 389 | attachment_path = dest.create_wiki_attachment(dest_project_id, users_map[info['author']], convert_xmlrpc_datetime(info['lastModified']), attachment, binary_attachment) 390 | except KeyError: 391 | attachment_path = dest.create_wiki_attachment(dest_project_id, default_user, convert_xmlrpc_datetime(info['lastModified']), attachment, binary_attachment) 392 | attachment_name = attachment.split('/')[-1] 393 | converted = converted.replace(r'](%s)' % attachment_name, r'](%s)' % os.path.relpath(attachment_path, '/namespace/project/wiki/page')) 394 | trac2down.save_file(converted, name, info['version'], info['lastModified'], info['author'], target_directory) 395 | 396 | 397 | if __name__ == "__main__": 398 | if method == 'api': 399 | dest = Connection(gitlab_url,gitlab_access_token,dest_ssl_verify) 400 | elif method == 'direct': 401 | dest = Connection(db_name, db_user, db_password, db_path, uploads_path) 402 | 403 | source = xmlrpclib.ServerProxy(trac_url) 404 | dest_project_id = get_dest_project_id(dest, dest_project_name) 405 | 406 | if must_convert_issues: 407 | convert_issues(source, dest, dest_project_id, only_issues=only_issues, blacklist_issues=blacklist_issues) 408 | 409 | if must_convert_wiki: 410 | convert_wiki(source, dest, dest_project_id) 411 | 412 | 413 | ''' 414 | This file is part of . 415 | 416 | This sotfware is free software: you can redistribute it and/or modify 417 | it under the terms of the GNU Lesser General Public License as published by 418 | the Free Software Foundation, either version 3 of the License, or 419 | (at your option) any later version. 420 | 421 | This sotfware is distributed in the hope that it will be useful, 422 | but WITHOUT ANY WARRANTY; without even the implied warranty of 423 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 424 | GNU Lesser General Public License for more details. 425 | 426 | You should have received a copy of the GNU Lesser General Public License 427 | along with this library. If not, see . 428 | ''' 429 | -------------------------------------------------------------------------------- /pwiz.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import datetime 4 | import sys 5 | from getpass import getpass 6 | from optparse import OptionParser 7 | 8 | from peewee import * 9 | from peewee import print_ 10 | from peewee import __version__ as peewee_version 11 | from playhouse.reflection import * 12 | 13 | TEMPLATE = """from peewee import * 14 | 15 | database = %s('%s', **%s) 16 | 17 | class UnknownField(object): 18 | pass 19 | 20 | class BaseModel(Model): 21 | class Meta: 22 | database = database 23 | """ 24 | 25 | DATABASE_ALIASES = { 26 | MySQLDatabase: ['mysql', 'mysqldb'], 27 | PostgresqlDatabase: ['postgres', 'postgresql'], 28 | SqliteDatabase: ['sqlite', 'sqlite3'], 29 | } 30 | 31 | DATABASE_MAP = dict((value, key) 32 | for key in DATABASE_ALIASES 33 | for value in DATABASE_ALIASES[key]) 34 | 35 | def make_introspector(database_type, database_name, **kwargs): 36 | if database_type not in DATABASE_MAP: 37 | err('Unrecognized database, must be one of: %s' % 38 | ', '.join(DATABASE_MAP.keys())) 39 | sys.exit(1) 40 | 41 | schema = kwargs.pop('schema', None) 42 | DatabaseClass = DATABASE_MAP[database_type] 43 | db = DatabaseClass(database_name, **kwargs) 44 | return Introspector.from_database(db, schema=schema) 45 | 46 | def print_models(introspector, tables=None, preserve_order=False): 47 | database = introspector.introspect(table_names=tables) 48 | 49 | print_(TEMPLATE % ( 50 | introspector.get_database_class().__name__, 51 | introspector.get_database_name(), 52 | repr(introspector.get_database_kwargs()))) 53 | 54 | def _print_table(table, seen, accum=None): 55 | accum = accum or [] 56 | foreign_keys = database.foreign_keys[table] 57 | for foreign_key in foreign_keys: 58 | dest = foreign_key.dest_table 59 | 60 | # In the event the destination table has already been pushed 61 | # for printing, then we have a reference cycle. 62 | if dest in accum and table not in accum: 63 | print_('# Possible reference cycle: %s' % dest) 64 | 65 | # If this is not a self-referential foreign key, and we have 66 | # not already processed the destination table, do so now. 67 | if dest not in seen and dest not in accum: 68 | seen.add(dest) 69 | if dest != table: 70 | _print_table(dest, seen, accum + [table]) 71 | 72 | print_('class %s(BaseModel):' % database.model_names[table]) 73 | columns = database.columns[table].items() 74 | if not preserve_order: 75 | columns = sorted(columns) 76 | primary_keys = database.primary_keys[table] 77 | for name, column in columns: 78 | skip = all([ 79 | name in primary_keys, 80 | name == 'id', 81 | len(primary_keys) == 1, 82 | column.field_class in introspector.pk_classes]) 83 | if skip: 84 | continue 85 | if column.primary_key and len(primary_keys) > 1: 86 | # If we have a CompositeKey, then we do not want to explicitly 87 | # mark the columns as being primary keys. 88 | column.primary_key = False 89 | 90 | print_(' %s' % column.get_field()) 91 | 92 | print_('') 93 | print_(' class Meta:') 94 | print_(' db_table = \'%s\'' % table) 95 | multi_column_indexes = database.multi_column_indexes(table) 96 | if multi_column_indexes: 97 | print_(' indexes = (') 98 | for fields, unique in sorted(multi_column_indexes): 99 | print_(' ((%s), %s),' % ( 100 | ', '.join("'%s'" % field for field in fields), 101 | unique, 102 | )) 103 | print_(' )') 104 | 105 | if introspector.schema: 106 | print_(' schema = \'%s\'' % introspector.schema) 107 | if len(primary_keys) > 1: 108 | pk_field_names = sorted([ 109 | field.name for col, field in columns 110 | if col in primary_keys]) 111 | pk_list = ', '.join("'%s'" % pk for pk in pk_field_names) 112 | print_(' primary_key = CompositeKey(%s)' % pk_list) 113 | print_('') 114 | 115 | seen.add(table) 116 | 117 | seen = set() 118 | for table in sorted(database.model_names.keys()): 119 | if table not in seen: 120 | if not tables or table in tables: 121 | _print_table(table, seen) 122 | 123 | def print_header(cmd_line, introspector): 124 | timestamp = datetime.datetime.now() 125 | print_('# Code generated by:') 126 | print_('# python -m pwiz %s' % cmd_line) 127 | print_('# Date: %s' % timestamp.strftime('%B %d, %Y %I:%M%p')) 128 | print_('# Database: %s' % introspector.get_database_name()) 129 | print_('# Peewee version: %s' % peewee_version) 130 | print_('') 131 | 132 | 133 | def err(msg): 134 | sys.stderr.write('\033[91m%s\033[0m\n' % msg) 135 | sys.stderr.flush() 136 | 137 | def get_option_parser(): 138 | parser = OptionParser(usage='usage: %prog [options] database_name') 139 | ao = parser.add_option 140 | ao('-H', '--host', dest='host') 141 | ao('-p', '--port', dest='port', type='int') 142 | ao('-u', '--user', dest='user') 143 | ao('-P', '--password', dest='password', action='store_true') 144 | engines = sorted(DATABASE_MAP) 145 | ao('-e', '--engine', dest='engine', default='postgresql', choices=engines, 146 | help=('Database type, e.g. sqlite, mysql or postgresql. Default ' 147 | 'is "postgresql".')) 148 | ao('-s', '--schema', dest='schema') 149 | ao('-t', '--tables', dest='tables', 150 | help=('Only generate the specified tables. Multiple table names should ' 151 | 'be separated by commas.')) 152 | ao('-i', '--info', dest='info', action='store_true', 153 | help=('Add database information and other metadata to top of the ' 154 | 'generated file.')) 155 | ao('-o', '--preserve-order', action='store_true', dest='preserve_order', 156 | help='Model definition column ordering matches source table.') 157 | return parser 158 | 159 | def get_connect_kwargs(options): 160 | ops = ('host', 'port', 'user', 'schema') 161 | kwargs = dict((o, getattr(options, o)) for o in ops if getattr(options, o)) 162 | if options.password: 163 | kwargs['password'] = getpass() 164 | return kwargs 165 | 166 | 167 | if __name__ == '__main__': 168 | raw_argv = sys.argv 169 | 170 | parser = get_option_parser() 171 | options, args = parser.parse_args() 172 | 173 | if options.preserve_order: 174 | try: 175 | from collections import OrderedDict 176 | except ImportError: 177 | err('Preserve order requires Python >= 2.7.') 178 | sys.exit(1) 179 | 180 | if len(args) < 1: 181 | err('Missing required parameter "database"') 182 | parser.print_help() 183 | sys.exit(1) 184 | 185 | connect = get_connect_kwargs(options) 186 | database = args[-1] 187 | 188 | tables = None 189 | if options.tables: 190 | tables = [table.strip() for table in options.tables.split(',') 191 | if table.strip()] 192 | 193 | introspector = make_introspector(options.engine, database, **connect) 194 | if options.info: 195 | cmd_line = ' '.join(raw_argv[1:]) 196 | print_header(cmd_line, introspector) 197 | 198 | print_models(introspector, tables, preserve_order=options.preserve_order) 199 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | peewee==2.8.0 2 | psycopg2==2.6.1 3 | -------------------------------------------------------------------------------- /trac2down/Trac2Down.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | # vim: autoindent tabstop=4 shiftwidth=4 expandtab softtabstop=4 filetype=python fileencoding=utf-8 3 | ''' 4 | Copyright © 2013 5 | Eric van der Vlist 6 | Shigeru KANEMOTO 7 | See license information at the bottom of this file 8 | ''' 9 | 10 | 11 | from __future__ import division 12 | import datetime 13 | import re 14 | import os 15 | from io import open 16 | 17 | # Config Start 18 | meta_header = True # whether to include the wiki pages' meta data at the top of the markdown 19 | markdown_extension = 'markdown' # file extension to use for the generated markdown files 20 | # Config End 21 | 22 | 23 | def convert(text, base_path, multilines=True): 24 | text = re.sub('\r\n', '\n', text) 25 | text = re.sub(r'{{{(.*?)}}}', r'`\1`', text) 26 | text = re.sub(r'(?sm){{{(\n?#![^\n]+)?\n(.*?)\n}}}', r'```\n\2\n```', text) 27 | 28 | text = text.replace('[[TOC]]', '') 29 | text = text.replace('[[BR]]', '\n') 30 | text = text.replace('[[br]]', '\n') 31 | 32 | if multilines: 33 | text = re.sub(r'^\S[^\n]+([^=-_|])\n([^\s`*0-9#=->-_|])', r'\1 \2', text) 34 | 35 | text = re.sub(r'(?m)^======\s+(.*?)\s+======$', r'\n###### \1', text) 36 | text = re.sub(r'(?m)^=====\s+(.*?)\s+=====$', r'\n##### \1', text) 37 | text = re.sub(r'(?m)^====\s+(.*?)\s+====$', r'\n#### \1', text) 38 | text = re.sub(r'(?m)^===\s+(.*?)\s+===$', r'\n### \1', text) 39 | text = re.sub(r'(?m)^==\s+(.*?)\s+==$', r'\n## \1', text) 40 | text = re.sub(r'(?m)^=\s+(.*?)\s+=$', r'\n# \1', text) 41 | text = re.sub(r'^ * ', r'****', text) 42 | text = re.sub(r'^ * ', r'***', text) 43 | text = re.sub(r'^ * ', r'**', text) 44 | text = re.sub(r'^ * ', r'*', text) 45 | text = re.sub(r'^ \d+. ', r'1.', text) 46 | 47 | a = [] 48 | is_table = False 49 | for line in text.split('\n'): 50 | if not line.startswith(' '): 51 | line = re.sub(r'\[\[(https?://[^\[\]\|]+)\|([^\[\]]+)\]\]', r'[\2](\1)', line) 52 | line = re.sub(r'\[(https?://[^\s\[\]]+)\s([^\[\]]+)\]', r'[\2](\1)', line) 53 | line = re.sub(r'\[wiki:([^\s\[\]]+)\s([^\[\]]+)\]', r'[\2](%s/\1)' % os.path.relpath('/wikis/', base_path), line) 54 | line = re.sub(r'\[source:([^\s\[\]]+)\s([^\[\]]+)\]', r'[\2](%s/\1)' % os.path.relpath('/tree/master/', base_path), line) 55 | line = re.sub(r'source:([\S]+)', r'[\1](%s/\1)' % os.path.relpath('/tree/master/', base_path), line) 56 | line = re.sub(r'\!(([A-Z][a-z0-9]+){2,})', r'\1', line) 57 | line = re.sub(r'\[\[Image\(source:([^(]+)\)\]\]', r'![](%s/\1)' % os.path.relpath('/tree/master/', base_path), line) 58 | line = re.sub(r'\[\[Image\(([^(]+)\)\]\]', r'![](\1)', line) 59 | line = re.sub(r'\'\'\'(.*?)\'\'\'', r'*\1*', line) 60 | line = re.sub(r'\'\'(.*?)\'\'', r'_\1_', line) 61 | if line.startswith('||'): 62 | if not is_table: 63 | sep = re.sub(r'[^|]', r'-', line) 64 | line = line + '\n' + sep 65 | is_table = True 66 | line = re.sub(r'\|\|', r'|', line) 67 | else: 68 | is_table = False 69 | else: 70 | is_table = False 71 | a.append(line) 72 | text = '\n'.join(a) 73 | return text 74 | 75 | 76 | def save_file(text, name, version, date, author, directory): 77 | folders = name.rsplit("/", 1) 78 | if len(folders) > 1 and not os.path.exists("%s%s" % (directory, folders[0])): 79 | os.makedirs("%s%s" % (directory, folders[0])) 80 | else: 81 | if not os.path.exists('%s' % (directory)): 82 | os.makedirs('%s' % (directory)) 83 | fp = open('%s%s.%s' % (directory, name, markdown_extension), "w+") 84 | 85 | if meta_header: 86 | fp.write( unicode('\n' % name) ) 87 | fp.write( unicode('\n' % version) ) 88 | fp.write( unicode('\n' % date) ) 89 | fp.write( unicode('\n' % author) ) 90 | fp.write( unicode('\n') ) 91 | 92 | fp.write(unicode(text)) 93 | fp.close() 94 | 95 | if __name__ == "__main__": 96 | SQL = ''' 97 | select 98 | name, version, time, author, text 99 | from 100 | wiki w 101 | where 102 | version = (select max(version) from wiki where name = w.name) 103 | ''' 104 | 105 | import sqlite3 106 | conn = sqlite3.connect('../trac.db') 107 | result = conn.execute(SQL) 108 | for row in result: 109 | name = row[0] 110 | version = row[1] 111 | time = row[2] 112 | author = row[3] 113 | text = row[4] 114 | text = convert(text, '/wikis/') 115 | try: 116 | time = datetime.datetime.fromtimestamp(time).strftime('%Y/%m/%d %H:%M:%S') 117 | except ValueError: 118 | time = datetime.datetime.fromtimestamp(time/1000000).strftime('%Y/%m/%d %H:%M:%S') 119 | save_file(text, name, version, time, author, '') 120 | 121 | ''' 122 | This file is part of . 123 | 124 | This sotfware is free software: you can redistribute it and/or modify 125 | it under the terms of the GNU Lesser General Public License as published by 126 | the Free Software Foundation, either version 3 of the License, or 127 | (at your option) any later version. 128 | 129 | This sotfware is distributed in the hope that it will be useful, 130 | but WITHOUT ANY WARRANTY; without even the implied warranty of 131 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 132 | GNU Lesser General Public License for more details. 133 | 134 | You should have received a copy of the GNU Lesser General Public License 135 | along with this library. If not, see . 136 | ''' 137 | -------------------------------------------------------------------------------- /trac2down/__init__.py: -------------------------------------------------------------------------------- 1 | from .Trac2Down import * 2 | --------------------------------------------------------------------------------