aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/usr/bin/.drive-write-driveselect
blob: df35e1fb791a487d818742222c177da7b6a373d7 (about) (plain)
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#!/bin/bash
###################################################################################################
# .drive-write-driveselect
###################################################################################################
# Copyright 2017-2022 Jean-Christophe Manciot <jcmanciot@sdxlive.com>
#
# Licensed under a GPLv3 License.
# You may not use this file except in compliance with the License. You may obtain a copy of the 
# License at:
#
#    https://www.gnu.org/licenses/gpl-3.0.md
#
# The licensor cannot revoke these freedoms as long as you follow the license terms.
#
# Attribution — You must give appropriate credit, provide a link to the license, and indicate if 
#               changes were made. You may do so in any reasonable manner, but not in any way that 
#               suggests the licensor endorses you or your use.
###################################################################################################

###################################################################################################
#
# Writing into the file .driveselect the <objects> (files/folders) under rhe right [<command>] 
# section.
# If the file is already present locally prior to the call, all entries (list of objects) 
# within the corresponding section [<command>] will be replaced.
#
###################################################################################################
#
# Requirements:
# ------------
#
# - We assume that drive-google package is already installed.
#
# - This command must be called from within your local Google Drive folder(s).
#
###################################################################################################
#
# Parameters:
# ----------
#
# - <command>: related command corresponding to the section within .driveselect.
#              Cf. /etc/drive-google/.driveselect for a list of currently supported commands.
#
# - <objects>: Array listing all objects which need to be placed in the related [<command>] 
#              section.
#              Cf. /etc/drive-google/.driveselect for its format.
#
###################################################################################################
#
# Usage examples:
# --------------
# cd ~/<google_drive_folder>/parent/folder/
# .drive-write-driveselect push "${objects_to_push[@]}" 
#
###################################################################################################
if [[ $LOG_DRIVE_WRITE_DRIVESELECT == ON ]]; then
        # Getting the last existing file descriptor of ~/.drive-google/logs/drive-google.log
        fd=$(ls -al /proc/$$/fd | grep ~/.drive-google/logs/drive-google.log | sed -E 's|^.* ([0-9]+) -> .*$|\1|g' | sort -V | tail -n 1)

        # Case where fd is unset, i.e the file ~/.drive-google/logs/drive-google.log has not yet been opened
        if [[ -z $fd ]]; then
                lowest_unused_fd () 
                {
                        local fd=0
                        while [ -e /proc/$$/fd/${fd} ]; do
                                fd=$((fd+1))
                        done
                        echo $fd
                }
                fd=$(lowest_unused_fd)

                # Opening ~/.drive-google/logs/drive-google.log as file descriptor $fd for appending
                eval "exec $fd>> ~/.drive-google/logs/drive-google.log"
        fi

        # Writing the trace output generated when set -x is enabled to file descriptor $fd 
        eval "BASH_XTRACEFD=$fd"
        # Logging line numbers - We could also use ${0} for ${BASH_SOURCE}
        BASH_SOURCE_BASENAME=$(basename ${BASH_SOURCE})
        export PS4='${BASH_SOURCE_BASENAME}.${LINENO}+ '
        # Expanding all variables and prints the full commands before output of the command
        set -x
fi

# Preventing globbing (pathname expansion)
set -o noglob
# Allowing extended globbing
shopt -s extglob
# Expanding aliases
shopt -s expand_aliases

# Including alias definitions to sed/grep/awk/perl commands for readability sake
. /usr/include/drive-google/aliases

command=$1
shift
declare -a objects=("$@")

section='out'
first_line_to_delete=1
number_of_lines_to_delete=0
eof=false

# Purging the section [$command] if .driveselect exists
if [[ -f ".driveselect" ]]; then
        # We will include a [$command] section at the end containing the relevant object names
        # Removing all occurences of $command within [section] when the section name contains also another command
        # This spares some tests later on and makes the algorithm much simpler
        # Case n°1: $command is leading
        sed -E -i "s|^(\[)${command}\/(.*)|\1\2|g" .driveselect
        # Case n°2: $command is in between 2 other commands
        sed -E -i "s|^(\[.*\/)${command}\/(.*)|\1\2|g" .driveselect
        # Case n°3: $command is trailing
        sed -E -i "s|^(\[.*)\/${command}(\])|\1\2|g" .driveselect

        # Removing all object names within .driveselect file in the right [$command] section
        while [[ $eof == false ]]
        do
                read -r line
                if [[ $? -ne 0 ]]; then
                        eof=true
                fi

                # Checking for blank lines or comments
                if [[ ($section == 'out') && ((-z "${line}") || ("${line}" =~ ^#)) ]]; then
                        ((first_line_to_delete++))
                elif [[ ($section == 'out') && (! "$line" =~ ^\[$command\]) ]]; then
                        ((first_line_to_delete++))
                elif [[ ($section == 'out') && ("$line" =~ ^\[$command\]) ]]; then
                        # Case n°4: $command is alone
                        section='in'
                        ((first_line_to_delete++))
                elif [[ ($section == 'in') && (("$line" =~ \[.*\]) || ($eof == true)) ]]; then
                        if [[ ! ("$line" =~ ^\[$command\]) ]]; then
                                # We've just finished reading a [$command] section
                                # Removing all lines in the right [$command] section
                                # first_line_to_delete will point to first line below next [section] after that block removal
                                sed --follow-symlinks -i "`expr ${first_line_to_delete} - 1`,`expr ${first_line_to_delete} + ${number_of_lines_to_delete} - 1`d" .driveselect
                                section='out'
                        # We may have several [delete] sections in a row and they will all be removed
                        fi
                elif [[ $section == 'in' ]]; then
                        ((number_of_lines_to_delete++))
                fi
        done < ".driveselect"
fi

# Exiting if $objects is empty
if [[ ${#objects[@]} -eq 0 ]]; then
        exit 0
fi

# [${command}] section line added in .driveselect
echo "[${command}]" >> .driveselect            

# Sorting & deduplicating the object names in alphabatical order
# Dismissing the first columns describing the object stats
if [[ ${#objects[@]} -ne 0 ]]; then
        sorted_objects=()
        IFS=$'\n' sorted_objects=($(sort -r -u -t ' ' -k 3 <<<"${objects[*]}"))
        unset IFS
fi

# Saving the object names in the right [$command] section
for object in "${sorted_objects[@]}"
do
        # Escaping the '$.*/[\]^' characters in sed searched string
        # Letters, digits and (){}+?| must not be escaped
        esc_object="$(echo "$object" | escape_sed_bre_search_string)"

        # Inserting $object in the right section [$command]
        sed --follow-symlinks -i "/^\[${command}\]/a ${esc_object}" .driveselect
done

exit 0