📄 cvsdb.py
字号:
# -*- Mode: python -*-## Copyright (C) 2000 The ViewCVS Group. All Rights Reserved.## By using this file, you agree to the terms and conditions set forth in# the LICENSE.html file which can be found at the top level of the ViewCVS# distribution or at http://www.lyra.org/viewcvs/license-1.html.## Contact information:# Greg Stein, PO Box 760, Palo Alto, CA, 94302# gstein@lyra.org, http://www.lyra.org/viewcvs/## -----------------------------------------------------------------------############################################################################ INSTALL-TIME CONFIGURATION## These values will be set during the installation process. During# development, they will remain None.#CONF_PATHNAME = None#########################################################################import osimport sysimport stringimport timeimport configimport dbiimport rlog## load configuration file, the data is used globally hereif CONF_PATHNAME: _cfg_pathname = CONF_PATHNAMEelse: # developer assistance: running from a CVS working copy _cfg_pathname = os.path.join(os.path.dirname(__file__), os.pardir, 'cgi', 'viewcvs.conf')cfg = config.Config()cfg.set_defaults()cfg.load_config(_cfg_pathname)## errorerror = "cvsdb error"## cached (active) database connectionsgCheckinDatabase = NonegCheckinDatabaseReadOnly = None## CheckinDatabase provides all interfaces needed to the SQL database## back-end; it needs to be subclassed, and have its "Connect" method## defined to actually be complete; it should run well off of any DBI 2.0## complient database interfaceclass CheckinDatabase: def __init__(self, host, user, passwd, database): self._host = host self._user = user self._passwd = passwd self._database = database ## database lookup caches self._get_cache = {} self._get_id_cache = {} self._desc_id_cache = {} def Connect(self): self.db = dbi.connect( self._host, self._user, self._passwd, self._database) def sql_get_id(self, table, column, value, auto_set): sql = "SELECT id FROM %s WHERE %s=%%s" % (table, column) sql_args = (value, ) cursor = self.db.cursor() cursor.execute(sql, sql_args) try: (id, ) = cursor.fetchone() except TypeError: if not auto_set: return None else: return str(int(id)) ## insert the new identifier sql = "INSERT INTO %s(%s) VALUES(%%s)" % (table, column) sql_args = (value, ) cursor.execute(sql, sql_args) return self.sql_get_id(table, column, value, 0) def get_id(self, table, column, value, auto_set): ## attempt to retrieve from cache try: return self._get_id_cache[table][column][value] except KeyError: pass id = self.sql_get_id(table, column, value, auto_set) if id == None: return None ## add to cache try: temp = self._get_id_cache[table] except KeyError: temp = self._get_id_cache[table] = {} try: temp2 = temp[column] except KeyError: temp2 = temp[column] = {} temp2[value] = id return id def sql_get(self, table, column, id): sql = "SELECT %s FROM %s WHERE id=%%s" % (column, table) sql_args = (id, ) cursor = self.db.cursor() cursor.execute(sql, sql_args) try: (value, ) = cursor.fetchone() except TypeError: return None return value def get(self, table, column, id): ## attempt to retrieve from cache try: return self._get_cache[table][column][id] except KeyError: pass value = self.sql_get(table, column, id) if value == None: return None ## add to cache try: temp = self._get_cache[table] except KeyError: temp = self._get_cache[table] = {} try: temp2 = temp[column] except KeyError: temp2 = temp[column] = {} temp2[id] = value return value def get_list(self, table, field_index): sql = "SELECT * FROM %s" % (table) cursor = self.db.cursor() cursor.execute(sql) list = [] while 1: row = cursor.fetchone() if row == None: break list.append(row[field_index]) return list def GetBranchID(self, branch, auto_set = 1): return self.get_id("branches", "branch", branch, auto_set) def GetBranch(self, id): return self.get("branches", "branch", id) def GetDirectoryID(self, dir, auto_set = 1): return self.get_id("dirs", "dir", dir, auto_set) def GetDirectory(self, id): return self.get("dirs", "dir", id) def GetFileID(self, file, auto_set = 1): return self.get_id("files", "file", file, auto_set) def GetFile(self, id): return self.get("files", "file", id) def GetAuthorID(self, author, auto_set = 1): return self.get_id("people", "who", author, auto_set) def GetAuthor(self, id): return self.get("people", "who", id) def GetRepositoryID(self, repository, auto_set = 1): return self.get_id("repositories", "repository", repository, auto_set) def GetRepository(self, id): return self.get("repositories", "repository", id) def SQLGetDescriptionID(self, description, auto_set = 1): ## lame string hash, blame Netscape -JMP hash = len(description) sql = "SELECT id FROM descs WHERE hash=%s AND description=%s" sql_args = (hash, description) cursor = self.db.cursor() cursor.execute(sql, sql_args) try: (id, ) = cursor.fetchone() except TypeError: if not auto_set: return None else: return str(int(id)) sql = "INSERT INTO descs (hash,description) values (%s,%s)" sql_args = (hash, description) cursor.execute(sql, sql_args) return self.GetDescriptionID(description, 0) def GetDescriptionID(self, description, auto_set = 1): ## attempt to retrieve from cache hash = len(description) try: return self._desc_id_cache[hash][description] except KeyError: pass id = self.SQLGetDescriptionID(description, auto_set) if id == None: return None ## add to cache try: temp = self._desc_id_cache[hash] except KeyError: temp = self._desc_id_cache[hash] = {} temp[description] = id return id def GetDescription(self, id): return self.get("descs", "description", id) def GetRepositoryList(self): return self.get_list("repositories", 1) def GetBranchList(self): return self.get_list("branches", 1) def GetAuthorList(self): return self.get_list("people", 1) def AddCommitList(self, commit_list): for commit in commit_list: self.AddCommit(commit) def AddCommit(self, commit): ## MORE TIME HELL: the MySQLdb module doesn't construct times ## correctly when created with TimestampFromTicks -- it doesn't ## account for daylight savings time, so we use Python's time ## module to do the conversion temp = time.localtime(commit.GetTime()) ci_when = dbi.Timestamp( temp[0], temp[1], temp[2], temp[3], temp[4], temp[5]) ci_type = commit.GetTypeString() who_id = self.GetAuthorID(commit.GetAuthor()) repository_id = self.GetRepositoryID(commit.GetRepository()) directory_id = self.GetDirectoryID(commit.GetDirectory()) file_id = self.GetFileID(commit.GetFile()) revision = commit.GetRevision() sticky_tag = "NULL" branch_id = self.GetBranchID(commit.GetBranch()) plus_count = commit.GetPlusCount() minus_count = commit.GetMinusCount() description_id = self.GetDescriptionID(commit.GetDescription()) sql = "REPLACE INTO checkins"\ " (type,ci_when,whoid,repositoryid,dirid,fileid,revision,"\ " stickytag,branchid,addedlines,removedlines,descid)"\ "VALUES(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)" sql_args = (ci_type, ci_when, who_id, repository_id, directory_id, file_id, revision, sticky_tag, branch_id, plus_count, minus_count, description_id) cursor = self.db.cursor() cursor.execute(sql, sql_args) def SQLQueryListString(self, sqlString, query_entry_list): sqlList = [] for query_entry in query_entry_list: ## figure out the correct match type if query_entry.match == "exact": match = "=" elif query_entry.match == "like": match = " LIKE " elif query_entry.match == "regex": match = " REGEXP " sqlList.append(sqlString % (match, query_entry.data)) return "(%s)" % (string.join(sqlList, " OR ")) def CreateSQLQueryString(self, query): tableList = ["checkins"] condList = [] ## XXX: this is to exclude .ver files -- RN specific hack --JMP tableList.append("files") temp = "(checkins.fileid=files.id AND files.file NOT LIKE \"%.ver\")" condList.append(temp) ## XXX if len(query.repository_list): tableList.append("repositories") sql = "(checkins.repositoryid=repositories.id AND "\ "repositories.repository%s\"%s\")" temp = self.SQLQueryListString(sql, query.repository_list) condList.append(temp) if len(query.branch_list): tableList.append("branches") sql = "(checkins.branchid=branches.id AND "\ "branches.branch%s\"%s\")" temp = self.SQLQueryListString(sql, query.branch_list) condList.append(temp) if len(query.directory_list): tableList.append("dirs") sql = "(checkins.dirid=dirs.id AND dirs.dir%s\"%s\")" temp = self.SQLQueryListString(sql, query.directory_list) condList.append(temp) if len(query.file_list): tableList.append("files") sql = "(checkins.fileid=files.id AND files.file%s\"%s\")" temp = self.SQLQueryListString(sql, query.file_list) condList.append(temp) if len(query.author_list): tableList.append("people") sql = "(checkins.whoid=people.id AND people.who%s\"%s\")" temp = self.SQLQueryListString(sql, query.author_list) condList.append(temp) if query.from_date: temp = "(checkins.ci_when>=\"%s\")" % (str(query.from_date)) condList.append(temp) if query.to_date: temp = "(checkins.ci_when<=\"%s\")" % (str(query.to_date)) condList.append(temp) if query.sort == "date": order_by = "ORDER BY checkins.ci_when DESC" elif query.sort == "author": order_by = "ORDER BY checkins.whoid" elif query.sort == "file": order_by = "ORDER BY checkins.fileid" ## exclude duplicates from the table list for table in tableList[:]:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -