Skip to content

Commit

Permalink
Merge branch 'whole-repo'
Browse files Browse the repository at this point in the history
* whole-repo:
  Add documentation for whole directory linking
  Add guards for using whole directory mode in bad ways
  Don't copy over .git when linking whole repos
  Allow linking of entire repositories
  • Loading branch information
jasoncodes committed Jun 5, 2013
2 parents f4747ae + b98f408 commit 8d74a92
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 27 deletions.
3 changes: 2 additions & 1 deletion README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,11 @@ fresh jasoncodes/dotfiles config/pryrc --file --marker

#### Sourcing whole directories of files

Whole directories can be built and symlinked by including a trailing slash on the `--file` path:
Whole directories or repositories can be built and symlinked by including a trailing slash on the `--file` path:

``` sh
fresh mutt --file=~/.mutt/
fresh tpope/vim-pathogen . --file=~/.vim/bundle/vim-pathogen/ # whole repository
```

#### Building files without symlinking
Expand Down
75 changes: 49 additions & 26 deletions bin/fresh
Original file line number Diff line number Diff line change
Expand Up @@ -153,55 +153,75 @@ EOF
SOURCE_DIR="$REPO_DIR"
else
SOURCE_DIR="$FRESH_LOCAL"
if [[ "$FILE_NAME" == '.' ]]; then
_fatal_error "Cannot source whole of local dotfiles."
fi
fi

# check the source file exists
if [[ $(find "$SOURCE_DIR" -path "$SOURCE_DIR/$FILE_NAME" | wc -l) -lt 1 ]]; then
# but not if we are locking to a git ref
# since we would be checking the working tree
if [[ ! -n "$REF" ]]; then
if [[ ! -n "$REF" ]] && [[ "$FILE_NAME" != '.' ]]; then
_fatal_error "Could not find \"$FILE_NAME\" source file."
fi
fi
}

_file_list() {
if [[ "$FILE_NAME" == '.' ]]; then
if [[ "$MODE" != file ]]; then
_fatal_error "Whole repositories can only be sourced in file mode."
fi
if [[ "$MODE_ARG" != */ ]]; then
_fatal_error "Whole repositories require destination to be a directory."
fi
fi
if [[ -n "$REF" ]]; then
cd "$SOURCE_DIR"
local MATCHED=0
while read FILE_PATH; do
if [[ "$FILE_PATH" == $FILE_NAME ]]; then
if ! echo "${FILE_PATH#$FILE_NAME}" | grep -q /; then
if [[ "$(basename "$FILE_PATH")" != .* ]] || [[ "$(basename "$FILE_NAME")" == .* ]]; then
echo "$FILE_PATH"
MATCHED=1
fi
fi
fi
if _prefix_match "$FILE_PATH" "$FILE_NAME/"; then
if [[ "$FILE_NAME" == '.' ]]; then
echo "$FILE_PATH"
MATCHED=1
else
if [[ "$FILE_PATH" == $FILE_NAME ]]; then
if ! echo "${FILE_PATH#$FILE_NAME}" | grep -q /; then
if [[ "$(basename "$FILE_PATH")" != .* ]] || [[ "$(basename "$FILE_NAME")" == .* ]]; then
echo "$FILE_PATH"
MATCHED=1
fi
fi
fi
if _prefix_match "$FILE_PATH" "$FILE_NAME/"; then
echo "$FILE_PATH"
MATCHED=1
fi
fi
done < <(git ls-tree -r --name-only "$REF")
cd "$OLDPWD"
if [[ "$MATCHED" == 0 ]]; then
_fatal_error "Could not find \"$FILE_NAME\" source file."
fi
else
local path_glob="$SOURCE_DIR/$FILE_NAME"
if basename "$FILE_NAME" | grep -q '^\.'; then
local not_name_glob=''
if [[ "$FILE_NAME" == '.' ]]; then
find "$SOURCE_DIR" -type f -not -path "$SOURCE_DIR/.git/*"
else
local not_name_glob='.*'
fi
if [[ -d $path_glob ]]; then
find "$path_glob" -type f -not -name "$not_name_glob"
else
find "$SOURCE_DIR" -path "$path_glob" -not -name "$not_name_glob" -type f | while read FILE_PATH; do
if ! echo "${FILE_PATH#$path_glob}" | grep -q /; then
echo "$FILE_PATH"
fi
done
local path_glob="$SOURCE_DIR/$FILE_NAME"
if basename "$FILE_NAME" | grep -q '^\.'; then
local not_name_glob=''
else
local not_name_glob='.*'
fi
if [[ -d $path_glob ]]; then
find "$path_glob" -type f -not -name "$not_name_glob"
else
find "$SOURCE_DIR" -path "$path_glob" -not -name "$not_name_glob" -type f | while read FILE_PATH; do
if ! echo "${FILE_PATH#$path_glob}" | grep -q /; then
echo "$FILE_PATH"
fi
done
fi
fi
fi | sort
}
Expand Down Expand Up @@ -279,10 +299,13 @@ _fresh_file() {
do
if [ -n "$MODE_ARG" ]; then
if echo "$MODE_ARG" | grep -q '/$'; then
if [[ -n "$REF" ]]; then
local base_path="$FILE_NAME/"
if [[ "$FILE_NAME" == '.' ]]; then
local base_path=
else
local base_path="$SOURCE_DIR/$FILE_NAME/"
local base_path="$FILE_NAME/"
fi
if [[ -z "$REF" ]]; then
local base_path="$SOURCE_DIR/$base_path"
fi
if echo "$MODE_ARG" | grep -q '^[~/]'; then
local dest_dir="$(echo "$MODE_ARG" | sed -e 's/^~\///' -e 's/\/$//' -e 's/[/ ]/-/g' -e 's/^\.//')"
Expand Down
93 changes: 93 additions & 0 deletions test/fresh_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,99 @@ EOF
assertTrue 'can traverse symlink' '[ -f ~/.other/file1 ]'
}

it_links_directory_of_generic_files_for_whole_repo() {
stubGit
mkdir -p $FRESH_PATH/source/repo/name/{.git,.hidden-dir,sub} $FRESH_LOCAL

echo 'fresh repo/name . --file=~/.foo/' >> $FRESH_RCFILE

echo file1 > $FRESH_PATH/source/repo/name/file1
echo file2 > $FRESH_PATH/source/repo/name/sub/file2
touch $FRESH_PATH/source/repo/name/{.git,.hidden-dir}/some-file

runFresh

assertFileMatches $SANDBOX_PATH/err.log <<EOF
EOF

assertEquals "$FRESH_PATH/build/foo" "$(readlink ~/.foo)"

assertFileMatches $FRESH_PATH/build/foo/file1 <<EOF
file1
EOF
assertFileMatches $FRESH_PATH/build/foo/sub/file2 <<EOF
file2
EOF

assertFalse 'git repo is not copied' '[ -e $FRESH_PATH/build/foo/.git ]'
assertTrue 'hidden dirs are copied' '[ -e $FRESH_PATH/build/foo/.hidden-dir ]'

assertTrue 'can traverse symlink' '[ -f ~/.foo/file1 ]'
assertTrue 'can traverse symlink' '[ -f ~/.foo/sub/file2 ]'
}

it_links_directory_of_generic_files_for_whole_repo_with_ref() {
stubGit
mkdir -p $FRESH_PATH/source/repo/name/.git $FRESH_LOCAL

echo 'fresh repo/name . --file=~/.foo/' --ref=abc123 >> $FRESH_RCFILE

runFresh

assertFileMatches $SANDBOX_PATH/err.log <<EOF
EOF

assertEquals "$FRESH_PATH/build/foo" "$(readlink ~/.foo)"

assertFileMatches $FRESH_PATH/build/foo/ackrc <<EOF
test data for abc123:ackrc
EOF
assertFileMatches $FRESH_PATH/build/foo/recursive-test/abc/def <<EOF
test data for abc123:recursive-test/abc/def
EOF

assertTrue 'can traverse symlink' '[ -f ~/.foo/ackrc ]'
assertTrue 'can traverse symlink' '[ -f ~/.foo/recursive-test/abc/def ]'
}

it_errors_if_trying_to_use_whole_repo_with_invalid_arguments() {
stubGit
mkdir -p $FRESH_PATH/source/repo/name/.git $FRESH_LOCAL

# good
echo 'fresh repo/name . --file=~/.good/' > $FRESH_RCFILE
runFresh
assertFalse 'does not output an error' '[ -s $SANDBOX_PATH/err.log ]'

# invalid path to --file
echo 'fresh repo/name . --file=~/.bad-path' > $FRESH_RCFILE
runFresh fails
assertFileMatches <(grep Error $SANDBOX_PATH/err.log) <<EOF
$(echo $'\033[4;31mError\033[0m:') Whole repositories require destination to be a directory.
EOF

# missing path to --file
echo 'fresh repo/name . --file' > $FRESH_RCFILE
runFresh fails
assertFileMatches <(grep Error $SANDBOX_PATH/err.log) <<EOF
$(echo $'\033[4;31mError\033[0m:') Whole repositories require destination to be a directory.
EOF

# missing --file
echo 'fresh repo/name .' > $FRESH_RCFILE
runFresh fails
assertFileMatches <(grep Error $SANDBOX_PATH/err.log) <<EOF
$(echo $'\033[4;31mError\033[0m:') Whole repositories can only be sourced in file mode.
EOF

# missing repo
echo 'fresh . --file=~/.bad-local/' > $FRESH_RCFILE
runFresh fails
assertFileMatches <(grep Error $SANDBOX_PATH/err.log) <<EOF
$(echo $'\033[4;31mError\033[0m:') Cannot source whole of local dotfiles.
EOF
}

it_builds_bin_files() {
echo 'fresh scripts/sedmv --bin' >> $FRESH_RCFILE
echo 'fresh pidof.sh --bin=~/bin/pidof' >> $FRESH_RCFILE
Expand Down

0 comments on commit 8d74a92

Please sign in to comment.