📄 viewcvs.py
字号:
row.anchor = file row.href = url row.name = file + '/' row.type = 'dir' info = fileinfo.get(file) if info == _FILE_HAD_ERROR: row.cvs = 'error' unreadable = 1 elif info: row.cvs = 'data' row.time = html_time(request, info[1]) row.author = info[3] if cfg.options.use_cvsgraph: row.graph_href = ' ' if cfg.options.show_logs: row.show_log = 'yes' subfile = info[4] idx = string.find(subfile, '/') row.log_file = subfile[idx+1:] row.log_rev = info[0] if info[2]: row.log = format_log(info[2]) else: row.cvs = 'none' rows.append(row) else: # remove the ",v" file = file[:-2] row.type = 'file' row.anchor = file num_files = num_files + 1 info = fileinfo.get(file) if info == _FILE_HAD_ERROR: row.cvs = 'error' rows.append(row) num_displayed = num_displayed + 1 unreadable = 1 continue elif not info: continue elif hideattic and view_tag and info[5] == 'dead': continue num_displayed = num_displayed + 1 file_url = urllib.quote(file) url = file_url + request.qmark_query if file[:6] == 'Attic/': file = file[6:] row.cvs = 'data' row.name = file # ensure this occurs after we strip Attic/ row.href = url row.rev = info[0] row.author = info[3] row.state = info[5] row.rev_href = file_url + '?rev=' + row.rev + request.amp_query row.time = html_time(request, info[1]) if cfg.options.use_cvsgraph: row.graph_href = file_url + '?graph=' + row.rev + request.amp_query if cfg.options.show_logs: row.show_log = 'yes' row.log = format_log(info[2]) rows.append(row) ### we need to fix the template w.r.t num_files. it usually is not a ### correct (original) count of the files available for selecting data['num_files'] = num_files # the number actually displayed data['files_shown'] = num_displayed if num_files and not num_displayed: data['no_match'] = 'yes' if unreadable: data['unreadable'] = 'yes' # always create a set of form parameters, since we may have a search form data['params'] = params = [ ] for varname in _sticky_vars: value = query_dict.get(varname, '') if value != '' and value != default_settings.get(varname, '') \ and varname != 'only_with_tag' \ and varname != 'search': params.append(_item(name=varname, value=query_dict[varname])) if alltags or view_tag: alltagnames = alltags.keys() alltagnames.sort(lambda t1, t2: cmp(string.lower(t1), string.lower(t2))) alltagnames.reverse() branchtags = [] nonbranchtags = [] for tag in alltagnames: rev = alltags[tag] if string.find(rev, '.0.') == -1: nonbranchtags.append(tag) else: branchtags.append(tag) data['branch_tags'] = branchtags data['plain_tags'] = nonbranchtags if cfg.options.allow_tar: tar_basename = os.path.basename(where) if not tar_basename: tar_basename = "cvs_root" url = tar_basename + '.tar.gz?tarball=1' + request.amp_query data['tarball_href'] = url http_header() generate_page(request, cfg.templates.directory, data)def fetch_log(full_name, which_rev=None): if which_rev: args = ('-r' + which_rev, full_name) else: args = (full_name,) rlog = popen.popen(os.path.normpath(os.path.join(cfg.general.rcs_path,'rlog')), args, 'r') header, eof = parse_log_header(rlog) filename = header.filename head = header.head branch = header.branch taginfo = header.taginfo if eof: # no log entries or a parsing failure return head, branch, taginfo, [ ] revs = [ ] while 1: entry, eof = parse_log_entry(rlog) if entry: # valid revision info revs.append(entry) if eof: break return head, branch, taginfo, revsdef logsort_date_cmp(rev1, rev2): # sort on date; secondary on revision number return -cmp(rev1.date, rev2.date) or -revcmp(rev1.rev, rev2.rev)def logsort_rev_cmp(rev1, rev2): # sort highest revision first return -revcmp(rev1.rev, rev2.rev)_re_is_branch = re.compile(r'^((.*)\.)?\b0\.(\d+)$')def read_log(full_name, which_rev=None, view_tag=None, logsort='cvs'): head, cur_branch, taginfo, revs = fetch_log(full_name, which_rev) if not cur_branch: idx = string.rfind(head, '.') cur_branch = head[:idx] rev_order = map(lambda entry: entry.rev, revs) rev_order.sort(revcmp) rev_order.reverse() # HEAD is an artificial tag which is simply the highest tag number on the # main branch, unless there is a branch tag in the RCS file in which case # it's the highest revision on that branch. Find it by looking through # rev_order; it is the first commit listed on the appropriate branch. # This is not neccesary the same revision as marked as head in the RCS file. idx = string.rfind(cur_branch, '.') if idx == -1: taginfo['MAIN'] = '0.' + cur_branch else: taginfo['MAIN'] = cur_branch[:idx] + '.0' + cur_branch[idx:] for rev in rev_order: idx = string.rfind(rev, '.') if idx != -1 and cur_branch == rev[:idx]: taginfo['HEAD'] = rev break else: idx = string.rfind(cur_branch, '.') taginfo['HEAD'] = cur_branch[:idx] # map revision numbers to tag names rev2tag = { } # names of symbols at each branch point branch_points = { } branch_names = [ ] # Now that we know all of the revision numbers, we can associate # absolute revision numbers with all of the symbolic names, and # pass them to the form so that the same association doesn't have # to be built then. items = taginfo.items() items.sort() items.reverse() for tag, rev in items: match = _re_is_branch.match(rev) if match: branch_names.append(tag) # # A revision number of A.B.0.D really translates into # "the highest current revision on branch A.B.D". # # If there is no branch A.B.D, then it translates into # the head A.B . # # This reasoning also applies to the main branch A.B, # with the branch number 0.A, with the exception that # it has no head to translate to if there is nothing on # the branch, but I guess this can never happen? # (the code below gracefully forgets about the branch # if it should happen) # head = match.group(2) or '' branch = match.group(3) if head: branch_rev = head + '.' + branch else: branch_rev = branch rev = head for r in rev_order: if r == branch_rev or r[:len(branch_rev)+1] == branch_rev + '.': rev = branch_rev break if rev == '': continue if rev != head and head != '': if branch_points.has_key(head): branch_points[head].append(tag) else: branch_points[head] = [ tag ] if rev2tag.has_key(rev): rev2tag[rev].append(tag) else: rev2tag[rev] = [ tag ] if view_tag: view_rev = taginfo.get(view_tag) if not view_rev: error('Tag %s not defined.' % view_tag, '404 Tag not found') if view_rev[:2] == '0.': view_rev = view_rev[2:] idx = string.rfind(view_rev, '.') branch_point = view_rev[:idx] else: idx = string.find(view_rev, '.0.') if idx == -1: branch_point = view_rev else: view_rev = view_rev[:idx] + view_rev[idx+2:] idx = string.rfind(view_rev, '.') branch_point = view_rev[:idx] show_revs = [ ] for entry in revs: rev = entry.rev idx = string.rfind(rev, '.') branch = rev[:idx] if branch == view_rev or rev == branch_point: show_revs.append(entry) else: show_revs = revs if logsort == 'date': show_revs.sort(logsort_date_cmp) elif logsort == 'rev': show_revs.sort(logsort_rev_cmp) else: # no sorting pass # build a map of revision number to entry information rev_map = { } for entry in revs: rev_map[entry.rev] = entry ### some of this return stuff doesn't make a lot of sense... return show_revs, rev_map, rev_order, taginfo, rev2tag, \ cur_branch, branch_points, branch_names_re_is_vendor_branch = re.compile(r'^1\.1\.1\.\d+$')g_name_printed = { } ### gawd, what a hack...def augment_entry(entry, request, file_url, rev_map, rev2tag, branch_points, rev_order, extended): "Augment the entry with additional, computed data from the log output." query_dict = request.query_dict rev = entry.rev idx = string.rfind(rev, '.') branch = rev[:idx] entry.vendor_branch = ezt.boolean(_re_is_vendor_branch.match(rev)) entry.utc_date = time.asctime(time.gmtime(entry.date)) entry.ago = html_time(request, entry.date, 1) entry.branches = prep_tags(query_dict, file_url, rev2tag.get(branch, [ ])) entry.tags = prep_tags(query_dict, file_url, rev2tag.get(rev, [ ])) entry.branch_points = prep_tags(query_dict, file_url, branch_points.get(rev, [ ])) prev_rev = string.split(rev, '.') while 1: if prev_rev[-1] == '0': # .0 can be caused by 'commit -r X.Y.Z.0' prev_rev = prev_rev[:-2] # X.Y.Z.0 becomes X.Y.Z else: prev_rev[-1] = str(int(prev_rev[-1]) - 1) prev = string.join(prev_rev, '.') if rev_map.has_key(prev) or prev == '': break entry.prev = prev ### maybe just overwrite entry.log? entry.html_log = htmlify(entry.log) if extended: entry.tag_names = rev2tag.get(rev, [ ]) if rev2tag.has_key(branch) and not g_name_printed.has_key(branch): entry.branch_names = rev2tag.get(branch) g_name_printed[branch] = 1 else: entry.branch_names = [ ] ### I don't like this URL construction stuff. not obvious enough (how ### it keys off the mime_type to do different things). also, the ### value for entry.href is a bit bogus: why decide to include/exclude ### the mime type from the URL? should just always be the same, right? entry.view_href = download_url(request, file_url, rev, viewcvs_mime_type) if request.default_viewable: entry.href = download_url(request, file_url, rev, None) else: entry.href = download_url(request, file_url, rev, request.mime_type) entry.text_href = download_url(request, file_url, rev, 'text/plain') # figure out some target revisions for performing diffs entry.branch_point = None entry.next_main = None idx = string.rfind(branch, '.') if idx != -1: branch_point = branch[:idx] if not entry.vendor_branch \ and branch_point != rev and branch_point != prev: entry.branch_point = branch_point # if it's on a branch (and not a vendor branch), then diff against the # next revision of the higher branch (e.g. change is committed and # brought over to -stable) if string.count(rev, '.') > 1 and not entry.vendor_branch: # locate this rev in the ordered list of revisions i = rev_order.index(rev) # create a rev that can be compared component-wise c_rev = string.split(rev, '.') while i: next = rev_order[i - 1] c_work = string.split(next, '.') if len(c_work) < len(c_rev): # found something not on the branch entry.next_main = next break # this is a higher version on the same branch; the lower one (rev) # shouldn't have a diff against the "next main branch" if c_work[:-1] == c_rev[:len(c_work) - 1]: break i = i - 1 # the template could do all these comparisons itself, but let's help # it out. r1 = query_dict.get('r1') if r1 and r1 != rev and r1 != prev and r1 != entry.branch_point \ and r1 != entry.next_main: entry.to_selected = 'yes' else: entry.to_selected = Nonedef view_log(request): full_name = request.full_name where = request.where query_dict = request.query_dict view_tag = query_dict.get('only_with_tag') show_revs, rev_map, rev_order, taginfo, rev2tag, \ cur_branch, branch_points, branch_names = \ read_log(full_name, None, view_tag, query_dict['logsort']) up_where = re.sub(_re_up_path, '', where) ### whoops. this sometimes/always? does not have the ",v" assert full_name[-2:] != ',v', 'please report this error to viewcvs@lyra.org' #filename = os.path.basename(full_name[:-2]) # drop the ",v" filename = os.path.basename(full_name) ### can we use filename rather than where? need to clarify the two vars file_url = urllib.quote(os.path.basename(where)) ### try: "./" + query + "#" + filename back_url = request.script_name + '/' + urllib.quote(up_where) + \ request.qmark_query + '#' + filename data = { 'where' : where, 'request' : request, 'back_url' : back_url, 'href' : file_url, 'query' : request.amp_query, 'qquery' : request.qmark_query,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -