Search code examples
repositoryrelative-pathabsolute-path

How do I avoid absolute pathnames in my code when using Git?


Up till this point in my programming career, I have mostly worked on small projects, editing the PHP/Perl/Python files directly on the Linux dev host, then copying the files to the same directory on a live server to push them into production.

I'm trying to set it up now by learning how to use Git and also how to properly write code with Git in mind. I want to learn the best practices for this scenario:

Here's a project called "BigFun", which also uses some libraries with tasks that are common to many projects.

/home/projects/BigFun/bin/script1.pl
/home/projects/BigFun/bin/script2.pl
/home/projects/BigFun/bin/script3.pl
/home/projects/BigFun/lib/FunMaker.pm

/home/projects/common/lib/Utilities.pm
/home/projects/common/lib/Format.pm

If this program is not managed by Git, and if I know that the files will never be moved around, I could do something like this:

#!/usr/bin/perl
use warnings;
use strict;
use lib '/home/projects/BigFun/lib';
use FunMaker;
use lib '/home/projects/common/lib';
use Utilities;

But once this is managed by Git, then anyone will be able to check these files out and put them in their own development space. The hardcoded URLs will not work anymore if your development rootdir is "C:\My Projects\BigFun".

So, some questions:

  1. I can probably assume that the BigFun "lib" directory will always be relative to the "bin" directory. So maybe I could change line 3 to use lib '../lib'; . Is that the right solution, though?

  2. It seems likely, though, that this example code I've listed would be split up in to two repositories - one for BigFun, and the other as a "common" repo containing some tools that are used by many projects. When that happens, it seems to me that the BigFun code would have no way of knowing where to find the "common" libraries. /home/projects/common/lib is not at all guaranteed to work, and nor would ../../common/lib. What's the normal Git way to handle something like this?

I'm working my way through the "Pro Git" book, but I haven't (yet) found anything to answer these questions. Thanks to anyone who can point me in the right direction!


Solution

  • Your question is not about Git, it's about collaboration. Absolute paths force all users of your piece of software to use the same directory layout, and that's unacceptable. No decent software does that. Avoiding absolute paths in software is the norm, regardless of what version control system you use, or not use.

    How to make your software work using strictly relative paths and never absolute paths? That depends on the software/framework/language. For relative paths to make sense, you need to consider the question: relative from where? Here are some ideas as the anchor from which relative paths could be considered:

    • current working directory
    • user home directory
    • package installation directory
    • framework installation directory

    Every language typically has some packaging mechanism. The goal of packaging is that developers in the language can create a standard package, the content of which is organized in such a way that the standard tools of the language can install it, adding the software to the system-wide libraries of the language, or to custom user libraries, or to a specified library location. Once the software is installed, from a standard package, it becomes ready to use just like any other installed software.

    In your example, use warnings; and use strict; work without any setup because these libraries are installed in the system. The system finds their location relative to the installation directory of Perl. Roughly speaking.

    So what you need to do is:

    1. Figure out how to package a Perl library
    2. Figure out how to install a Perl package

    Once your FunMaker and Utilities are installed as standard Perl packages, you will be able to simplify your script as:

    #!/usr/bin/perl
    use warnings;
    use strict;
    use FunMaker;
    use Utilities;
    

    You will of course have to document the dependencies of the script (FunMaker, Utilities), as well as how to install them (especially the location where these packages will be hosted).