Skip to content

Instantly share code, notes, and snippets.

@jlinoff
Last active March 7, 2017 21:42
Show Gist options
  • Save jlinoff/14c6901bbd9682a3f33efe92379e93b7 to your computer and use it in GitHub Desktop.
Save jlinoff/14c6901bbd9682a3f33efe92379e93b7 to your computer and use it in GitHub Desktop.
Demo to show how to setup a Google git-repo from scratch with 2 projects, it creates the projects, the manifest and the repo.
#!/bin/bash
#
# This example sets up two remote repositories named project1 and
# project2 in the current directory.
#
# It assumes a very old version of bash so that it can be used
# Mac OS X as well as Linux.
#
# Run it like this:
#
# $ mkdir /tmp/tryit
# $ cd /tmp/tryit
# $ cp ~/Downloads/setup.sh .
# $ chmod a+x setup.sh
# $ tree . # you must have tree installed
# $ ./setup.sh
#
# When it is done, you can run repo commands like this.
#
# $ cd myrepo
# $ ../bin/repo version
# $ ../bin/repo forall -p -c pwd
#
# Note that the bin/repo command is a wrapper that
# correctly sets the environment for new and existing
# repos.
#
# License: MIT Open Source
# Copyright (c) 2017 by Joe Linoff
# ================================================================
# Functions
# ================================================================
# Print an info message with context (caller line number)
function info() {
local Msg="$*"
echo -e "INFO:${BASH_LINENO[0]}: $Msg"
}
# Print a warning message with context (caller line number)
function warn() {
local Msg="$*"
echo -e "WARNING:${BASH_LINENO[0]}: $Msg"
}
# Print an error message and exit.
function err() {
local Msg="$*"
echo -e "ERROR:${BASH_LINENO[0]}: $Msg"
exit 1
}
# Run a command with decorations.
function runcmd() {
local Cmd="$*"
local LineNum=${BASH_LINENO[0]}
echo
echo "INFO:${LineNum}: cmd.run=$Cmd"
eval "$Cmd"
local st=$?
echo "INFO:${LineNum}: cmd.status=$st"
if (( st )) ; then
echo "ERROR:${LineNum}: command failed"
exit 1
fi
}
# ================================================================
# Main
# ================================================================
Checks=('remote-project1.git'
'remote-project2.git'
'remote-manifest.git'
'project1'
'project1a'
'project2'
'manifest'
'myrepo'
'bin'
)
for Check in ${Checks[@]} ; do
rm -rf "$Check"
if [ -e "$Check" ] ; then
err "file must not exist: $Check"
fi
done
RootDir=$(pwd)
# Create the remotes.
# The first two are for projects,
# the last one is for the remote.
runcmd git init --bare remote-project1.git
runcmd git init --bare remote-project2.git
runcmd git init --bare remote-manifest.git
# Create project1 by cloning from the remote.
runcmd git clone file://$RootDir/remote-project1.git project1
runcmd cd project1
runcmd pwd
runcmd git branch --list --all
runcmd git remote show origin
runcmd echo 'project1' '>' info.txt
runcmd git add info.txt
runcmd git commit -m "'Create info.txt'"
runcmd git push
runcmd git branch --list --all
runcmd git remote show origin
runcmd cd ..
# Create project2 from an existing git repo.
runcmd mkdir project2
runcmd cd project2
runcmd git init
runcmd echo 'project2' '>' info.txt
runcmd git add info.txt
runcmd git commit -m "'Create info.txt'"
runcmd git branch --list --all
# Now create the remote origin association.
runcmd git remote add origin file://$RootDir/remote-project2.git
runcmd git push --set-upstream origin master
runcmd git branch --list --all
runcmd git remote show origin
runcmd cd ..
# Create project1a from the project one, verify that info.txt
# exists.
runcmd git clone file://$RootDir/remote-project1.git project1a
runcmd cd project1a
runcmd ls -l info.txt
runcmd cat info.txt
runcmd cd ..
# Create the manifest.
# Create the default.xml file for project1 and project2.
# This is the hard part.
runcmd git clone file://$RootDir/remote-manifest.git manifest
runcmd cd manifest
runcmd pwd
runcmd git branch --list --all
runcmd git remote show origin
cat >default.xml <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<remote name="origin" fetch="file://$RootDir/" />
<default revision="master" remote="origin" />
<project remote="origin"
path="project1"
name="remote-project1.git" />
<project remote="origin"
path="project2"
name="remote-project2.git" />
</manifest>
EOF
runcmd cat -n default.xml
runcmd git add default.xml
runcmd git commit -m "'Add default.xml'"
runcmd git push
runcmd cd ..
# Create the official git-repo local repository if necessary.
if [ ! -d git-repo ] ; then
runcmd git clone https://gerrit.googlesource.com/git-repo
runcmd cd git-repo
runcmd git checkout stable
runcmd cd ..
fi
runcmd export REPO_URL=file://$RootDir/git-repo
runcmd git-repo/repo help init
# Create the wrapper if it is not already there.
# This sets up the environment properly for repo
# and allows it to work with existing repos that
# may have used an older version.
if [ ! -f bin/repo ] ; then
[ ! -d bin ] && runcmd mkdir bin || true
cat >bin/repo <<EOF
#!/bin/bash
Loc=$(pwd)/git-repo
export REPO_URL=file://\$Loc
# Fix the repo configuration files.
File='.repo/repo/.git/FETCH_HEAD'
if [ -f \$File ] ; then
sed -i -E -e "s@ of .*\\\$@ of \$Loc@" \$File
fi
File='.repo/repo/.git/config'
if [ -f \$File ] ; then
sed -i -E -e "s@url = .*\\\$@url = \$Loc/.git@" \$File
fi
File='.repo/repo/.git/.repo_config.json'
if [ -f \$File ] ; then
Osname="\$( uname | tr 'A-Z' 'a-z')"
case "\$Osname" in
linux)
# GNU sed is very powerful.
sed -i -E -e "/remote.origin.url/{n;d;}" \$File
sed -i -E -e "s@(remote.origin.url.*\\\$)@\\1\n \"\$Loc/.git\"@" \$File
;;
darwin)
# Posix sed is slightly different.
sed -i -E -e "/remote.origin.url/{n;d;}" \$File
sed -i -E -e "s@(remote.origin.url.*\\\$)@\\1 \"\$Loc/.git\"@" \$File
;;
*)
echo "ERROR: unknown OS type: '\$Osname'."
exit 1
;;
esac
fi
# Quote arguments.
Cmd="\$Loc/repo"
while (( \$# > 0 )) ; do
Arg="\$1"
shift
if echo "\$Arg" | egrep -q ' |\t' ; then
Cmd+=" \\"\$Arg\\""
else
Cmd+=" \$Arg"
fi
done
# Echo the command line if REPO_CMD_ECHO=yes.
case "\$REPO_CMD_ECHO" in
y|yes|t|true)
echo "\$Cmd"
;;
*)
;;
esac
# Run the command.
eval \$Cmd
st=\$?
if (( st )) ; then
echo "ERROR: command failed (\$st)."
fi
exit \$st
EOF
chmod a+x bin/repo
fi
# Now that we have the manifest and the project remotes, create the
# repo.
runcmd mkdir myrepo
runcmd cd myrepo
runcmd ../bin/repo init -u file://$RootDir/remote-manifest.git
runcmd ../bin/repo sync
runcmd ../bin/repo forall -p -c pwd
runcmd ../bin/repo --version
runcmd ../bin/repo forall -p -c "'pwd && uname && uptime'"
which tree
if (( $? == 0 )) ; then
runcmd tree .
else
warn "command not found: tree"
fi
info "done"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment