370963d2db8b3a07029dfeaa82fa506dd05416b9
[drupal-init-tools.git] / libexec / create-profile.sh
1 #!/bin/bash
2 # Create a Drupal installation profile
3 #
4 # Copyright (C) 2017  Antonio Ospite <ao2@ao2.it>
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19 set -e
20
21 usage() {
22   cat <<EOF
23 usage: drin $(basename "$0" .sh) [-h|--help] <title> <machine_name>
24
25 Create an installation profile from the installed project.
26
27 Options:
28   -h, --help          display this usage message and exit
29 EOF
30 }
31
32 while [ $# -gt 0 ];
33 do
34   case "$1" in
35     -h|--help)
36       usage
37       exit 0
38       ;;
39     -*)
40       echo "Error: Unknown option '${1}'" 1>&2
41       ;;
42     *)
43       break
44       ;;
45   esac
46   shift
47 done
48
49
50 { [ "x$1" = "x" ] || [ "x$2" = "x" ]; } && { usage 1>&2; exit 1; }
51
52 PROFILE_TITLE="$1"
53 PROFILE_MACHINE_NAME="$2"
54
55 WEB_ROOT="${PWD}/web"
56
57 [ -d "$WEB_ROOT" ] || { echo "Aborting, run this command from the Drupal project directory." 1>&2; exit 1; }
58
59 PROJECT_ROOT="$PWD"
60
61 DRUPAL_CONSOLE="${PROJECT_ROOT}/vendor/bin/drupal"
62 DRUSH="${PROJECT_ROOT}/vendor/bin/drush"
63
64 [ -x "$DRUSH" ] || { echo "Aborting, '$DRUSH' not available." 1>&2; exit 1; }
65 [ -x "$DRUPAL_CONSOLE" ] || { echo "Aborting, '$DRUPAL_CONSOLE' not available." 1>&2; exit 1; }
66
67 PROFILE_DEST_DIR="${PROJECT_ROOT}/${PROFILE_MACHINE_NAME}"
68
69 [ -d "${PROFILE_DEST_DIR}" ] && { echo "Aborting, '${PROFILE_DEST_DIR}' already exists." 1>&2; exit 1; }
70
71 pushd "$WEB_ROOT"
72
73 CURRENT_PROFILE="$($DRUSH php-eval "echo drupal_get_profile();")"
74 CURRENT_PROFILE_PATH="$($DRUSH php-eval "echo drupal_get_path('profile', '${CURRENT_PROFILE}');")"
75
76 [ -d "$CURRENT_PROFILE_PATH" ] || { echo "Aborting, the current profile path is not valid." 1>&2; exit 1; }
77
78 # The list of modules and themes could also be obtained by exporting the
79 # configuration first and then looking at: config/install/core.extension.yml
80 # like this:
81 #
82 #  sed -e '/module:/,/^[^ ]/!d;//d' -e 's/^[ ]*\(.*\):.*$/\1/' config/install/core.extension.yml
83 #
84 # or
85 #
86 #  $DRUPAL_CONSOLE yaml:get:value "${PROFILE_DEST_DIR}/config/install/core.extension.yml" dependencies
87 #
88 # However getting them before exporting the configuration and generating the
89 # profile is cleaner.
90 #
91 ENABLED_MODULES="$($DRUSH pm-list --type=module --field=name --status=enabled --pipe | tr '\n' ',' | sed 's/,$//')"
92 ENABLED_THEMES="$($DRUSH pm-list --type=theme --field=name --status=enabled --pipe | tr '\n' ',' | sed 's/,$//')"
93
94 $DRUPAL_CONSOLE generate:profile \
95   --profile="$PROFILE_TITLE" \
96   --machine-name="$PROFILE_MACHINE_NAME" \
97   --description="Drupal installation profile for $PROFILE_TITLE" \
98   --dependencies="$ENABLED_MODULES" \
99   --themes="$ENABLED_THEMES" \
100   --profile-path="$PROJECT_ROOT" \
101   --no-interaction
102
103 # Copy private code and data from the currently installed profile
104 pushd "$CURRENT_PROFILE_PATH"
105
106 find . -maxdepth 1 -type d ! -name "tests" -printf "%P\n" |
107   while read -r dir;
108   do
109     [ -d "$dir" ] && cp -r "$dir" "${PROFILE_DEST_DIR}/"
110   done
111
112 find . -maxdepth 1 -type f ! -name "*.info.yml" -printf "%P\n" |
113   while read -r original_file;
114   do
115     DESTINATION_FILE="${PROFILE_DEST_DIR}/${original_file/#${CURRENT_PROFILE}/${PROFILE_MACHINE_NAME}}"
116     cp "${original_file}" "$DESTINATION_FILE"
117     if file "$original_file" | grep -q PHP;
118     then
119       sed -i "s/^function ${CURRENT_PROFILE}_/function ${PROFILE_MACHINE_NAME}_/g" "$DESTINATION_FILE"
120     fi
121   done
122
123 popd
124
125 # Basically do what's suggested in the "Configuration" section here:
126 # https://www.drupal.org/docs/8/creating-distributions/how-to-write-a-drupal-8-installation-profile
127 $DRUPAL_CONSOLE config:export --directory="${PROFILE_DEST_DIR}/config/install" --remove-uuid --remove-config-hash
128 rm "${PROFILE_DEST_DIR}/config/install/core.extension.yml"
129
130 # The reference to the core version could be removed, even though it is not strictly necessary.
131 find "${PROFILE_DEST_DIR}/config/install" -type f -exec sed -i -e '/^_core: {  }/d' {} \;
132
133 # Since the profile generated by `$DRUPAL_CONSOLE generate:profile` calls in
134 # the standard profile, some duplicated config files could be removed in the
135 # new profile, but that's not strictly necessary either.
136 #fdupes -f -1 "${WEB_ROOT}/core/profiles/standard/config/install/" "${PROFILE_DEST_DIR}/config/install/" | xargs rm
137
138 # Export the default content if the default_content module is there
139 if $DRUSH pm-list --type=module --field=name --status=enabled --pipe | grep -q "^default_content$";
140 then
141   $DRUSH default-content-export-references --folder="${PROFILE_DEST_DIR}/content" node
142 fi
143
144 # The code copied over from the current profile may refer to the old name.
145 # Warn the user about that.
146 if [ "$PROFILE_MACHINE_NAME" != "$CURRENT_PROFILE" ];
147 then
148   echo "The newly created profile has a name different from the current profile."
149   echo "Check that the code of the created profile refers to the new profile name."
150 fi
151
152 popd