summaryrefslogtreecommitdiff
path: root/scripts/project_file_header_fix.sh
blob: 03e31b164b90d636b9938ba915f5b2349650347f (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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
#!/bin/bash

# George Miller
# 6-10-2022
# If you do not have permission to run, try: chmod u+x project_file_header_fix.sh
#
# The purpose of this script is to update the location of header files in an xcode project by their public attribute.
# It goes backwards, finding the paths to the header files first, then backtracking to find the attributes for file.
# This was more reliable because files marked private/project have a path, but do not always have attributes.
# This script also identifies and moves any associated code files for the headers
# 
# Also,
# Any file in public/ needs to be referenced in the project header
# Any file located in private/ needs to NOT be referenced in the project header

project_file="SmartDeviceLink-iOS.xcodeproj/project.pbxproj"
target_path="SmartDeviceLink"
project_header=$target_path"/public/SmartDeviceLink.h"


# A utility function for prompting the user Y/N
# This takes in a string prompt for the input
# This returns 1 for yes/true or 0 for no/false
prompt_user() {
    user_input="g"
    echo
    echo $1" (Y/N)?"
    read user_input
    while [[ ! $user_input == [YyNn] ]]; do
        echo $1" (Y/N)?"
        read user_input
    done
    if [[ ! $user_input == [Nn] ]]; then
        return 1
    else
        return 0
    fi
}

# Make sure we are in the correct directory.
# If we are running from the scripts directory, we want to pop back to the project root to do everything.
if [[ $PWD == *"scripts" ]]; then
    cd ..
fi
# If, for some reason, we are not now in the correct working directory, exit.
if [[ $PWD != *"sdl_ios" ]]; then
    echo "Please run this from the sdl_ios project root or the sdl_ios/scripts directory"
    exit 0
fi


# Find the lines in the project file with "path".
path_lines=$(sed -n '/path/{s/[[:space:]]*//;s/\/\*.*\*\///g;s/{.*path//;p;}' $project_file)
# Filter to get only the lines with the header_filepath and fileref.
header_files=$(sed -n '/\.h/{s/[[:space:]]*//g;s/\"//g;s/\;.*//g;s/==/=/;p;}' <<< "$path_lines")

echo "Checking files for public / private correctness..."

for line in $header_files
do
    # Pick out the fileref and the header_filepath.
    fileref=$(sed -n 's/=.*//;p;' <<< $line)
    header_filepath=$(sed -n 's/.*=//;p;' <<< $line)
    
    # Use the fileref to get the attributes.
    attributes=$(sed -n '/fileRef[[:space:]]*=[[:space:]]*'$fileref'/{s/.*fileRef[[:space:]]*=[[:space:]]*'$fileref'//;s/\/\*.*\*\///g;p;};' $project_file)
    
    # Determine public or private.
    # Save off the opposite for the file path change later.
    if [[ $attributes == *"Public"* ]]; then
        header_type="public"
    else
        header_type="private"
    fi
    

    # Only look at entries where the attributes line is not empty.
    if [ ! -z "$attributes" ]; then
        # Find the real location of the file.
        file_found_location=$(find "$target_path" -name "$(basename "$header_filepath")" -maxdepth 2)
        
        # If file is found.
        if [ ! -z "$file_found_location" ]; then
            
            # Test to see if the file is where it should be. (Does the path contain the correct folder)
            if [[ ! $file_found_location == *"/$header_type/"* ]]; then
                # Add the file to the list of files that are in the wrong location.
                broken_file_list+=$file_found_location"=="$header_type"=="$fileref" "
            fi
        fi
    fi
done

# If the broken file list is not empty.
if [ ! -z "$broken_file_list" ]; then
    echo
    # List the files found for the user.
    for header_file in $broken_file_list
    do
        if [ ! -z "$header_file" ]; then
            header_filepath="${header_file%%==*}"
            header_type1="${header_file%==*}"
            header_type="${header_type1##*==}"
            fileref="${header_file##*==}"
            code_file=$(sed -n 's/\.h/\.m/p' <<< "$header_filepath")
            echo $header_filepath" and "$code_file" are marked "$header_type
        fi
    done
    
    # Prompt the user to move the files.
    prompt_user "These files were found to be out of place. Would you like to move them automatically"
    if [[ $? == 1 ]]; then
        for header_file in $broken_file_list
        do
            echo
            header_filepath="${header_file%%==*}"
            header_type1="${header_file%==*}"
            header_type="${header_type1##*==}"
            fileref="${header_file##*==}"
            
            # Figure out where the file should be located
            destiny=$target_path"/"$header_type"/"
        
            # Move the file to the correct destination
            mv -f $header_filepath $destiny
            echo "File "$header_filepath" moved to "$destiny
            
            # Figure out the opposite of the type
            if [[ $header_type == "public" ]]; then
                header_opp="private"
            else
                header_opp="public"
            fi

            # Fix path in the project file.
            # Output to a second file, then overwrite the first with the second.
            # This is done because sed does not like writing to the file it is currently reading.
            sed '/'$fileref'/{s/'$header_opp'/'$header_type'/;}' $project_file > $project_file"2"
            mv -f $project_file"2" $project_file

            # Identify associated implementation file.
            code_file=$(sed -n 's/\.h/\.m/p' <<< "$header_filepath")
            
            code_file_basename=$(basename "$code_file")
            code_file_found_location=$(find "$target_path" -name "$code_file_basename" -maxdepth 2)
            if [ ! -z "$code_file_found_location" ]; then
                if [[ ! $code_file_found_location -ef $destiny$code_file_basename ]]; then
                    # Move associated implementation file.
                    mv -f $code_file_found_location $destiny
                    echo "File "$code_file" moved to "$destiny

                    # Fix path in the project file.
                    # Output to a second file, then overwrite the first with the second.
                    # This is done because sed does not like writing to the file it is currently reading.
                    sed '/'$code_file_basename'/{s/'$header_opp'/'$header_type'/;}' $project_file > $project_file"2"
                    mv -f $project_file"2" $project_file
                else
                    echo $code_file_found_location" does not need to be moved"
                fi
            fi
        done
    fi

else
    echo "All files are in the correct folder..."
fi

# Find all header files in public/
public_file_list=$(find "$target_path"/public -name '*.h')

if [ ! -z "$public_file_list" ]; then
    for header_file in $public_file_list
    do
        file_basename=$(basename "$header_file")
        # Use sed to check to see if the file is in the project header
        found=$(sed -n '/'$file_basename'/{p;}' $project_header)
        if [ -z "$found" ]; then
            project_header_not_found_list+=$header_file" "
        fi
    done
fi

# List the files found.
if [ ! -z "$project_header_not_found_list" ]; then
    echo
    echo "These files are public and were not found in "$project_header
    for header_file in $project_header_not_found_list
    do
        echo $header_file
    done
    echo "Please add them to the project header, then press enter to continue..."
    read user_input
else
    echo "All public header files were found in "$project_header
fi

# Find all header files in private/
private_file_list=$(find "$target_path"/private -name '*.h')

if [ ! -z "$private_file_list" ]; then
    for private_header_file in $private_file_list
    do
        file_basename=$(basename "$private_header_file")

        # Use sed to check to see if the file is NOT in the project header
        found=$(sed -n '/'$file_basename'/{p;}' $project_header)
        if [ ! -z "$found" ]; then
            private_file_found_list+=$private_header_file" "
        fi
    done
fi

# List the files found.
if [ ! -z "$private_file_found_list" ]; then
    echo
    echo "These files are private and were found in "$project_header
    for private_header_file in $private_file_found_list
    do
        echo $private_header_file
    done
    echo "Please remove them from the project header, then press enter to continue..."
    read user_input
else
    echo "No private header files were found in "$project_header
fi

echo "Done checking public / private headers for correctness"