Rev 1295 | Blame | Compare with Previous | Last modification | View Log | RSS feed
################################################################################ Codestriker: Copyright (c) 2001, 2002 David Sitsky. All rights reserved.# sits@users.sourceforge.net## This program is free software; you can redistribute it and modify it under# the terms of the GPL.# Action object for handling the viewing of a file.package Codestriker::Action::ViewTopicFile;use strict;use Codestriker::Model::File;use Codestriker::Model::Comment;use Codestriker::Http::Render;use Codestriker::Repository::RepositoryFactory;# If the input is valid, display the topic.sub process($$$) {my ($type, $http_input, $http_response) = @_;# Retrieve the parameters for this action.my $query = $http_response->get_query();my $topicid = $http_input->get('topic');my $mode = $http_input->get('mode');my $tabwidth = $http_input->get('tabwidth');my $email = $http_input->get('email');my $fn = $http_input->get('fn');my $new = $http_input->get('new');my $parallel = $http_input->get('parallel');my $brmode = $http_input->get('brmode');my $fview = $http_input->get('fview');# Check if this action is allowed.if (scalar(@Codestriker::valid_repositories) == 0) {$http_response->error("This function has been disabled");}# Retrieve the appropriate topic details.my $topic = Codestriker::Model::Topic->new($topicid);# Retrieve the corresponding repository object.my $repository =Codestriker::Repository::RepositoryFactory->get($topic->{repository});# Retrieve the deltas corresponding to this file.my @deltas = Codestriker::Model::Delta->get_deltas($topicid, $fn);# We need to untaint the filename and revision values, as they will# potentially be used to launch an external program.$deltas[0]->{filename} =~ /^(.*)$/o;my $filename = $1;$deltas[0]->{revision} =~ /^(.*)$/o;my $revision = $1;# Retrieve the comment details for this topic.my @comments = $topic->read_comments();# Load the appropriate original form of this file into memory.my ($filedata_max_line_length, @filedata);if (!_read_repository_file($filename, $revision, $tabwidth,$repository, \@filedata,\$filedata_max_line_length)) {## 13-Sep-07 SJK: Provide some more info in this message, suggesting the likely root cause.##$http_response->error("Couldn't get repository data for $filename " .# "$revision: $!");$http_response->error("Couldn't get repository data for $filename " ."$revision: $!. Check repository $repository->{dynamic_view_name} can navigate to this file.");}# This could be done more efficiently, but for now, read through the# file, and determine the longest line length for the resulting# data that is to be viewed. Note it is not 100% accurate, but it will# do for now, to reduce the resulting page size.my $max_line_length = $filedata_max_line_length;for (my $d = 0; $d <= $#deltas; $d++) {my @difflines = split /\n/, $deltas[$d]->{text};for (my $i = 0; $i <= $#difflines; $i++) {my $line = $difflines[$i];if ($line =~ /^\s(.*)$/o || $line =~ /^\+(.*)$/o ||$line =~ /^\-(.*)$/o) {my $line_length = length($1);if ($line_length > $max_line_length) {$max_line_length = $line_length;}}}}# Output the new file, with the deltas applied.my $title;if ($parallel) {$title = "View File: Parallel view of $filename v$revision";} else {$title = $new ? "View File: New $filename" :"View File: $filename v$revision";}$http_response->generate_header(topic=>$topic,comments=>\@comments,topic_title=>$title,mode=>$mode,tabwidth=>$tabwidth,fview=>$fview,repository=>$Codestriker::repository_name_map->{$topic->{repository}},reload=>0, cache=>1);# Render the HTML header.my $vars = {};$vars->{'closehead'} = 1;my $header = Codestriker::Http::Template->new("header");$header->process($vars);my $max_digit_width = length($#filedata);# Create a new render object to perform the line rendering.my @toc_filenames = ();my @toc_revisions = ();my @toc_binaries = ();my $url_builder = Codestriker::Http::UrlBuilder->new($query);my $render =Codestriker::Http::Render->new($query, $url_builder, $parallel,$max_digit_width, $topicid, $mode,\@comments, $tabwidth,$repository, \@toc_filenames,\@toc_revisions, \@toc_binaries,undef, $max_line_length, $brmode,$fview);# Prepare the output.if ($parallel) {$render->print_coloured_table();}else {print "<PRE class=\"ms\">\n";}# Read through all the deltas, and apply them to the original form of the# file.my $delta = undef;for (my $delta_index = 0; $delta_index <= $#deltas; $delta_index++) {$delta = $deltas[$delta_index];# Output those lines leading up to the start of the next delta.# Build up a delta with no changes, and render it.my $delta_text = "";my $next_delta_linenumber = $delta->{old_linenumber};for (my $i = $render->{old_linenumber};$i < $next_delta_linenumber; $i++) {$delta_text .= " $filedata[$i]\n";}$render->delta_text($filename, $fn, $revision,$render->{old_linenumber},$render->{new_linenumber},$delta_text, 0, $new, 0);# Render the actual change delta.$render->delta_text($filename, $fn, $revision,$delta->{old_linenumber},$delta->{new_linenumber}, $delta->{text}, 1,$new, 1);}# Render the tail part of the file, again by building up a delta.my $delta_text = "";for (my $i = $render->{old_linenumber}; $i <= $#filedata; $i++) {$delta_text .= " $filedata[$i]\n";}$render->delta_text($filename, $fn, $revision, $render->{old_linenumber},$render->{new_linenumber}, $delta_text, 0, $new, 0);# Close off the rendering.if ($parallel) {print $query->end_table();}else {print "</PRE>\n";}# Render the HTML trailer.my $trailer = Codestriker::Http::Template->new("trailer");$trailer->process();print $query->end_html();$http_response->generate_footer();# Fire the topic listener to indicate that the user has viewed the topic.Codestriker::TopicListeners::Manager::topic_viewed($email, $topic);}# Read the specified repository file and revision into memory. Return true if# successful, false otherwise.sub _read_repository_file ($$$$$$) {my ($filename, $revision, $tabwidth, $repository, $data_array_ref,$maxline_length_ref) = @_;# Read the file data.$repository->retrieve($filename, $revision, $data_array_ref);## 13-Sep-07 SJK: Return false if no data read from repository#if ( $#$data_array_ref <= 0 ) {return 0;}# Determine the maximum line length, and replace tabs with spaces.$$maxline_length_ref = 0;for (my $i = 1; $i <= $#$data_array_ref; $i++) {$$data_array_ref[$i] =Codestriker::Http::Render::tabadjust($tabwidth,$$data_array_ref[$i], 0);my $line_length = length($$data_array_ref[$i]);if ($line_length > $$maxline_length_ref) {$$maxline_length_ref = $line_length;}}return 1;}1;