Where does Cargo put the git requirements? - rust

When compiling a project, cargo automatically downloads the requirements, specified in the Cargo.toml, given as a git-repository.
E.g.
[dependencies.piston]
git = "https://github.com/PistonDevelopers/piston"
will result in
Updating git repository 'https://github.com/PistonDevelopers/opengl_graphics'
when compiling. Where does it save those repositories on my disk? I'm using Windows, does this change anything?

man cargo gives:
FILES
~/.cargo
Directory in which Cargo stores repository data. Cargo can
be instructed to use a .cargo subdirectory in a different
location by setting the CARGO_HOME environment variable.
Doing a git grep for CARGO_HOME finds https://github.com/rust-lang/cargo/blob/3533ff11c505017751d1e466685efe7084cbd96b/src/cargo/util/config.rs#L380-L384
which uses http://doc.rust-lang.org/nightly/std/os/fn.homedir.html

Related

What mechanism does git use to find its repository?

I have several git repositories. One of these is in $PATH. Today, I accidentally moved to a directory that I thought had a git repository, but did not have one.
cd <another_directory_without_.git>.
So, when I entered git status, the output was confusing.
It appears git found the repository in $PATH, so in this case, git found the repository in ~/bin, which is in my PATH.
Does git search for repositories by looking in $PATH, or is there another search mechanism at work?
I can't find a definitive reference for the actual details, but we can infer most of it from the documentation to the git repository variables.
Git looks for its a repository, by order of preference:
in a directory provided by the --git-dir argument
in a directory provided by the GIT_DIR environment variable
in subdirectory .git or the current directory
in subdirectory .git of an ancestor directory. Environment variables GIT_CEILING_DIRECTORIES and GIT_DISCOVERY_ACROSS_FILESYSTEMS set a few constraints on that.
According to the git(1) manual page, Git goes like this when it looks for its object store:
If the "--git-dir" command-line option was specified its value is used to locate the repository.
If the GIT_DIR environment variable is available and set its value is used to locate the repository.
Note that in both of these cases no search/heuristics is done.
Otherwise Git tries to figure out if the current directory is the repository — in case it's a bare repository which has no work tree.
The logic it uses to carry out this task is explained here. To cite it:
Test if it looks like we're at a git directory.
We want to see:
- either an objects/ directory _or_ the proper
GIT_OBJECT_DIRECTORY environment variable
- a refs/ directory
- either a HEAD symlink or a HEAD file that is formatted as
a proper "ref:", or a regular file HEAD that has a properly
formatted sha1 object name.
Failing that, Git tries to find a directory named ".git" in the current directory.
If it succeeds, it uses the test from the previous step to verify if it's really what it was looking for.
If it fails, it ascends one level up — to the parent directory and tries again.
The last two steps are carried out until / on POSIX-like systems or the root of the drive — on Windows is hit (and hence there's nothing to ascent). By default, Git also won't cross the boundary of a filesystem of the current directory.
As you can see, no $PATH is involved: this directory is used only to look up executable programs, and Git has no business with it.

How to build a project using Cargo in an offline environment?

I have a laptop with an OS X system which can access the internet, and a Linux server which can not access internet for some security reason.
I want to build a Rust project with some dependency on the Linux server. Because the Linux server can not access internet, I run the cargo build command on the OSX laptop and download the dependency source file to the .cargo directory and then copy these files to the Linux server and put them into /root/.cargo directory.
I made the file structures the same, but when I run cargo build on the Linux server, it still tries to connect to this website and the build fails. The cargo build command always tries to connect internet although the dep source files are already in the .cargo directory.
How can I build a Rust project with dependencies in an offline environment? Why does copying the source file of the dependencies not work?
Good News! As of Rust 1.37, you can use Cargo's own vendor command to download and bundle your crate's dependencies in the crate itself:
First, run cargo vendor. This will setup a new directory named vendor in the root of your crate. It will then download dependencies from crates.io and git, and store them in this new directory.
When cargo vendor is done downloading all the required dependencies, it will print a set of instructions that you'll need to follow. At the time of this writing, you only need to copy a few lines to .cargo/config.toml. Note that config.toml is relative to the root of your crate and is not the one in your home directory.
Once you're done, your crate will be completely self-contained as far as dependencies are concerned. You can couple this approach with Rust's offline installers to build Rust programs completely offline.
For Rust 1.37+ see: https://stackoverflow.com/a/65254702/147192
The short answer is: up to 1.37 (excluded), it's complicated.
The long answer is that cargo will attempt to connect to github in order to check the index of the crates that the Cargo.toml file references.
I recommend you to check the cargo-vendor prototype to solve this issue (by aturon, a member of the Rust tooling subteam), and otherwise you could look at how some people created a mirror for crates.io in order to avoid the dependency on Internet.
There is a demand for Rust builds not to require Internet, and people working on it, however there is no blessed solution for now.
Check out romt - Rust Offline Mirror Tool.
Romt (Rust Offline Mirror Tool) aids in using the Rust programming language in an offline context. Instructions and tooling are provided for:
Mirroring of Rust ecosystem artifacts:
Toolchains (Rustc, Cargo, libraries, etc.)
Rustup (toolchain multiplexer)
Crates.io (community-supplied Crates)
Incremental artifact downloading.
Incremental artifact transfer to offline network.
Artifact serving in offline context (offline computer, disconnected network).
I could replace official crates.io registry use by adding this
.cargo/config file in my project (under windows %USERPROFILE%\.cargo\config seems ignored) :
[source]
[source.mirror]
registry = "http://localhost:8185/auser/crates.io-index.git"
[source.crates-io]
replace-with = "mirror"
Also works using a file based git registry clone:
registry = "file://c:/github/crates.io-index.git"
downloaded either using git clone --bare or --mirror
cargo build now print
Updating 'c:\github\crates.io-index.git' index
instead of Updating crates.io index

Changing the location of git installation on linux

I apologize if this seems basic but I'm new to linux and not really sure how to proceed. My current git version is 1.7.1 and is located in /usr/bin/git but a newer version of git (1.8) is now available in /usr/src/git/bin/git. How do I make git use this version by default as opposed to the 1.7.1 version?
You have to make sure to call the right executable. This can ben done by explicitly calling /usr/src/git/bin/git instead of git. Of course this would be annoying to type all the time, so you can either make git an alias for that path by adding the line
alias git=/usr/src/git/bin/git
to your .bashrc, or add the directory /usr/src/git/bin to your binary search path by adding the line
export PATH="/usr/src/git/bin:$PATH"
To test that the other git installation searches for the core binaries in the right place, you can check the output of git --exec-path.

Git clone without including top/parent folder

We have a repo in git where the project is contained in a folder called Project. We'd like to be able to release the code to a production server, by cloning the repo, without including the "Project" folder, but with everything below it. Is this possible? The destination directory name is /var/www, which is unrelated to anything in the project. Unfortunately I can't just do a symbolic link because of the nature of our hosting provider (which we'll change soon).
My answer take the assumption that you have a git repository whose content is the following:
/.gitignore
/Project
/Project/index.php
/ProjectB
/ProjectB/pom.xml
If you don't need history at all in that copy of your repository, there is the git archive command which can do what you want except its output its data in tar or zip format:
git archive [--format=<fmt>] [--list] [--prefix=<prefix>/] [<extra>]
[-o <file> | --output=<file>] [--worktree-attributes]
[--remote=<repo> [--exec=<git-upload-archive>]] <tree-ish>
[<path>…]
Like:
git archive --format=zip --remote=git#foobar.git master -- Project | unzip
However, the git clone command does not accept a repository path, and I think it's not really git like to export only a tree view of some branch. You would probably need a submodule making Project an independent git repository, or like the git archive example, get only what you want but without versioning (which can be questionable on a production server).
Instead, you can do that:
Clone your repository to whatever path, say /opt/foobar.
Create a symbolic link of /opt/foobar/Project in /var/www.
Or reference the /opt/foobar/Project in your apache configuration (to avoid the symlink) instead of plain /var/www.

Specify SVN destination folder name in Buildbot

I'm setting up buildbot to build a project. The project's code is stored in SVN and it uses a couple of libs in our SVN repository.
When performing a manul build, what I need to do is (of course) to checkout the main project and the libs. The command used to checkout the libs is something like:
svn co svn://<path_to_lib_repo>/trunk mylib
That way the code of the library is stored in a local folder called "mylib" where the makefiles will look for.
Is there a way to configure the SVN build step to have the code checked-out to a folder with a custom name, as above? I did not found a way so far.
As a (temporarly?) workaround on Linux, I'm using the ShellCommand() step building myself the svn command, but I really don't like such solution.
Use the workdir paraemter to set the directory where you want the files. For example:
f.addStep(SVN(name='pull.src', repourl=svn://<path_to_lib_repo>/trunk,
workdir='mylib',
description='pull.src'))

Resources