The order of execution in Makefile - "rm -rf" does not finish on time? - linux

Makefile:
# Defines
BUILD_PATH ?= out
REPO_NAME ?= my_work_dir
REPO_URL ?= git#github.com:your_org/your_repo
REPO_BRANCH := main
### Functions
define clone_repository
echo Cloning repository...
git -C $(1) init --quiet
git -C $(1) remote add origin $(2)
git -C $(1) fetch origin --progress --quiet --depth 1 $(3)
git -C $(1) reset --quiet --hard FETCH_HEAD
endef
define get_sha1
$(2):=$(shell git -C $(1) rev-parse HEAD)
endef
### Targets
do_the_work:
# Prepare
rm -rf $(BUILD_PATH)/$(REPO_NAME)
mkdir -p $(BUILD_PATH)/$(REPO_NAME)
# Clone
$(call clone_repository,$(BUILD_PATH)/$(REPO_NAME),$(REPO_URL),$(REPO_BRANCH))
# SHA1
$(eval $(call get_sha1,$(BUILD_PATH)/$(REPO_NAME),REPO_BRANCH_SHA1))
# Do...
# do_something --sha1 REPO_BRANCH_SHA1
What I tried to do in the do_the_work is:
Step 1: create an empty dir
Step 2: clone repository
Step 3: get sha1 from repository
Step 4: do something with sha1 info
However, when I execute the do_the_work, I get error (please not that $(BUILD_PATH)/$(REPO_NAME) evaluates to out/my_work_dir):
fatal: cannot change to 'out/my_work_dir': No such file or directory
rm -rf out/my_work_dir
mkdir -p out/my_work_dir
echo Cloning repository...
.
.
.
etc
But, when I run the same command again, it executes OK! Is this because the out/my_work_dir is in place already? It also works if the dir is completely empty.
Seems like the Step 3 $(eval $(call get_sha1...) executed before the Step 1 mkdir finished? How do I fix this?
To me it seems that rm -rf gets prolonged if the dir does not exist at all.

The error is in the $(shell ...) invocation in define get_sha1 which runs when you define the function, not when you call it.
This seems like an overcomplication anyway; I would simply get rid of the define and replace the recipe with one where the result is stored in a shell variable.
do_the_work:
...
# SHA1
sha1=$$(git -C $(BUILD_PATH)/$(REPO_NAME) rev-parse HEAD); \
# Do...
# do_something --sha1 "$$sha1"

Related

Make execute commands on folder context multiple times

I'm having a makefile which under proj root dir.
Folder proj is the main folder and there is folders such as ws-led or tools-ext etc under it which contains docker files.
In addition, there is also Makefile which is under the root that needs to run all the commands.
This is the folder structure
proj
- ws-led
— Dockerfile
- tools-ext
— Dockerfile
- Makefile
What I need is to cd to each of the folders under the rot (we have many more) and run:
docker build <folder name> .
Example: ( exactly like running the following command manually )
cd ws-led
docker build -t ws-led .
cd tools-ext
docker build -t tools-ext .
I try with the following (maybe instead of repo param I get run on all the folders in the same level of the Makefile )
Like (CURDIR) …
all: pre docker-build
.PHONY: pre docker-build
repos := ws-led tools-ext
pre:
$(patsubst %,docker-build,$(repos))
docker-build:pre
cd $*; docker build -t $* . >&2 | tee docker-build
while using this im getting an error:
invalid argument "." for "-t, --tag" flag: invalid reference format
Any idea what is wrong here ? or i could do it better?
As I've many repos/folders I want to use make to handle it
There's more than one way to do it.
You could use a bash for loop:
docker-build:
for dir in $(repos); do cd $$dir; docker build -t $$dir . >&2 | tee docker-build; done
Or use a pattern rule (or in this case a static pattern rule):
REPO_BUILDS := $(addsuffix -build, $(repos))
docker-build: $(REPO_BUILDS)
.PHONY: $(REPO_BUILDS)
$(REPO_BUILDS): %-build:
cd $*; docker build -t $* . >&2 | tee docker-build

Installing reaction-platform on windows, getting error like `Parameter format not correct`

I'm trying to install reaction-platform on my windows system. I have cofirmed the dependancies mentioned, everything seems fine.
I'm fllowing the official documentation.
https://docs.reactioncommerce.com/docs/installation-reaction-platform
When I run make command getting issue like:
28ec31dc0e9cba366bdbb724ce1f9733b327aae90801f371c234437748d7d688
abc5351b5c17853153771d8a9e868d4f443106bb908d23f6672531cd6105364c
dc796c6d02a715ccd9e1133157cb770e5399ed66184202186c1151d520e1d03b
Running pre-build hook script for reaction-hydra. reaction-hydra
post-project-start script invoked. FIND: Parameter format not correct
make: *** [prebuild-reaction-hydra] Error 2
Here is the makefile:
#gnu makefile
# This Makefile provides macro control of the Reaction Platform microservice
# ecosystem. It performs tasks like:
#
# * Verify dependencies are present
# * Clone git projects, checkout a particular reference
# * Preconfiguration and subproject bootstrapping
# * Launching subprojects
# * Teardown tasks with varying destructiveness
#
#
# Exit codes:
#
# All failures should exit with a detailed code that can be used for
# troubleshooting. The current exit codes are:
#
# 0: Success!
# 101: Github is not configured correctly.
# 102: Required dependency is not installed.
#
###############################################################################
### Configuration
### Load configuration from external files. Configuration variables defined in
### later files have precedent and will overwrite those defined in previous
### files. The -include directive ensures that no error is thrown if a file is
### not found, which is the case if config.local.mk does not exist.
###############################################################################
-include config.mk config.local.mk
SUBPROJECTS=$(foreach rr,$(SUBPROJECT_REPOS),$(shell echo $(rr) | cut -d , -f 2))
###############################################################################
### Tasks
###############################################################################
all: init
###############################################################################
### Init-Project
### Initializes a project. Does not do common tasks shared between projects.
###############################################################################
define init-template
init-$(1): $(1) network-create prebuild-$(1) build-$(1) post-build-$(1) start-$(1) post-project-start-$(1)
endef
$(foreach p,$(SUBPROJECTS),$(eval $(call init-template,$(p))))
###############################################################################
### Init Project with System
### Init project and run the post-system hook script.
### Assumes dependencies are already started.
###############################################################################
define init-with-system-template
init-with-system-$(1): init-$(1) post-system-start-$(1)
endef
$(foreach p,$(SUBPROJECTS),$(eval $(call init-with-system-template,$(p))))
.PHONY: init
init: $(foreach p,$(SUBPROJECTS),init-$(p)) post-system-start
###############################################################################
### Targets to verify Github is configured correctly.
###############################################################################
github-configured: dependencies
#(ssh -T git#github.com 2>&1 \
| grep "successfully authenticated" >/dev/null \
&& echo "Github login verified.") \
|| (echo "You need to configure an ssh key with access to github" \
&& echo "See https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/ for instructions" \
&& exit 101)
###############################################################################
### Verify prerequisite software is installed.
###############################################################################
is-not-installed=! (command -v $(1) >/dev/null)
define dependency-template
dependency-$(1):
#if ( $(call is-not-installed,$(1)) ); \
then \
echo "Dependency" $(1) " not found in path." \
&& exit 102; \
else \
echo "Dependency" $(1) "found."; \
fi;
endef
$(foreach pkg,$(REQUIRED_SOFTWARE),$(eval $(call dependency-template,$(pkg))))
.PHONY: dependencies
dependencies: $(foreach pkg,$(REQUIRED_SOFTWARE),dependency-$(pkg))
###############################################################################
### Create Docker Networks
### Create all networks defined in the DOCKER_NETWORKS variable.
### Networks provide a way to loosely couple the projects and allow them to
### communicate with each other. We'll use dependencies on external networks
### rather than dependencies on other projects. Networks are lightweight and
### easy to create.
###############################################################################
define network-create-template
network-create-$(1):
#docker network create "$(1)" || true
endef
$(foreach p,$(DOCKER_NETWORKS),$(eval $(call network-create-template,$(p))))
.PHONY: network-create
network-create: $(foreach p,$(DOCKER_NETWORKS),network-create-$(p))
###############################################################################
### Remove Docker Networks
### Remove all networks defined in the DOCKER_NETWORKS variable.
###############################################################################
define network-remove-template
network-remove-$(1):
#docker network rm "$(1)" || true
endef
$(foreach p,$(DOCKER_NETWORKS),$(eval $(call network-remove-template,$(p))))
.PHONY: network-remove
network-remove: $(foreach p,$(DOCKER_NETWORKS),network-remove-$(p))
###############################################################################
### Git cloning
###############################################################################
define git-clone-template
$(2):
if [ ! -d "$(2)" ] ; then \
git clone "$(1)" "$(2)"; \
cd $(2) && git checkout "$(3)"; \
fi
endef
$(foreach rr,$(SUBPROJECT_REPOS),$(eval $(call git-clone-template,$(shell echo $(rr) | cut -d , -f 1),$(shell echo $(rr) | cut -d , -f 2),$(shell echo $(rr) | cut -d , -f 3))))
.PHONY: clone
clone: github-configured $(foreach p,$(SUBPROJECTS),$(p))
###############################################################################
### Git checkout
### Checkout the branch configured in the platform settings.
### Does not gracefully deal with conflicts or other problems.
###############################################################################
define git-checkout-template
checkout-$(2): $(2)
cd $(2) && git checkout "$(3)"
endef
$(foreach rr,$(SUBPROJECT_REPOS),$(eval $(call git-checkout-template,$(shell echo $(rr) | cut -d , -f 1),$(shell echo $(rr) | cut -d , -f 2),$(shell echo $(rr) | cut -d , -f 3))))
.PHONY: checkout
checkout: clone $(foreach p,$(SUBPROJECTS),checkout-$(p))
###############################################################################
### Pre Build Hook
### Invokes the pre-build hook in the child project directory if it exists.
### Invoked before the Docker Compose build.
###############################################################################
define prebuild-template
prebuild-$(1): $(1)
#if [ -e "$(1)/$(HOOK_DIR)/pre-build" ]; then \
echo "Running pre-build hook script for $(1)." \
&& "$(1)/$(HOOK_DIR)/pre-build"; \
else \
echo "No pre-build hook script for $(1). Skipping."; \
fi;
endef
$(foreach p,$(SUBPROJECTS),$(eval $(call prebuild-template,$(p))))
.PHONY: prebuild
prebuild: $(foreach p,$(SUBPROJECTS),prebuild-$(p))
###############################################################################
### Docker Build
### Performs `docker-compose build --no-cache --pull`
### This is a very conservative build strategy to avoid cache related build
### issues.
###############################################################################
define build-template
build-$(1): prebuild-$(1)
#cd $(1) \
&& docker-compose build --no-cache --pull
endef
$(foreach p,$(SUBPROJECTS),$(eval $(call build-template,$(p))))
.PHONY: build
build: $(foreach p,$(SUBPROJECTS),build-$(p))
###############################################################################
### Post Build Hook
### Invokes the post-build hook in the child project if existent.
### Invoke after all services in a project have been built.
###############################################################################
define post-build-template
post-build-$(1): build-$(1)
#if [ -e "$(1)/$(HOOK_DIR)/post-build" ]; then \
echo "Running post-build hook script for $(1)." \
&& "$(1)/$(HOOK_DIR)/post-build"; \
else \
echo "No post-build hook script for $(1). Skipping."; \
fi;
endef
$(foreach p,$(SUBPROJECTS),$(eval $(call post-build-template,$(p))))
.PHONY: post-build
post-build: $(foreach p,$(SUBPROJECTS),post-build-$(p))
###############################################################################
### Start
### Starts services with `docker-compose up -d`
###############################################################################
define start-template
start-$(1):
#cd $(1) \
&& docker-compose up -d
endef
$(foreach p,$(SUBPROJECTS),$(eval $(call start-template,$(p))))
.PHONY: start
start: $(foreach p,$(SUBPROJECTS),start-$(p))
###############################################################################
### Post Project Start Hook
### Invokes the post-project-start hook in the child project if existent.
### Invoked after all services in a project have been started.
###############################################################################
define post-project-start-template
post-project-start-$(1):
#if [ -e "$(1)/$(HOOK_DIR)/post-project-start" ]; then \
echo "Running post-project-start hook script for $(1)." \
&& "$(1)/$(HOOK_DIR)/post-project-start"; \
else \
echo "No post-project-start hook script for $(1). Skipping."; \
fi;
endef
$(foreach p,$(SUBPROJECTS),$(eval $(call post-project-start-template,$(p))))
###############################################################################
### Post System Start Hook
### Invokes the post-system-start hook in the child projects if existent.
### Invoked after all services in the system have been started.
###
### Note: The final echo is required otherwise output of post-system-hook is
### not output.
###############################################################################
define post-system-start-template
post-system-start-$(1):
#if [ -e "$(1)/$(HOOK_DIR)/post-system-start" ]; then \
echo "Running post-system-start hook script for $(1)." \
&& "$(1)/$(HOOK_DIR)/post-system-start" \
&& echo ""; \
else \
echo "No post-system-start hook script for $(1). Skipping."; \
fi;
endef
$(foreach p,$(SUBPROJECTS),$(eval $(call post-system-start-template,$(p))))
.PHONY: post-system-start
post-system-start: $(foreach p,$(SUBPROJECTS),post-system-start-$(p))
###############################################################################
### Stop
### Stops services with `docker-compose stop`
###############################################################################
define stop-template
stop-$(1):
#cd $(1) \
&& docker-compose stop
endef
$(foreach p,$(SUBPROJECTS),$(eval $(call stop-template,$(p))))
.PHONY: stop
stop: $(foreach p,$(SUBPROJECTS),stop-$(p))
###############################################################################
### rm
### Remove containers with `docker-compose rm`
### Does not remove volumes.
###############################################################################
define rm-template
rm-$(1):
#cd $(1) \
&& docker-compose rm --stop --force
endef
$(foreach p,$(SUBPROJECTS),$(eval $(call rm-template,$(p))))
.PHONY: rm
rm: $(foreach p,$(SUBPROJECTS),rm-$(p))
###############################################################################
### Clean
### Clean services with `docker-compose rm`
### Removes all containers, volumes and local networks.
###############################################################################
define clean-template
clean-$(1):
#cd $(1) \
&& docker-compose down -v --rmi local --remove-orphans
endef
$(foreach p,$(SUBPROJECTS),$(eval $(call clean-template,$(p))))
.PHONY: clean
clean: $(foreach p,$(SUBPROJECTS),clean-$(p)) network-remove
###############################################################################
### Destroy
### Deletes project directories after removing running containers.
### WARNING: This is extremely destructive. It will remove local project
### directories. Any work that is not pushed to a remote git
### repository will be lost!
###
###############################################################################
define destroy-template
destroy-$(1): clean
#rm -Rf $(1)
endef
$(foreach p,$(SUBPROJECTS),$(eval $(call destroy-template,$(p))))
.PHONY: destroy
destroy: network-remove $(foreach p,$(SUBPROJECTS),destroy-$(p))
###############################################################################
### Dynamically list all targets.
### See: https://stackoverflow.com/a/26339924
###############################################################################
.PHONY: list
list:
#$(MAKE) -pRrq -f $(MAKEFILE_LIST) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$#$$' | xargs -n 1
Any help would be appriciated.
Run the make file in a gitbash terminal or wsl2. The problem is that the make file doesn't convert the commands in it correctly.
I have got an alternat solution to install/run reaction-commerce on windows platform. Using npm and reaction-cli.
https://docs.reactioncommerce.com/docs/next/installation-windows
Still I'm looking for the solution / fix with docker.

Build on shell condition with Make

I would like to add to a build list the packages I want to build if it is not installed yet.
The goal is to install some Python packages without pip and from local sources. I don't have access to pip...
So I wrote I Makefile that looks like:
all: natsort foo bar foobar ...
natsort: natsort-4.0.4.tar.gz
tar xvzf $<
cd $(patsubst %.tar.gz,%, $<) && python setup.py install
rm -rf $(patsubst %.tar.gz,%, $<)
python -c 'import natsort'
echo -e "Installation of $< [done]\n" >> install.log
The problem with this implementation is that all the packages will be rebuild and reinstalled each time I run the Make command. I would like to check if the module is already installed. My idea is to do something like this:
ifdef $(shell python -c 'import natsort')
all: natsort
endif
How can I rewrite this to make it works?
You can absolutely do something like that. But it "costs" a shell invocation and an invocation of python every time you run make and that's a relatively high cost.
There are, basically, two ways to do what you want in a cheaper manner.
A stamp file and short-circuiting logic in the recipe.
The stamp file method is basically what you have except you add touch $# to the end of the recipe.
natsort: natsort-4.0.4.tar.gz
tar xvzf $<
cd $(patsubst %.tar.gz,%, $<) && python setup.py install
rm -rf $(patsubst %.tar.gz,%, $<)
python -c 'import natsort'
echo -e "Installation of $< [done]\n" >> install.log
touch $#
That way running the recipe the first time creates the stamp file and until natsort-4.0.4.tar.gz becomes newer than the stamp file or the stamp file gets deleted the recipe will never run again.
Note that second point though. Delete the stamp file and you install again.
That's the thing that the short-circuit logic solution solves.
Instead of your original rule of multiple commands you wrap it all in one command (this is optional but saves repeated checking costs) and check for the module to be installed before doing any work.
natsort: natsort-4.0.4.tar.gz
if ! python -c 'import natsort'; then \
tar xvzf $< || exit 1; \
cd $(patsubst %.tar.gz,%, $<) && python setup.py install || exit 1; \
rm -rf $(patsubst %.tar.gz,%, $<); \
python -c 'import natsort' || exit 1; \
echo -e "Installation of $< [done]\n" >> install.log; \
fi
Note the need to add || exit 1 since we no longer have make handling that for us. Also note that this now always runs the rule (and we should mark natsort and .PHONY) but in the most common case it will stop after the if test.
That all said you can combine these methods to get the best of both worlds.
natsort: natsort-4.0.4.tar.gz
if ! python -c 'import natsort'; then \
tar xvzf $< || exit 1; \
cd $(patsubst %.tar.gz,%, $<) && python setup.py install || exit 1; \
rm -rf $(patsubst %.tar.gz,%, $<); \
python -c 'import natsort' || exit 1; \
echo -e "Installation of $< [done]\n" >> install.log; \
fi
touch $#
and you get the benefits of both methods. The first time you run make the natsort file doesn't exist and the recipe is run. natsort isn't installed so the if test fails and the installation occurs. After that the natsort file it touched. The next time make is installed natsort is newer than natsort-4.0.4.tar.gz so make doesn't think it has anything to do. If, for some reason, you delete the natsort file then the next time make runs it checks for the module to exist, skips the installation and touches the natsort file again to get back into sync.

