Skip to content

Instantly share code, notes, and snippets.

@dianagold
Last active September 30, 2020 12:27
Show Gist options
  • Save dianagold/880b7f542fe1c2569f52b3e741c5dac1 to your computer and use it in GitHub Desktop.
Save dianagold/880b7f542fe1c2569f52b3e741c5dac1 to your computer and use it in GitHub Desktop.
Automatically set project path for multiple collaborators in Stata

Automatically set project path for multiple collaborators in Stata

Say you have a project in Stata with multiple collaborators, each of them with their local copy in a different path. This often happens when if you collaborate via Git or a cloud storage platform. Everyone will need to execute the same master run - but unlike Python or R scripts, Stata do-files do not "know" their location.

Let's see a few solutions on how to set the project path as a global at the beginning of your master do-file.

Manual method

This solution works but requires every collaborator to change the line manually before running. Annoying.

* Define user-dependant project path
global projectpath "C:/Users/adalovelace/git/This_Project/" // CHANGE HERE!

Recognizing the user

Alternatively, you could spell out everyone's path and recognize the path by the username. But any time a new collaborator joins, you will need to update this section. And fingers cross none of your users has the the same username that should point to different paths.

*-----------------------------------------------------------------------------
* Define user-dependant project paths
*-----------------------------------------------------------------------------
* Ada Lovelace
if inlist("`c(username)'","adalovelace","adaalterego") {
  global projectpath "C:/Users/`c(username)'/git/This_project/"
}
* Alan Turing
else if inlist("`c(username)'","aturing") {
  global projectpath "/users/`c(username)'/git/This_project/"
}
* Charles Babbage
else if inlist("`c(username)'","charles","id12345") {
  global projectpath "C:/Users/`c(username)'/GitHub/This_project/"
}
/* WELCOME!!! ARE YOU NEW TO THIS CODE?
   Add yourself by copying the lines above, making sure to adapt your clone */
* If none of above cases, give an error
else {
  noi disp as error _newline "{phang}Your username [`c(username)'] could not be matched with any profile. Please update the master do-file accordingly and try again.{p_end}"
  error 2222
}

Using whereis (basic)

The command whereis can be installed from SSC. It maintains a directory of external programs and ancillary files and folders. If all your projects are subfolders of a particular folder, you can store that location through whereis manually once.

That is, one time per computer, you would type:

ssc install whereis
whereis github "C:/Users/adalovelace/git/"

Then every Stata instance after that will have this location returned to you. That is, whereis git will return the macro r(github): "C:/Users/adalovelace/git/"

Once everyone has manually set whereis git once, then have in your master do-file:

whereis github
global projectpath "`r(github)'/This_project/"

Even if you are not part of a team, but rather changes between computers a lot, this can be useful. I have whereis installed with the stored locations of my GitHub and Dropbox folders and a handful of applications (Pandoc, 7zip, R) in all my computers.

Using whereis (power)

To be more clear and help future users/collaborators, you may add a capture, clearer error messages and a check to it. In addition, you could give the option to locate the file by a dialogue box in case the user does not have whereis.

The code below is an overblown for some, but it is our team's preferred solution.

*-----------------------------------------------------------------------------
* Define user-dependant project paths
*-----------------------------------------------------------------------------
* Change here only if this repo is renamed
local this_repo     "This_Project"
* Change here only if this master run do-file is renamed
local this_run_do   "master_run.do"

* The remaining section is standard in all of our team repositories

* One of two options can be used to "know" the clone path for a given user
* A. the user had previously saved their GitHub location with -whereis-,
*    so the clone is a subfolder with this Project Name in that location
* B. through a window dialog box where the user manually selects a file

* Method A - Github location stored in -whereis-
*---------------------------------------------
capture whereis github
if _rc == 0 global clone "`r(github)'/`this_repo'"

* Method B - clone selected manually by user
*---------------------------------------------
else {
  * Display an explanation plus warning to force the user to look at the dialog box
  noi disp as txt `"{phang}Your GitHub clone local could not be automatically identified by the command {it: whereis}, so you will be prompted to do it manually. To save time, you could install -whereis- with {it: ssc install whereis}, then store your GitHub location, for example {it: whereis github "C:/Users/AdaLovelace/GitHub"}.{p_end}"'
  noi disp as error _n `"{phang}Please use the dialog box to manually select the file `this_run_do' in your machine.{p_end}"'

  * Dialog box to select file manually
  capture window fopen path_and_run_do "Select the master do-file for this project (`this_run_do'), expected to be inside any path/`this_repo'/" "Do Files (*.do)|*.do|All Files (*.*)|*.*" do

  * If user clicked cancel without selecting a file or chose a file that is not a do, will run into error later
  if _rc == 0 {

    * Pretend user chose what was expected in terms of string lenght to parse
    local user_chosen_do   = substr("$path_and_run_do",   - strlen("`this_run_do'"),     strlen("`this_run_do'") )
    local user_chosen_path = substr("$path_and_run_do", 1 , strlen("$path_and_run_do") - strlen("`this_run_do'") - 1 )

    * Replace backward slash with forward slash to avoid possible troubles
    local user_chosen_path = subinstr("`user_chosen_path'", "\", "/", .)

    * Check if master do-file chosen by the user is master_run_do as expected
    * If yes, attributes the path chosen by user to the clone, if not, exit
    if "`user_chosen_do'" == "`this_run_do'"  global clone "`user_chosen_path'"
    else {
      noi disp as error _newline "{phang}You selected $path_and_run_do as the master do file. This does not match what was expected (any path/`this_repo'/`this_run_do'). Code aborted.{p_end}"
      error 2222
    }
  }
}

* Regardless of the method above, check clone
*---------------------------------------------
* Confirm that clone is indeed accessible by testing that master run is there
cap confirm file "${clone}/`this_run_do'"
if _rc != 0 {
  noi disp as error _n `"{phang}Having issues accessing your local clone of the `this_repo' repo. Please double check the clone location specified in `this_run_do' and try again.{p_end}"'
  error 2222
}

* Flag that profile was successfully loaded
*--------------------------------------------
noi disp as result _n `"{phang}`this_repo' clone sucessfully set up (${clone}).{p_end}"'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment