Repository navigation
Expand file tree
/
Copy pathridiff
More file actions
executable file
·140 lines (117 loc) · 3.36 KB
/
Copy pathridiff
File metadata and controls
executable file
·140 lines (117 loc) · 3.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/usr/bin/env bash
#
# Synopsis:
# Synchronize a local and remote text file using idiff and rsync.
# Usage:
# ridiff /path/to/local/file <remote-ssh-auth>
# See:
# https://github.com/jmscott/work/blob/master/idiff.c
# GNU Depends:
# realpath
# chmod # needs --reference
# Note:
# Consider moving idiff.out to starting dir instead of $HOME.
#
# Resolving the remote path is still problematic if the file system
# full path is different from the local. For example, the path to
# $HOME is /Users/jmscott on MacOS and /home/jmscott on linux,
# which affects "realpath --relative-to" in the current code.
#
PROG=$(basename $0)
START_DIR=$(pwd)
WORK_DIR=${TMPDIR:=/tmp}/$PROG.$$.d
WORK_DIR=$(realpath $WORK_DIR)
log()
{
echo "$@"
}
leave()
{
cd .. && (
rm -rf $WORK_DIR ||
log "WARN: rm work dir failed: exit status=$?" >&2
)
}
trap leave EXIT
usage()
{
echo "usage: $PROG path/to/local/file remote-ssh-auth"
}
die()
{
log "ERROR: $PROG: $@" >&2
usage >&2
exit 1
}
test $# = 2 || die "wrong number arguments: got $#, expected 2"
LOCAL_PATH="$1"
SSH_AUTH="$2"
log "local path: $LOCAL_PATH"
log "ssh auth: $SSH_AUTH"
case "$SSH_AUTH" in
*:*)
die "colon in ssh auth: $SSH_AUTH"
;;
esac
log "start directory: $START_DIR"
test -r "$LOCAL_PATH" || die "can not read local file: $LOCAL_PATH"
# Note: may break when LOCAL_PATH is relative to root. algo needs rumination.
REMOTE_PATH=$(realpath --relative-to $HOME "$LOCAL_PATH")
log "testing existance of remote file: $SSH_AUTH:$REMOTE_PATH"
ssh $SSH_AUTH "exec test -r $REMOTE_PATH" ||
die "can not read remote file: $SSH_AUTH:$REMOTE_PATH"
REAL_LOCAL_PATH=$(realpath $LOCAL_PATH)
log "real local path: $REAL_LOCAL_PATH"
test -r "$REAL_LOCAL_PATH" || die 'can not read real local path'
log "work dir: $WORK_DIR"
mkdir -p $WORK_DIR || die "mkdir work dir failed: exit status=$?"
cd $WORK_DIR || die "cd work dir failed: exit status=$?"
FILE_A=$(basename $LOCAL_PATH).a
log "local file: $FILE_A"
cp $REAL_LOCAL_PATH $FILE_A ||
die "cp local file failed: exit status=$?"
FILE_B=$(basename $LOCAL_PATH).b
log "fetch remote file: $SSH_AUTH -> $FILE_B"
rsync -va $SSH_AUTH:$REMOTE_PATH $FILE_B ||
die "rsync remote failed: exit status=$?"
if cmp $FILE_A $FILE_B; then
log "files are identical, bye"
exit 0
fi
log "invoke: idiff $FILE_A $FILE_B"
idiff $FILE_A $FILE_B || die "idiff aborted: exit status=$?"
if [ ! -e idiff.out ]; then
log 'no idiff.out file: bye'
exit 0
fi
if [ ! -s idiff.out ]; then
log 'idiff.out is empty: refuse to overwrite local/remote files'
exit 0
fi
chmod --reference "$REAL_LOCAL_PATH" idiff.out ||
die "chmod --reference idiff.out failed: exit status=$?"
echo -n "update local $LOCAL_PATH? (Y/n)? "
read RESPONSE
if [ "$RESPONSE" = Y ]; then
rsync idiff.out $REAL_LOCAL_PATH ||
die "rsync local update failed: exit status=$?"
log "local file: update: $LOCAL_PATH"
else
log "local file: not updated (ok)"
fi
echo -n "update remote $SSH_AUTH:$LOCAL_PATH? (Y/n)? "
read RESPONSE
if [ "$RESPONSE" = Y ]; then
rsync -va idiff.out $SSH_AUTH:$LOCAL_PATH ||
die "rsync remote update failed: exit status=$?"
log "remote file: update: $SSH_AUTH:$LOCAL_PATH"
else
log "remote file: not updated (ok)"
fi
SAVE=$START_DIR/ridiff.out
echo -n "mv idiff.out to $SAVE: (Y/n)? "
read RESPONSE
if [ "$RESPONSE" = Y ]; then
mv -v idiff.out $SAVE || die "mv idiff.out failed: exit status=$?"
fi
exit 0