In a bash script, git does not recognize it own directory?

So I have written a bash script within Atlassian-Stash for post-receive events. In this script, after a commit has been made, it creates a codecollaborator code review. To create a code review, it needs commit title, commit user and git SHA for any changes and uploading the changes to the code review. To get these informations, I clone'd the directory to --depth=1 (even without --depth=1) and work with git log (options).
The problem I am seeing is that if I run the script manually, it works just fine. However, if it runs after a commit has been made, it errors out after it clones the directory saying it is not a git directory. If I cd into the directory after the script exits, I am able to run git log (and other git commands).
Things I tried to troubleshoot are
1. Permissions issues (running it as root), so I am not seeing any permissions issues.
2. troubleshooting it with bash -xv and until that point everything looks good.
3. I also put it status checks with $?
4. I tried to move .git to git-backup, wait 3 seconds and moved it back, still the same issue.
5. I ran ls -ltra to make sure that it has all the files and .git directory.
Now, I am out of options. Has anyone ran into this kind of problem before?
Anyone know where I might be doing something wrong or missing something?
I tried to be as descriptive as possible, if the question does not make sense or need a sample script, please let me know.
Adding the script and its error output below.
#!/bin/bash -xv
CCollabExe='/usr/local/bin/ccollab'
CCollabUrl='--url http://***:8080'
CCollabUser='--user ******'
CCollabPassword='--password ******'
CCollabConnection="${CCollabExe} ${CCollabUrl} ${CCollabUser} ${CCollabPassword}"
CCollabStuff='/home/stash/repositories/tmp'
CloneDir="${CCollabStuff}/ClonnedDir"
StashUser='******'
StashPass='******'
RepoURLlinkGit="http://${StashUser}:${StashPass}#******:7990/scm/t/test1.git"
unset SSH_ASKPASS
# Test function to check if a varibale is empty
CheckIfVarEmpty () {
local Variable="$1"
if [[ -z ${Variable} ]] ; then
echo "Variable $1 '\${Variable}' is empty, exiting"
echo "Lets try to go back in the git dir" && cd ${CloneDir} && git log -10
cd /root && cd ${CloneDir}
[[ -d .git ]] && cp -rp .git git-backup && rm -rf .git && echo "sleeping 3" && sleep 3 && mv git-backup .git
git log -10
exit 0
fi
}
#Create a new CCollab temp dir, clone the directory and get commit title, user and SHA info
rm -rf ${CCollabStuff} && mkdir ${CCollabStuff} && cd ${CCollabStuff}
git clone ${RepoURLlinkGit} ${CloneDir}
cd ${CloneDir}
# below is where its erroring out.
CommitTitle=$(git log --pretty=format:"%s" -1)
CheckIfVarEmpty ${CommitTitle}
CommitUser=$(git log --pretty=format:"%an" -1)
CheckIfVarEmpty ${CommitUser}
CommitSHA=$(git log --pretty=format:"%h" -2)
CheckIfVarEmpty ${CommitSHA}
CommitSHA1=$(echo $CommitSHA | awk -F' ' '{ print $1 }')
CommitSHA2=$(echo $CommitSHA | awk -F' ' '{ print $2 }')
echo "=========="
Error out is:
remote: rm -rf ${CCollabStuff} && mkdir ${CCollabStuff} && cd ${CCollabStuff}
remote: + rm -rf /home/stash/repositories/tmp
remote: + mkdir /home/stash/repositories/tmp
remote: + cd /home/stash/repositories/tmp
remote: git clone ${RepoURLlinkGit} ${CloneDir}
remote: + git clone http://******:******#******:7990/scm/t/test1.git /home/stash/repositories/tmp/ClonnedDir
remote: Cloning into '/home/stash/repositories/tmp/ClonnedDir'...
remote: cd ${CloneDir}
remote: + cd /home/stash/repositories/tmp/ClonnedDir
remote: CommitTitle=$(git log --pretty=format:"%s" -1)
remote: git log --pretty=format:"%s" -1
remote: ++ git log --pretty=format:%s -1
remote: fatal: Not a git repository: '.'
I know nothing about Atlassian but it's clear from the error output that you're tripping over one of the hook traps I noted in an answer I can't find now:
In a git hook, the environment variable GIT_DIR is set (to . in --bare repos, to .git in non-bare ones). This is valid only until you cd to some other directory, often in a sub-process run from the hook script that has no idea that $GIT_DIR is pointing off to some now-inappropriate place.
(The git clone step works because it is not looking for a git directory, it's just creating a new one.)
The quick and easy fix is unset GIT_DIR.

How to run a series of commands with a single command in the command line?

I typically run the following commands to deploy a particular app:
compass compile -e production --force
git add .
git commit -m "Some message"
git push
git push production master
How can I wrap that up into a single command?
I'd need to be able to customize the commit message. So the command might look something like:
deploy -m "Some message"
There are two possibilities:
a script, as others answered
a function, defined in your .bash_profile:
deploy() {
compass compile -e production --force &&
git add . &&
git commit -m "$#" &&
git push &&
git push production master
}
Without arguments, you'd have a third option, namely an alias:
alias deploy="compass compile -e production --force &&
git add . &&
git commit -m 'Dumb message' &&
git push &&
git push production master"
You could create a function that does what you want, and pass the commit message as argument:
function deploy() {
compass compile -e production --force
git add .
git commit "$#"
git push
git push production master
}
Put that in your .bashrc and you're good to go.
You can make a shell script. Something that looks like this (note no input validation etc):
#!/bin/sh
compass compile -e production --force
git add .
git commit -m $1
git push
git push production master
Save that to myscript.sh, chmod +x it, then do something like ./myscript.sh "Some message".
You can write a shell script for this
#!/bin/bash
compass compile -e production --force
git add .
git commit -m $1
git push
git push production master
Save this to 'deploy' and do a chmod 7xx on it. Now you can use it as ./deploy "Some message"
you could write these commands into a file named deploy.sh .
Then make it executable and run as sh deploy.sh
You could even add it to your path by exporting the path where you save the script.
everyone mentions about writing a script and this is probably the best way of doing it.
However you might someday want to use another way - merge commands with &&, for example:
cd ../ && touch abc
will create a file "abc" in a parent directory :)
It is just to let you know about such thing, for this particular scenario (and 99% of the others) please take a look at other answers :)
I would go through the effort of making the command work for more than just the current directory. One of the most versitle ways of doing this is to use getopt in a BASH script. Make sure you have getopt installed, create deploy.sh then chmod 755 deploy.sh and then do something like this:
#!/bin/bash
declare -r GETOPT=/usr/bin/getopt
declare -r ECHO='builtin echo'
declare -r COMPASS=/path/to/compass
declare -r GIT=/path/to/git
sanity() {
# Sanity check our runtime environment to make sure all needed apps are there.
for bin in $GETOPT $ECHO $COMPASS $GIT
do
if [ ! -x $bin ]
then
log error "Cannot find binary $bin"
return 1
fi
done
return 0
}
usage() {
$CAT <<!
${SCRIPTNAME}: Compile, add and commit directories
Usage: ${SCRIPTNAME} -e <env> [-v]
-p|--path=<path to add>
-c|--comment="Comment to add"
-e|--environment=<production|staging|dev>
Example:
$SCRIPTNAME -p /opt/test/env -c "This is the comment" -e production
!
}
checkopt() {
# Since getopt is used within this function, it must be called as
# checkopt "$#"
local SHORTOPT="-hp::c::e::"
local LONGOPT="help,path::,comment::,environment::"
eval set -- "`$GETOPT -u -o $SHORTOPT --long $LONGOPT -n $SCRIPTNAME -- $#`"
while true
do
case "$1" in
-h|--help)
return 1
;;
-|--path)
PATH="$2"
shift 2
;;
-c|--comment)
COMMENT=$2
shift 2
;;
-e|--environment)
ENV="$2"
shift 2
;;
--)
shift
break
;;
*)
$ECHO "what is $1?"
;;
esac
done
}
if ! sanity
then
die "Sanity check failed - Cant find proper system binaries"
fi
if checkopt $#
then
$ECHO "Running Compass Compile & Git commit sequence..."
$COMPASS compile -e $ENV --force
$GIT add $PATH
$GIT commit -m $COMMENT
$GIT push
$GIT push ENV master
else
usage
exit 1
fi
exit 0

Resources