Gitweb - name of last person to commit - perl

I'm looking to add the name of the person who made the last commit to each project on the GitWeb project list, so instead of
14 min ago
it says something like
14 min ago (Someone's Name)
I've had a look through gitweb.cgi and found the point where the string is written (line 5488 in mine), but I don't really know how to proceed.
Has anyone already done this? Or can anyone offer a quick solution?

Thanks to simbabque for pointing me to git_get_last_activity. My solution (possibly sub-optimal, let me know if it is):
Change git_get_last_activity to
sub git_get_last_activity {
my ($path) = #_;
my $fd;
$git_dir = "$projectroot/$path";
open($fd, "-|", git_cmd(), 'for-each-ref',
'--format=%(committer)',
'--sort=-committerdate',
'--count=1',
'refs/heads') or return;
my $most_recent = <$fd>;
close $fd or return;
if (defined $most_recent &&
$most_recent =~ / (\d+) [-+][01]\d\d\d$/) {
my $bracket_position = rindex($most_recent, "<");
my $committer_name = substr($most_recent, 0, $bracket_position - 1);
my $timestamp = $1;
my $age = time - $timestamp;
return ($age, age_string($age), $committer_name);
}
return (undef, undef, undef);
}
Then search for where that is called later (should only be once) and change
($pr->{'age'}, $pr->{'age_string'}) = #activity;
to be
($pr->{'age'}, $pr->{'age_string'}, $pr->{'committer'}) = #activity;
Then go to git_project_list_rows and change
(defined $pr->{'age_string'} ? $pr->{'age_string'} : "No commits") . "</td>\n" .
to
(defined $pr->{'age_string'} ? $pr->{'age_string'} . ' (' . $pr->{'committer'} . ')' : "No commits") . "</td>\n" .

Related

Use Archive::Zip to determine if a member is a text file or not

I'm working on a script that will grep the contents of members of zip archives when the member name matches a pattern, using a given search string.
I have the following sub that processes a single archive (the script can take more than one archive on the command line):
sub processArchive($$$$) {
my ($zip, $searchstr, $match, $zipName) = #_;
print "zip[$zip] searchstr[$searchstr] match[$match] zipName[$zipName]\n";
my #matchingList = $zip->membersMatching($match);
my $len = #matchingList;
if ($len > 0) {
print $zipName . ":\n";
for my $member (#matchingList) {
print "member[$member]\n";
print "textfile[" . $member->isTextFile() . "] contents[" . $member->contents() . "]\n";
if ($member->isTextFile()) {
print "Is a text file.\n";
}
else {
print "Is not a text file.\n";
}
my #matchingLines = grep /$searchstr/, $member->contents();
my $len = #matchingLines;
if ($len > 0) {
print #matchingLines;
}
}
}
}
The logic isn't even complete yet. I'm first experimenting with calling "isTextFile()" to see what it does. I must be doing something wrong, because I get "Is not a text file" for at least one member that is clearly a text file.
I also note that when I print the value of the return from "isTextFile()", it's always an empty string. Is that what I should expect from printing a "true" or "false" value, or is something else wrong here?
The "text file" status is read from a flag in the ZIP file. Many archiving tools do not set this flag properly, as it is rarely used and has no impact on normal use.
If you actually need to check whether a file contains text, you will need to extract it and see for yourself.

access sub child value by libxml::xpathcontext

I want to access the value of sub child and modify it. This is my xml
<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0">
<outer1 xmlns="http://blablabla" >
<inner>
<name>
<prenom>Hello</prenom>
</name>
<profession>warrior</profession>
</inner>
<inner>
<name>
<prenom>Hello</prenom>
</name>
<org>wwf</org>
<profession>warrior</profession>
</inner>
</outer1>
and this is my code
my $dom = XML::LibXML->load_xml( location => $xml);
my $context = XML::LibXML::XPathContext->new( $dom->documentElement() );
$context->registerNs( 'u' => '"urn:ietf:params:xml:ns:netconf:base:1.0' );
$context->registerNs( 'u' => 'http://blablabla');
for my $node ($context->findnodes('//u:inner') ) {
for my $node2 ($node->findnodes('//u:name') ) {
#if (($node->findnodes('u:name', $node2) ->size) != 1) {next;}
my ($mh) = $node->findnodes('u:prenom', $node2);
my $size = $node->findnodes('u:prenom', $node2) ->size;
print "size $size";
if ($size != 1) {next;}
$mh ->removeChildNodes();
$mh->appendText('World12456');
print "mh = $mh";
}
}
I want to access prenom and modify it to 'World12456'. With currrent code; I got this error XPath error : Undefined namespace prefix
error : xmlXPathCompiledEval: evaluation failed. Then I tried different way
for my $node ($context->findnodes('//u:inner') ) {
my ($mh) = $context->findnodes('u:name/prenom', $node);
my $size = $context->findnodes('u:name/prenom', $node) ->size;
print "size $size";
if ($size != 1) {next;}
$mh ->removeChildNodes();
$mh->appendText('World12456');
print "mh = $mh";
}
Then I get the size is 0 for both. It doesn't find the tag prenom. With
for my $node ($context->findnodes('//u:inner/name')
It displays nothing.
I am sorry if this is duplicate but I don't find any link to access the sub child with xpathcontext yet.
I got it . I just need to put u for each element
for my $node ($context->findnodes('//u:inner/u:name')

Perl NetSNMP extension with multiple devices

I have got a machine (Debian based) with some temperature sensors attached to it, and i would like to query them over snmp, from one script. I can work with one sensor ok, but i am struggling when i plug another one in.
What I am trying to do is loop through each device, and give each one an id, then use this ID as part of the OID, then give it a value.
I've never worked with snmp before, and my perl is not great so any help would be much appreciated. Below is my code:
#!/usr/bin/perl
use NetSNMP::agent (':all');
use NetSNMP::ASN qw(ASN_OCTET_STR ASN_INTEGER);
$BASE_OID=".1.3.6.1.4.1.41050";
$dev_id=1;
$string_value;
$integer_value;
sub pimon_handler {
my ($handler, $registration_info, $request_info, $requests) = #_;
my $request;
my $oid_key;
for($request = $requests; $request; $request = $request->next()) {
$oid_key=$BASE_OID . '.' . $dev_id;
my $oid = $request->getOID();
if ($request_info->getMode() == MODE_GET) {
if ($oid == new NetSNMP::OID($oid_key . '.0')) {
$request->setValue(ASN_OCTET_STR, $string_value);
}
elsif ($oid == new NetSNMP::OID($oid_key . '.1')) {
$request->setValue(ASN_INTEGER, $integer_value);
}
} elsif ($request_info->getMode() == MODE_GETNEXT) {
if ($oid == new NetSNMP::OID($oid_key . '.0')) {
$request->setOID($oid_key . '.1');
$request->setValue(ASN_INTEGER, $integer_value);
}
elsif ($oid < new NetSNMP::OID($oid_key . '.0')) {
$request->setOID($oid_key . '.0');
$request->setValue(ASN_OCTET_STR, $string_value);
}
}
}
}
#location of where we are going to find the 1wire devices
#sensors = `cat /sys/bus/w1/devices/w1_bus_master1/w1_master_slaves`;
chomp(#sensors);
#loop through the sensors we find
foreach $line(#sensors) {
#work out the temp we have got. Need to change this for other sensor types
$output = `cat /sys/bus/w1/devices/$line/w1_slave`;
$output =~ /t=(?<temp>\d+)/;
$integer_value = sprintf "%.0f",$+{temp} / 1000;
$string_value = $line;
my $agent = new NetSNMP::agent();
$agent->register("Pimon$looptest", $BASE_OID . '.' . $dev_id,
\&pimon_handler);
print "Dev $dev_id temp $line temp is $integer_value\n";
$dev_id ++;
}
Are you getting any errors or output?
I suspect that your problem lies in and around your reading the data file by shelling-out to cat instead of opening the file and looping over the linewise contents.
Try dumping the value of #sensors. if it is a single entry array, with the only element containing your entire file, then simply switch #sensors to be scalar. then split $sensors into an array and loop over that.
my $sensors = `read something`
chomp $sensors;
my #sensors = split(/\n/, $sensors);
foreach $line (#sensors) {
...

Perl sub doesn't want to work with passed objects as parameters

I pass two Date::Manip::Date objects, perfectly valid dates to my sub:
sub get_duration {
my $duration;
my #val;
my $from = $_[0]->new_date();
my $to = $_[1]->new_date();
# $from->parse("2012-03-06");
# $to->parse("2012-03-07");
print $from . " ".$to. "<-- <br />";
my #f = $from->value();
if ($f[0] == 2012) {
$from->config("ConfigFile",$HOLIDAYS_2012);
} elsif ($f[0] == 2013) {
$from->config("ConfigFile",$HOLIDAYS_2013);
} elsif ($f[0] == 2014) {
$from->config("ConfigFile",$HOLIDAYS_2014);
} elsif ($f[0] == 2015) {
$from->config("ConfigFile",$HOLIDAYS_2015);
}
my #t = $to->value();
if ($t[0] == 2012) {
$to->config("ConfigFile",$HOLIDAYS_2012);
} elsif ($t[0] == 2013) {
$to->config("ConfigFile",$HOLIDAYS_2013);
} elsif ($t[0] == 2014) {
$to->config("ConfigFile",$HOLIDAYS_2014);
} elsif ($t[0] == 2015) {
$to->config("ConfigFile",$HOLIDAYS_2015);
}
print "from " . #f ." to ". #t."<br>";
my $delta = $from->calc($to, "business");
print $from->calc($to, "business") . " <-";
#val = $delta->value();
if ($to->is_business_day()) {
$duration = $val[3]+1;
} else {
$duration = $val[3];
}
return $duration;
}
I get the output
Date::Manip::Date=HASH(0xacdf7a0) Date::Manip::Date=HASH(0xacdfb50)<--
from 0 to 0
<-
Software error:
Can't call method "value" on an undefined value at '#val = $delta->value();'
That is the two dates are passed all right, I got NO errors when it tries to set their config files, Regardless, the value arrays #t and #f are empty and it breaks down as soon as I try to get the delta.
However if I uncomment the two lines
$from->parse("2012-03-06");
$to->parse("2012-03-07");
(hence ignoring the parameters)
It works just fine as intended.
There's something I'm missing about passing objects in Perl I suspect?
Firstly
&get_overlap_duration($saved[$i][5], $saved[$i][6], $saved[$i][7], $saved[$i][8])
Is called
I've printed the #saved values and they're correct, they're strings:
2012-03-06, 2012-03-08, 2012-03-05, 2012-03-07
Then inside get_overlap_duration those strings are
my $from1 = new Date::Manip::Date;
my $to1 = new Date::Manip::Date;
my $from2 = new Date::Manip::Date;
my $to2 = new Date::Manip::Date;
$from1->parse($_[0]);
$to1->parse($_[1]);
$from2->parse($_[2]);
$to2->parse($_[3]);
Then there's there is a call for get_duration for instance $duration = get_duration($from2, $to1);
I've checked the server error log there were no complaints apart from the software error displayed in the browser.
The problem is that on the following line:
my $delta = $from->calc($to, "business");
It's not returning a valid object. Which likely means that something in the calc() function is failing. Since "business" is not a valid date. And if you read the Date::Manip::Calc man page, the mode parameter is only legal when you pass in two date objects before that and you've only passed one.

How do you get CGI::Session to expire after a certain interval?

It seems like CGI::Session expire() function only expires after a user is idle for a specified interval. I'm assuming by idle they mean a user hasnt refreshed the page or accessed any others.
While I see that you can force the session to expire by using delete(), what I dont see is a way to automatically force the session to expire whether the use has been idle or not.
Maybe this is not a desired user experience, but for sake of understanding is there a way to do this without having to track the time interval or using any additional libraries?
Also what is the point of CGI::Session::is_expired if session returns a new one when it expires anyway? At least it seems I can't get to an expired state with my script
sub build_sss{
my($this) = shift;
$cgi = $this->cgi_obj();
my $sid = $this->sid();
my $sss = CGI::Session->load(undef, $cgi, {Directory=>'tmp'}) or die CGI::Session->errstr();
#check expired session
if ( $sss->is_expired() ) {
my $expired_url = $ENV{'SCRIPT_URI'}.'?expired='.$sid;
$this->session_status("SESSION_EXPIRED");
print $cgi->redirect($expired_url); #when expired param is set shows a msg
}
#check if empty create new
if ( $sss->is_empty() ) {
$sss = $sss->new() or $sss->errstr;
$this->session_status("SESSION_NEW");
$sss->expire('30s');
$sss->expire(_TEST_SUB_SESSION => '15s');
}
return $sss;
}
update: so yeah, if you want a session to expire based on creation time, you have to subclass CGI::Session
1) make sure you have latest version of CGI::Session
2) read CGI::Session::Tutorial
3) write programs that prove your claims, like this CGI::Session expire demo
#!/usr/bin/perl --
use strict;
use warnings;
use CGI();
use CGI::Session();
my ($oneid);
{
my $one = CGI::Session->new or die CGI::Session->errstr;
$one->expire('3s');
$one->param(qw' var value ');
$oneid = $one->id;
print "set exire to 3 seconds\n";
}
for my $loop ( 1 .. 4 ) {
sleep 1;
my $bob = CGI::Session->load($oneid) or die CGI::Session->errstr;
print "one second later $bob / $oneid load\n";
}
for my $loop ( 1 .. 4 ) {
sleep 2;
my $bob = CGI::Session->load($oneid) or die CGI::Session->errstr;
print "two seconds later ";
if ( $bob->is_expired ) {
print "$bob / $oneid is_expired\n";
} else {
print "var=", $bob->param('var'), "\n";
}
} ## end for my $loop ( 1 .. 4 )
{
sleep 3;
my $bob = CGI::Session->load($oneid) or die CGI::Session->errstr;
print "three seconds later ";
if ( $bob->is_expired ) {
print "$bob / $oneid is_expired\n";
} else {
print "var=", $bob->param('var'), "\n";
}
}
__END__
set exire to 3 seconds
one second later CGI::Session=HASH(0xa965fc) / cf27e3ec9ff5a06a5bef4491e830c8b6 load
one second later CGI::Session=HASH(0x97a164) / cf27e3ec9ff5a06a5bef4491e830c8b6 load
one second later CGI::Session=HASH(0xbef68c) / cf27e3ec9ff5a06a5bef4491e830c8b6 load
one second later CGI::Session=HASH(0xbef56c) / cf27e3ec9ff5a06a5bef4491e830c8b6 load
two seconds later var=value
two seconds later var=value
two seconds later var=value
two seconds later var=value
three seconds later CGI::Session=HASH(0xa965ec) / cf27e3ec9ff5a06a5bef4491e830c8b6 is_expired
From the documentation:
"is_empty() - Returns true for sessions that are empty. It's preferred way of testing whether requested session was loaded successfully or not"
I don't understand how you are trying to expire a session on the condition that it is empty?
#check if empty create new
if ( $sss->is_empty() ) {
$sss = $sss->new() or $sss->errstr;
$this->session_status("SESSION_NEW");
$sss->expire('30s');
$sss->expire(_TEST_SUB_SESSION => '15s');
}
Did you perhaps mean:
if ( !$sss->is_empty() ) { #...Not empty?