Subscribed unsubscribe Subscribe Subscribe

JPMartha's Pancake

This blog is the way to brush up my poor English.

Carthage の bootstrap について調べたこと 🙋

前回同様、コマンドラインツールを作成する際に Carthage を参考にしたので、自分で挙動を理解しておくために調べました。

Thanks Carthage ! 😊

github.com

Carthage の bootstrap とは

Carthage プロジェクト の script フォルダにある bootstrap という名前のシェルスクリプトです。

Carthage/README.md at 696142fec7800309ed6eda6479894bbbb6955b40 · Carthage/Carthage · GitHub

ざっくり言うと

  • git のサブモジュールを更新します。
  • この記事 で説明した Makefile から呼び出します。(Part 9)

説明

前提

  • あくまでこのファイルだけを対象とします。
  • 用語に誤りなどがあればちょいちょい直していきます。
  • 断片的でわかりづらいかもしれませんが上から順に区切って説明します。
  • Part は説明用に付けた独自のものです。

Part 1

#!/bin/bash

This is known as an interpreter line. If you don’t specify an interpreter line, the default is usually the Bourne shell (/bin/sh). However, it is best to specify this line anyway for consistency.

Shell Script Basics

bash - GNU Bourne-Again SHell

Part 2

export SCRIPT_DIR=$(dirname "$0")

The export and declare -x commands allow parameters and functions to be added to and deleted from the environment.

  • dirname

    ディレクトリ名を取得します。

extract the directory part of a pathname

  • $0

    このファイル名です。

If bash is invoked with a file of commands, $0 is set to the name of that file.

Part 3

##
## Bootstrap Process
##
  • #

    コメントです。

COMMENTS

In a non-interactive shell, or an interactive shell in which the interactive_comments option to the shopt builtin is enabled (see SHELL BUILTIN COMMANDS below), a word beginning with # causes that word and all remaining characters on that line to be ignored. An interactive shell without the interac-tive_comments option enabled does not allow comments. The interactive_comments option is on by default in interactive shells.

Part 4

main ()
{
    local submodules=$(git submodule status)
    local result=$?

    if [ "$result" -ne "0" ]
    then
        exit $result
    fi

    if [ -n "$submodules" ]
    then
        echo "*** Updating submodules..."
        update_submodules
    fi
}

$ git submodule status コマンドを実行して長さが 0 より大きい文字列が返されたら *** Updating submodules... と出力して update_submodules 関数を実行します。

  • local

    ローカル変数です。

For each argument, a local variable named name is created, and assigned value. The option can be any of the options accepted by declare. When local is used within a function, it causes the variable name to have a visible scope restricted to that function and its children. With no operands, local writes a list of local variables to the standard output. It is an error to use local when not within a function. The return status is 0 unless local is used outside a function, an invalid name is supplied, or name is a readonly variable.

  • $?

    直前に実行したコマンドのステータスです。

Exit status of last command.

  • if list; then list; [ elif list; then list; ] ... [ else list; ] fi

    if 文です。

The if list is executed. If its exit status is zero, the then list is executed. Otherwise, each elif list is executed in turn, and if its exit status is zero, the corresponding then list is executed and the command completes. Otherwise, the else list is executed, if present. The exit status is the exit status of the last command executed, or zero if no condition tested true.

  • if [ "$result" -ne "0" ]

    $result が 0 でない場合。

arg1 OP arg2

OP is one of -eq, -ne, -lt, -le, -gt, or -ge. These arithmetic binary operators return true if arg1 is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to arg2, respectively. Arg1 and arg2 may be positive or negative integers.

  • exit [n]

    ステータス n で終了します。

Cause the shell to exit with a status of n. If n is omitted, the exit status is that of the last command executed. A trap on EXIT is executed before the shell terminates.

  • -n string

 文字列の長さが 0 でない。

True if the length of string is non-zero.

Part 5

bootstrap_submodule ()
{
    local bootstrap="script/bootstrap"

    if [ -e "$bootstrap" ]
    then
        echo "*** Bootstrapping $name..."
        "$bootstrap" >/dev/null
    else
        update_submodules
    fi
}

サブモジュールに script/bootstrap が存在すれば *** Bootstrapping $name... と出力して $bootstrap を空にします。

  • -e file

    ファイルが存在すれば true です。

True if file exists.

  • >/dev/null

    空にします。

If a command is followed by a & and job control is not active, the default standard input for the command is the empty file /dev/null. Otherwise, the invoked command inherits the file descriptors of the calling shell as modified by redirections.

Part 6

update_submodules ()
{
    git submodule sync --quiet && git submodule update --init && git submodule foreach --quiet bootstrap_submodule
}

ひとつずつコマンドを実行して正常終了すれば次をコマンドを実行します。

$ git submodule sync --quiet
$ git submodule update --init
$ git submodule foreach --quiet bootstrap_submodule
  • command1 && command2

    command1 を実行して正常終了すれば command2 を実行します。

command2 is executed if, and only if, command1 returns an exit status of zero.

  • sync

    .gitmodules で指定したリモートリポジトリと同期して .git/config を更新します。

Synchronizes submodules' remote URL configuration setting to the value specified in .gitmodules. It will only affect those submodules which already have a URL entry in .git/config (that is the case when they are initialized or freshly added). This is useful when submodule URLs change upstream and you need to update your local repositories accordingly.


更新時は次のように出力されます。

⚠️ syncupdate どちらでの処理かはっきりわかりません。 🙏

Submodule 'Carthage/Checkouts/FrameworkName' (https://github.com/.../FrameworkName.git) registered for path 'Carthage/Checkouts/FrameworkName'

  • --quiet

    エラーだけ出力します。

Only print error messages.

  • update

    サブモジュールを更新します。

Update the registered submodules to match what the superproject expects by cloning missing submodules and updating the working tree of the submodules.

If the submodule is not yet initialized, and you just want to use the setting as stored in .gitmodules, you can automatically initialize the submodule with the --init option.

  • foreach

    それぞれのサブモジュールに対してコードを実行します。

submodule foreach コマンドを使うと、サブモジュールごとに任意のコードを実行してくれます。

Git - サブモジュール


Evaluates an arbitrary shell command in each checked out submodule. The command has access to the variables $name, $path, $sha1 and $toplevel: $name is the name of the relevant submodule section in .gitmodules, $path is the name of the submodule directory relative to the superproject, $sha1 is the commit as recorded in the superproject, and $toplevel is the absolute path to the top-level of the superproject. Any submodules defined in the superproject but not checked out are ignored by this command. Unless given --quiet, foreach prints the name of each submodule before evaluating the command. If --recursive is given, submodules are traversed recursively (i.e. the given shell command is evaluated in nested submodules as well). A non-zero return from the command in any submodule causes the processing to terminate. This can be overridden by adding || : to the end of the command.

Part 7

export -f bootstrap_submodule
export -f update_submodules
  • export -f

    関数を環境変数のように登録します。

The supplied names are marked for automatic export to the environment of subsequently executed commands. If the -f option is given, the names refer to functions. If no names are given, or if the -p option is supplied, a list of all names that are exported in this shell is printed. The -n option causes the export property to be removed from each name. If a variable name is followed by =word, the value of the variable is set to word. export returns an exit status of 0 unless an invalid option is encountered, one of the names is not a valid shell variable name, or -f is supplied with a name that is not a function.

Part 8

main

The bottom-most element is "main".

サンプル

自作ツール で実行した結果を記載します。

  • $ git submodule status コマンドを実行すると次のとおり出力されます。

0162c5d236be757369ca871d553b5e7287dc2510 Carthage/Checkouts/Commandant (0.8.2-19-g0162c5d)

705e63b5da3810bc177122ac665fad8dd548c96f Carthage/Checkouts/Himotoki (1.4.0)

382f9339404d24f632a5f98453c1e08a5ea55904 Carthage/Checkouts/Result (0.6.0-beta.6-35-g382f933)

5dddca29c5659dab3c726fbfa051d8e093a2cfb4 Carthage/Checkouts/SWXMLHash (2.0.0-31-g5dddca2)

5b86c515ef22bc81918dd94186f5fe53399ef9b8 Carthage/Checkouts/SourceKitten (0.10.0)

d78854b22b9567e7f30d748bdd4966c86bcc93a5 Carthage/Checkouts/xcconfigs (0.7-29-gd78854b)

  • 流れを理解するため echo を追記して $ make bootstrap コマンドを実行すると次のとおり出力されます。
main ()
{
    local submodules=$(git submodule status)
    local result=$?

    if [ "$result" -ne "0" ]
    then
        exit $result
    fi

    if [ -n "$submodules" ]
    then
        echo "1: *** Updating submodules..."
        update_submodules
    fi
}
bootstrap_submodule ()
{
    local bootstrap="script/bootstrap"

    if [ -e "$bootstrap" ]
    then
        echo "2: *** Bootstrapping $name..."
        "$bootstrap" >/dev/null
    else
        echo "2: $name"
        update_submodules
    fi
}
update_submodules ()
{
    echo "3:"
    git submodule sync --quiet && git submodule update --init && git submodule foreach --quiet bootstrap_submodule
}
  • 出力内容

1: *** Updating submodules...

3:

2: *** Bootstrapping Carthage/Checkouts/Commandant...

2: Carthage/Checkouts/Himotoki

3:

2: Carthage/Checkouts/xcconfigs

3:

2: Carthage/Checkouts/Result

3:

2: Carthage/Checkouts/SWXMLHash

3:

2: *** Bootstrapping Carthage/Checkouts/SourceKitten...

2: Carthage/Checkouts/xcconfigs

3:

*** Bootstrapping を出力しないサブモジュールは script/bootstrap を持ちません。

参考