Ensuring git is not a GIT

Git is a great source-control tool written by the father of Linux himself. When creating FreeDESK I knew I really should use source control for a number of reasons (see the bottom of the post if you’re interested).

Having used a few in the past I shopped around and decided on git with the hosting of the repository on github. It installed nicely on my various different machines and I set about learning the command-lines for it.

As with any SCM once you have a project setup you just need to add any new files (git add filename) and then when you next commit these will be included.

But, here came my concern, what if I’ve forgotten to add a file. Often working late I can easily overlook stuff and overlooking a file would mean it’s not being put into the repository breaking the code as it may be relied upon and more importantly not being backed up (actually I also copy the entire source tree to Dropbox as part of my commit script but you get the idea – it’s only backed up once).

So as part of my development tools I made the following PHP script. It looks at the output from git for all the files it’s looking after and compares this to the physical file structure. Any missing files (those existing in the filesystem but not in git) are highlighted to be added. It also points out any orphan files, those which are in git but not on the filesystem.

Certain things are excluded for this purpose, the .git directory which contains all the git information but is not actually part of the software, temporary files created by gEdit (my code editor of choice) and finally the release directory which is used to build releases but not included in the source code tree.

On first run it identified three key files that I had indeed overlooked to include in git so I could quickly git add them and commit.

Here is the script in case anyone finds it useful outside of the FreeDESK project specifically (in the FreeDESK code tree it’s /gitcheck.php). Apologies for the indentation (or lack thereof) but copy-paste didn’t like it and I tried by hand but no joy, so I gave up.


<?php
/* -------------------------------------------------------------
This file is part of FreeDESK

FreeDESK is (C) Copyright 2012 David Cutting

FreeDESK is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

FreeDESK is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with FreeDESK. If not, see www.gnu.org/licenses

For more information see www.purplepixie.org/freedesk/
-------------------------------------------------------------- */

// Check git is up-to-date with all our files to be added using "git ls-files"
// compared against actual directory structure

// What to exclude - the ./.git directory and also our release directory
$exclude = array(
"./.git",
"./release" );

$gitout = array();
exec("git ls-files", $gitout);

$gitfiles=array();
foreach($gitout as $gitfile)
$gitfiles["./".$gitfile]=false;

$physfiles=array();

// Identify temp files from gEdit (~ on the end)
function isTempFile($file)
{
if (substr($file,-1)=="~")
return true;
return false;
}

// Recursive function to check a directory
function checkDir($path)
{
// File and exclude arrays
global $physfiles,$gitfiles, $exclude;
$handle = opendir($path); // open the directory
while (false !== ($file = readdir($handle))) // iterate through
{
$filepath = $path.$file; // get a "full" filepath

// Exclude . .. temp files and anything in our exclude array
if ($file != "." && $file != ".." &&
!isTempFile($file) && !in_array($filepath, $exclude) )
{
// If a directory recursively call checkDir again
if (is_dir($filepath))
checkDir($filepath."/");
else // is a file
{
// Check it against the list of git files
if (isset($gitfiles[$filepath]))
$ingit=true;
else
$ingit=false;
$physfiles[$filepath]=$ingit;
if ($ingit)
$gitfiles[$filepath]=true;

}
 }
 }
 closedir($handle);
}

checkDir("./");

// Show orphaned files - those in git but not on the filesystem
$orphancount=0;
foreach($gitfiles as $file => $physical)
{
 if (!$physical)
 {
 $orphancount++;
 echo "ORPHAN: ".$file."\n";
 }
}
// Show orphan summary
echo $orphancount." orphaned files (in git but not physically listed)\n";

// Show missing git files (exist on filesystem but not in git)
$filecount=0;
$ingitcount=0;
$misscount=0;
foreach($physfiles as $file => $ingit)
{
/*
 if ($ingit)
 echo " ";
 else
 echo "X";
 echo " ".$file."\n";
*/
 $filecount++;
 if (!$ingit)
 {
 $misscount++;
 echo "MISSING: ".$file."\n";
 }
 else
 $ingitcount++;
}
// Display a summary
echo "Total ".$filecount." physical files, ".$ingitcount." in git, ".$misscount." missing.\n";

?>

Why use SCM for FreeDESK?

I need to be able to easily work on the code on a variety of machines without having to worry about copying it. For example most of the work is done on cub, my little Fedora laptop, plugged into an external monitor, keyboard and mouse. When I’m at university cub can connect to the internet but I cannot connect to it (security restrictions). Hence I would need to copy anything I want from it to an external server and then back again to the uni PC I’m working on (needless to say I can’t install Dropbox on the uni PC).

As the code grows into release it is also important than anyone and everyone have access to the source tree. In previous projects I’ve provided full source but on a release-by-release basis rather than live access. This has meant if I want to share something with another developer I have to package up a specific set of code or produce a full development release, which they will work on entirely separately to me and I have to re-integrate back into the main code on completion.

So there you go, source control FTW.

Leave a Reply

Your email address will not be published. Required fields are marked *