📄 viewcvs.py
字号:
### in the future, it might be nice to break this path up into ### a list of elements, allowing the template to display it in ### a variety of schemes. ### maybe use drop_leaf here? 'nav_path' : clickable_path(request, up_where, 1, 0, 0), 'branch' : None, 'mime_type' : request.mime_type, 'view_tag' : view_tag, 'entries' : show_revs, ### rename the show_rev local to entries? 'rev_selected' : query_dict.get('r1'), 'diff_format' : query_dict['diff_format'], 'logsort' : query_dict['logsort'], ### should toss 'address' and just stick to cfg... in the template 'address' : cfg.general.address, 'cfg' : cfg, 'vsn' : __version__, 'kv' : request.kv, 'viewable' : ezt.boolean(request.default_viewable), 'human_readable' : ezt.boolean(query_dict['diff_format'] == 'h' or query_dict['diff_format'] == 'l'), } if cfg.options.use_cvsgraph: data['graph_href'] = file_url + '?graph=1' + request.amp_query else: data['graph_href'] = None if cur_branch: ### note: we really shouldn't have more than one tag in here. a "default ### branch" implies singular :-) However, if a vendor branch is created ### and no further changes are made (e.g. the HEAD is 1.1.1.1), then we ### end up seeing the branch point tag and MAIN in this list. ### FUTURE: fix all the branch point logic in ViewCVS and get this right. data['branch'] = string.join(rev2tag.get(cur_branch, [ cur_branch ]), ', ') ### 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 head_abs_href vs head_href is a bit bogus: why decide to ### include/exclude the mime type from the URL? should just always be ### the same, right? if request.default_viewable: data['head_href'] = download_url(request, file_url, 'HEAD', viewcvs_mime_type) data['head_abs_href'] = download_url(request, file_url, 'HEAD', request.mime_type) else: data['head_href'] = download_url(request, file_url, 'HEAD', None) for entry in show_revs: # augment the entry with (extended=1) info. augment_entry(entry, request, file_url, rev_map, rev2tag, branch_points, rev_order, 1) tagitems = taginfo.items() tagitems.sort() tagitems.reverse() data['tags'] = tags = [ ] for tag, rev in tagitems: tags.append(_item(rev=rev, name=tag)) if query_dict.has_key('r1'): diff_rev = query_dict['r1'] else: diff_rev = show_revs[-1].rev data['tr1'] = diff_rev if query_dict.has_key('r2'): diff_rev = query_dict['r2'] else: diff_rev = show_revs[0].rev data['tr2'] = diff_rev ### would be nice to find a way to use [query] or somesuch instead hidden_values = '' for varname in _sticky_vars: if varname != 'only_with_tag' and varname != 'logsort': value = query_dict.get(varname, '') if value != '' and value != default_settings.get(varname): hidden_values = hidden_values + \ '<input type=hidden name="%s" value="%s">' % \ (varname, value) data['hidden_values'] = hidden_values branch_names.sort() branch_names.reverse() data['branch_names'] = branch_names http_header() generate_page(request, cfg.templates.log, data)### suck up other warnings in _re_co_warning?_re_co_filename = re.compile(r'^(.*),v\s+-->\s+standard output\s*\n$')_re_co_warning = re.compile(r'^.*co: .*,v: warning: Unknown phrases like .*\n$')_re_co_revision = re.compile(r'^revision\s+([\d\.]+)\s*\n$')def process_checkout(full_name, where, query_dict, default_mime_type): rev = query_dict.get('rev') ### validate the revision? if not rev or rev == 'HEAD': rev_flag = '-p' else: rev_flag = '-p' + rev mime_type = query_dict.get('content-type') if mime_type: ### validate it? pass else: mime_type = default_mime_type fp = popen.popen(os.path.join(cfg.general.rcs_path, 'co'), (rev_flag, full_name), 'r') # header from co: # #/home/cvsroot/mod_dav/dav_shared_stub.c,v --> standard output #revision 1.1 # # Sometimes, the following line might occur at line 2: #co: INSTALL,v: warning: Unknown phrases like `permissions ...;' are present. # parse the output header filename = revision = None line = fp.readline() if not line: error('Missing output from co.<br>' 'fname="%s". url="%s"' % (filename, where)) match = _re_co_filename.match(line) if not match: error('First line of co output is not the filename.<br>' 'Line was: %s<br>' 'fname="%s". url="%s"' % (line, filename, where)) filename = match.group(1) line = fp.readline() if not line: error('Missing second line of output from co.<br>' 'fname="%s". url="%s"' % (filename, where)) match = _re_co_revision.match(line) if not match: match = _re_co_warning.match(line) if not match: error('Second line of co output is not the revision.<br>' 'Line was: %s<br>' 'fname="%s". url="%s"' % (line, filename, where)) # second line was a warning. ignore it and move along. line = fp.readline() if not line: error('Missing third line of output from co (after a warning).<br>' 'fname="%s". url="%s"' % (filename, where)) match = _re_co_revision.match(line) if not match: error('Third line of co output is not the revision.<br>' 'Line was: %s<br>' 'fname="%s". url="%s"' % (line, filename, where)) # one of the above cases matches the revision. grab it. revision = match.group(1) if filename != full_name: error('The filename from co did not match. Found "%s". Wanted "%s"<br>' 'url="%s"' % (filename, full_name, where)) return fp, revision, mime_type def view_checkout(request): fp, revision, mime_type = process_checkout(request.full_name, request.where, request.query_dict, request.mime_type) if mime_type == viewcvs_mime_type: # use the "real" MIME type markup_stream(request, fp, revision, request.mime_type) else: http_header(mime_type) copy_stream(fp)def view_annotate(request): rev = request.query_dict['annotate'] pathname, filename = os.path.split(request.where) if pathname[-6:] == '/Attic': pathname = pathname[:-6] data = nav_header_data(request, pathname, filename, rev) data.update({ 'cfg' : cfg, 'vsn' : __version__, 'kv' : request.kv, }) http_header() generate_page(request, cfg.templates.annotate, data) ### be nice to hook this into the template... import blame blame.make_html(request.cvsroot, request.where + ',v', rev, sticky_query(request.query_dict)) html_footer(request)def cvsgraph_image(cfg, request): "output the image rendered by cvsgraph" # this function is derived from cgi/cvsgraphmkimg.cgi http_header('image/png') fp = popen.popen(os.path.normpath(os.path.join(cfg.options.cvsgraph_path,'cvsgraph')), ("-c", cfg.options.cvsgraph_conf, "-r", request.cvsroot, request.where + ',v'), 'r') copy_stream(fp) fp.close()def view_cvsgraph(cfg, request): "output a page containing an image rendered by cvsgraph" # this function is derived from cgi/cvsgraphwrapper.cgi rev = request.query_dict['graph'] where = request.where pathname, filename = os.path.split(where) if pathname[-6:] == '/Attic': pathname = pathname[:-6] data = nav_header_data(request, pathname, filename, rev) # Required only if cvsgraph needs to find it's supporting libraries. # Uncomment and set accordingly if required. #os.environ['LD_LIBRARY_PATH'] = '/usr/lib:/usr/local/lib' # Create an image map fp = popen.popen(os.path.join(cfg.options.cvsgraph_path, 'cvsgraph'), ("-i", "-c", cfg.options.cvsgraph_conf, "-r", request.cvsroot, "-6", request.amp_query, "-7", request.qmark_query, request.where + ',v'), 'r') data.update({ 'request' : request, 'imagemap' : fp, 'cfg' : cfg, 'vsn' : __version__, 'kv' : request.kv, }) http_header() generate_page(request, cfg.templates.graph, data)def search_files(request, search_re): # Pass in Request object and the search regular expression. We check out # each file and look for the regular expression. We then return the data # for all files that match the regex. # Compile to make sure we do this as fast as possible. searchstr = re.compile(search_re) # Will become list of files that have at least one match. new_file_list = [ ] # Get list of files AND directories files = os.listdir(request.full_name) # Loop on every file (and directory) for file in files: full_name = os.path.join(request.full_name, file) # Is this a directory? If so, append name to new_file_list. if os.path.isdir(full_name): new_file_list.append(file) continue # figure out where we are and its mime type where = string.replace(full_name, request.cvsroot, '') mime_type, encoding = mimetypes.guess_type(where) if not mime_type: mime_type = 'text/plain' # Shouldn't search binary files, or should we? # Should allow all text mime types to pass. if string.split(mime_type, '/')[0] != 'text': continue # At this point everything should be a file. # Remove the ,v full_name = full_name[:-2] where = where[:-2] # process_checkout will checkout the head version out of the repository # Assign contents of checked out file to fp. fp, revision, mime_type = process_checkout(full_name, where, request.query_dict, mime_type) # Read in each line, use re.search to search line. # If successful, add file to new_file_list and break. while 1: line = fp.readline() if not line: break if searchstr.search(line): new_file_list.append(file) # close down the pipe (and wait for the child to terminate) fp.close() break return get_file_tests(request.full_name, new_file_list)def view_doc(request): """Serve ViewCVS help pages locally. Using this avoids the need for modifying the setup of the web server. """ help_page = request.where if CONF_PATHNAME: doc_directory = os.path.join(g_install_dir, "doc") else: # aid testing from CVS working copy: doc_directory = os.path.join(g_install_dir, "website") try: fp = open(os.path.join(doc_directory, help_page), "rt") except IOError, v: error('help file "%s" not available\n(%s)' % (help_page, str(v)), '404 Not Found') if help_page[-3:] == 'png': http_header('image/png') elif help_page[-3:] == 'jpg': http_header('image/jpeg') elif help_page[-3:] == 'gif': http_header('image/gif') else: # assume HTML: http_header() copy_stream(fp) fp.close()_re_extract_rev = re.compile(r'^[-+]+ [^\t]+\t([^\t]+)\t((\d+\.)+\d+)$')_re_extract_info = re.compile(r'@@ \-([0-9]+).*\+([0-9]+).*@@(.*)')def human_readable_diff(request, fp, rev1, rev2, sym1, sym2): # do this now, in case we need to print an error http_header() query_dict = request.query_dict where_nd = request.where[:-5] # remove the ".diff" pathname, filename = os.path.split(where_nd) data = nav_header_data(request, pathname, filename, rev2) log_rev1 = log_rev2 = None date1 = date2 = '' r1r = r2r = '' while 1: line = fp.readline() if not line: break # Use regex matching to extract the data and to ensure that we are # extracting it from a properly formatted line. There are rcsdiff # programs out there that don't supply the correct format; we'll be # flexible in case we run into one of those. if line[:4] == '--- ': match = _re_extract_rev.match(line) if match: date1 = ', ' + match.group(1) log_rev1 = match.group(2) elif line[:4] == '+++ ': match = _re_extract_rev.match(line) if match: date2 = ', ' + match.group(1) log_rev2 = match.group(2) break if (log_rev1 and log_rev1 != rev1) or (log_rev2 and log_rev2 != rev2): ### it would be nice to have an error.ezt for things like this print '<strong>ERROR:</strong> rcsdiff did not return the correct' print 'version number in its output.' print '(got "%s" / "%s", expected "%s" / "%s")' % \ (log_rev1, log_rev2, rev1, rev2) print '<p>Aborting operation.' sys.exit(0) # format selector hidden_values = '' for varname, value in query_dict.items(): if varname != 'diff_format' and value != default_settings.get(varname): hidden_values = hidden_values + \ '<input type=hidden name="%s" value="%s">' % \ (varname, cgi.escape(value)) data.update({ 'cfg' : cfg, 'vsn' : __version__, 'kv' : request.kv, 'request' : request, 'where' : where_nd, 'rev1' : rev1, 'rev2' : rev2, 'tag1' : sym1, 'tag2' : sym2, 'date1' : date1, 'date2' : date2, 'changes' : DiffSource(fp), 'diff_format' : query_dict['diff_format'], 'hidden_values' : hidden_values, }) generate_page(request, cfg.templates.diff, data)def spaced_html_text(text): text = string.expandtabs(string.rstrip(text)) # in the code below, "\x01" will be our stand-in for "&". We don't want # to insert "&" because it would get escaped by htmlify(). Similarly, # we use "\x02" as a stand-in for "<br>" if cfg.options.hr_breakable > 1 and len(text) > cfg.options.hr_breakable: text = re.sub('(' + ('.' * cfg.options.hr_breakable) + ')', '\\1\x02', text) if cfg.options.hr_breakable: # make eve
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -