利用 iCloud Drive 來同步 Xcode 配置

前言

多年以前一位老程序員告訴筆者代碼片段(code snippets)是程序員的財(cái)富,他有一個(gè) U 盤,里面裝著他的財(cái)富底挫。每當(dāng)他需要切換電腦寫代碼的時(shí)候恒傻,他就會把把精心配置的字體、主題建邓、代碼片段等部署到新電腦上盈厘,然后開始高速編碼。每次看他寫代碼都是一種享受官边,不過這是另一個(gè)故事了沸手。

需求

多年之后,筆者也終于湊夠了錢買了自己的 Mac注簿,閑暇無事的時(shí)候也會寫寫代碼祭奠下逝去的青春契吉。但是某些時(shí)候總會覺得很別扭,例如感覺字體和單位的有細(xì)小的差距诡渴,或者一個(gè)代碼片段怎么也按不出來——最后發(fā)現(xiàn)是沒有在這臺電腦配置這段代碼片段捐晶。這種事發(fā)生的事情多了之后,就會感覺厭煩妄辩,同樣的操作為什么得重復(fù)兩次惑灵、三次?或者拿出吃了幾年灰的 U 盤抽插在各地的電腦上人工同步眼耀?就不能有什么辦法可以一次更改多次應(yīng)用英支?筆者稍微一拍腦門,想到了今天的主角——iCloud Drive

  1. 為什么使用 iCloud Drive哮伟?
    • 因?yàn)檫@是蘋果本家的網(wǎng)盤潭辈,嵌入系統(tǒng)中,只要開啟我們就無需關(guān)心上傳下載澈吨,正如 OneDrive 在 Windows 一樣把敢,我們只需要把文件放進(jìn)去,他就會自動開始上傳谅辣,并在你的每一臺蘋果設(shè)備上同步修赞。利用這點(diǎn)我們就能方便的做到在不同的設(shè)備上同步 Xcode 配置文件,無需手動同步或者上傳下載桑阶。
  2. 其他的替代方案
    • GitHub 之類的大型同性交友網(wǎng)站
      • 目前想來用 git 應(yīng)該更好更方便柏副,不過實(shí)現(xiàn)起來有點(diǎn)復(fù)雜,有能力的朋友可以自己動手
    • OneDrive/堅(jiān)果云等網(wǎng)盤
      • 我覺得能有自帶的還是用自帶的吧

思路

總所周知 Xcode 的代碼片段是保存在~/Library/Developer/Xcode/UserData/CodeSnippets路徑下的蚣录,附近位置還有主題等配置信息割择。基于筆者的經(jīng)驗(yàn)我們只需要備份同級目錄下的 CodeSnippets萎河、FontAndColorThemes 和 KeyBindings 三個(gè)子目錄就行了荔泳。每當(dāng)我們修改了代碼片段蕉饼、主題或者快捷鍵,把對應(yīng)的文件放在 iCloud Drive 同步玛歌,當(dāng)在其他電腦上時(shí)就使用最新的覆蓋到對應(yīng)目錄即可昧港。

腳本

雖說思路如此,但是筆者肯定不敢把這種三歲小孩子就能分析出來的東西發(fā)出來糊弄人支子。所以為了簡化這個(gè)繁瑣而又機(jī)械的操作创肥,筆者編寫了這樣一個(gè)腳本:

#!/usr/bin/env bash

set -euo pipefail

################# variable define ##########
now=`date "+%Y%m%d%H%M%S"`

red=`tput setaf 1`
green=`tput setaf 2`
yellow=`tput setaf 3`
reset=`tput sgr0`

xcode_dir="${HOME}/Library/Developer/Xcode/UserData"
cloud_backup_dir="${HOME}/Library/Mobile Documents/com~apple~CloudDocs/XcodeBackup"
local_backup_dir="${HOME}/資源/歸檔/XcodeBackup"

code_snippets="CodeSnippets"
font_and_color_themes="FontAndColorThemes"
key_bindings="KeyBindings"

########### MAIN ##################
# check directory exist
if [ ! -d "${cloud_backup_dir}" ]; then
    echo "${red}iCloud Drive備份路徑不存在!${reset}"
    mkdir -p "${cloud_backup_dir}"
    echo "${green}自動創(chuàng)建iCloud Drive備份路徑:${reset}${cloud_backup_dir}"
    else
    echo "${green}iCloud Drive備份路徑:${reset}${cloud_backup_dir}"
fi

if [ ! -d "${local_backup_dir}" ]; then
    echo "${red}本地備份路徑不存在值朋!${reset}"
    mkdir -p "${local_backup_dir}"
    echo "${green}自動創(chuàng)建本地備份路徑:${reset}${local_backup_dir}"
    else
    echo "${green}本地備份路徑:${reset}${cloud_backup_dir}"
fi

# zip files
cd "${xcode_dir}"
zip -r "${cloud_backup_dir}/XcodeBackup+${now}.zip" "${code_snippets}" "${font_and_color_themes}" "${key_bindings}" &
zip -r "${local_backup_dir}/XcodeBackup+${now}.zip" "${code_snippets}" "${font_and_color_themes}" "${key_bindings}" &

wait

# delete unnecessary backup files
num=`ls -l "${cloud_backup_dir}" |grep "^-"|wc -l`
if [ ${num} -gt 5 ]; then
    num=`expr ${num} - 5`
    cd "${cloud_backup_dir}"
    ls -tr "${cloud_backup_dir}" | head -${num} | xargs rm
fi

num=`ls -l "${local_backup_dir}" |grep "^-"|wc -l`
if [ ${num} -gt 5 ]; then
    num=`expr ${num} - 5`
    cd "${local_backup_dir}"
    ls -tr "${local_backup_dir}" | head -${num} | xargs rm
fi

簡化了這個(gè)繁瑣的操作叹侄,僅需在開機(jī)的時(shí)候跑一下,就能達(dá)到自動備份的效果昨登。功能也是十分的簡單:

  1. 首先創(chuàng)建了兩個(gè)備份 Xcode 配置文件的路徑圈膏,一個(gè)在云端,一個(gè)在本地(本地路徑大家可以自行配置篙骡,一般也不會用上)稽坤。
  2. 然后把 Xcode 歸檔到這兩處各一份,筆者這里選用 zip 包而不是更高壓縮比的 7zip 等是因?yàn)橄胱鐾ㄓ靡稽c(diǎn)便于大家開箱即用糯俗,不需要額外安裝其他軟件尿褪。
  3. 最后將多次運(yùn)行后生成的老包刪除,只保留最新的 5 個(gè)得湘,以便節(jié)約寶貴的空間(畢竟筆者比較窮只舍得用免費(fèi)的 5g 版)

有了這個(gè)腳本之后杖玲,大家只需要堅(jiān)持開機(jī)的時(shí)候跑一跑就行了。筆者喜歡每天開機(jī)就更新下 cocoapods淘正、brew摆马、brew cask 這類的,所以就寫了個(gè)腳本鸿吆,剛好順便也就備份一下囤采。腳本思路大致如下,因?yàn)楹椭黝}無關(guān)就不細(xì)說了惩淳。

#!/usr/bin/env bash

open 自用魔法絲襪之影

wait

pod repo update --verbose &
更新Homebrew cask &
備份各種幣錢包 &

備份Xcode等IDE配置文件 &

wait

killall 自用魔法絲襪之影

不過這樣其實(shí)也不是很方便蕉毯,畢竟打開 terminal 輸入指令都很煩了,難道還要手動計(jì)算這臺電腦的配置是否是最新的思犁?然后再考慮是不是需要把云盤里面的配置解壓到指定的位置覆蓋代虾?而且很有可能在做這些前已經(jīng)把這臺電腦的配置當(dāng)最新版上傳到云盤里了。

讓所有的電腦用同一個(gè)版本的配置

筆者再次進(jìn)行了思考激蹲。如果可以根據(jù)這些文件的最后修改日期和備份的文件進(jìn)行比較棉磨,誰新就用哪個(gè)版本,那么不就實(shí)現(xiàn)了嗎学辱?只要我們確保每次修改都跑一次腳本乘瓤,每次開機(jī)都跑一次环形,就能達(dá)到我們想要的效果了。至于如何判斷文件的最后修改時(shí)間馅扣,筆者認(rèn)為只需要一個(gè)根據(jù)文件名生成的 key 和一個(gè)對應(yīng)的文件的最后修改時(shí)間做 value 的數(shù)據(jù)結(jié)構(gòu)就行了(雖說也可以把備份的文件展開比較,但是因?yàn)楣P者才疏學(xué)淺着降,尚不知如何操作差油,就只能通過鍵值對來判斷了)
不過實(shí)際操作起來,再次彰顯了筆者的才疏學(xué)淺任洞,筆者也不知道如何在 bash 中創(chuàng)建一個(gè)高效并能持久化的鍵值對蓄喇,如果哪位大佬知道請務(wù)必告訴筆者。
最后筆者想到 Mac 自帶的 SQLite3交掏,雖說這樣一個(gè)小小的功能上數(shù)據(jù)庫是有一點(diǎn)高射炮打蚊子妆偏,但是能跑就行吧。腳本如下盅弛;

#!/usr/bin/env bash

set -euo pipefail

################# variable define ##########
now=`date "+%Y%m%d%H%M%S"`

red=`tput setaf 1`
green=`tput setaf 2`
yellow=`tput setaf 3`
reset=`tput sgr0`

xcode_dir="${HOME}/Library/Developer/Xcode/UserData"
cloud_backup_dir="${HOME}/Library/Mobile Documents/com~apple~CloudDocs/XcodeBackup"
local_backup_dir="${HOME}/資源/歸檔/XcodeBackup"

xcode_backup_database="${HOME}/Library/Mobile Documents/com~apple~CloudDocs/.BackupDatabase"

code_snippets="CodeSnippets"
font_and_color_themes="FontAndColorThemes"
key_bindings="KeyBindings"

temp="DoNotModify"
database="${xcode_backup_database}/${temp}"

########### MAIN ##################
# check directory exist
if [ ! -d "${cloud_backup_dir}" ]; then
    echo "${red}iCloud Drive備份路徑不存在钱骂!${reset}"
    mkdir -p "${cloud_backup_dir}"
    echo "${green}自動創(chuàng)建iCloud Drive備份路徑:${reset}${cloud_backup_dir}"
else
    echo "${green}iCloud Drive備份路徑:${reset}${cloud_backup_dir}"
fi

if [ ! -d "${local_backup_dir}" ]; then
    echo "${red}本地備份路徑不存在!${reset}"
    mkdir -p "${local_backup_dir}"
    echo "${green}自動創(chuàng)建本地備份路徑:${reset}${local_backup_dir}"
else
    echo "${green}本地備份路徑:${reset}${cloud_backup_dir}"
fi

if [ ! -d "${xcode_backup_database}" ]; then
    echo "${red}同步數(shù)據(jù)庫路徑不存在挪鹏!${reset}"
    mkdir -p "${xcode_backup_database}"
    echo "${green}自動創(chuàng)建數(shù)據(jù)庫路徑:${reset}${local_backup_dir}"
else
    echo "${green}數(shù)據(jù)庫路徑:${reset}${cloud_backup_dir}"
fi

sqlite3 "${database}" 'create table if not exists backupXcode(id integer primary key not NULL,key integer unique not NULL,value integer not NULL);'

#獲取最后修改時(shí)間
cd "${xcode_dir}"
if [ -d "./${code_snippets}" ]; then
    find "./${code_snippets}" -type f >> ${temp}
fi
if [ -d "./${font_and_color_themes}" ]; then
    find "./${font_and_color_themes}" -type f >> ${temp}
fi
if [ -d "./${key_bindings}" ]; then
    find "./${key_bindings}" -type f >> ${temp}
fi

while read path; do
    key=`md5 -q -s "${path}"`
    value=`stat -f "%m" "${path}"`
    isModify=`sqlite3 "${database}" "select value from backupXcode where key == '${key}';"`
    if [ -z ${isModify} ]; then
        echo "${yellow}本地Xcode配置尚未同步${reset}见秽!"
        num=`ls -l "${cloud_backup_dir}" |grep "^-"|wc -l`
        if [ ${num} -ge 1 ]; then
            echo "${green}找到最新的Xcode配置,開始自動替換${reset}讨盒!"

            cd "${xcode_dir}"
            ## backup before
            zip -r "XcodeBackup.zip" "${code_snippets}" "${font_and_color_themes}" "${key_bindings}" &
            wait

            cd "${cloud_backup_dir}"
            newBackup=`ls -t | head -1`

            unzip -u "${newBackup}" -d "${xcode_dir}" &
            wait

            cd "${xcode_dir}"
            rm ${temp}
            if [ -d "./${code_snippets}" ]; then
                find "./${code_snippets}" -type f >> ${temp}
            fi
            if [ -d "./${font_and_color_themes}" ]; then
                find "./${font_and_color_themes}" -type f >> ${temp}
            fi
            if [ -d "./${key_bindings}" ]; then
                find "./${key_bindings}" -type f >> ${temp}
            fi
            echo 更新數(shù)據(jù)庫...
            while read path; do
                key=`md5 -q -s "${path}"`
                value=`stat -f "%m" "${path}"`
                sqlite3 "${database}" "insert or replace into backupXcode values(NULL,'${key}',${value});" &
            done < ${temp}
        fi
        break
    fi
    if [ ${isModify} != ${value} ]; then
        if [ ${isModify} -gt ${value} ]; then
            echo "${yellow}本地Xcode配置超前${reset}解取!"
        else
            echo "${yellow}本地Xcode配置已經(jīng)過期${reset}!"

            num=`ls -l "${cloud_backup_dir}" |grep "^-"|wc -l`
            if [ ${num} -ge 1 ]; then
                echo "${green}找到最新的Xcode配置返顺,開始自動替換${reset}禀苦!"

                cd "${xcode_dir}"
                ## backup before
                zip -r "XcodeBackup.zip" "${code_snippets}" "${font_and_color_themes}" "${key_bindings}" &
                wait

                cd "${cloud_backup_dir}"
                newBackup=`ls -t | head -1`

                unzip -o "${newBackup}" -d "${xcode_dir}" &
                wait
            fi
        fi
        cd "${xcode_dir}"
        rm ${temp}
        if [ -d "./${code_snippets}" ]; then
            find "./${code_snippets}" -type f >> ${temp}
        fi
        if [ -d "./${font_and_color_themes}" ]; then
            find "./${font_and_color_themes}" -type f >> ${temp}
        fi
        if [ -d "./${key_bindings}" ]; then
            find "./${key_bindings}" -type f >> ${temp}
        fi
        echo 更新數(shù)據(jù)庫...
        while read path; do
            key=`md5 -q -s "${path}"`
            value=`stat -f "%m" "${path}"`
            sqlite3 "${database}" "insert or replace into backupXcode values(NULL,'${key}',${value});"
        done < ${temp}
        break
    fi
done < ${temp}

wait
rm ${temp}

# zip files
cd "${xcode_dir}"
zip -r "${cloud_backup_dir}/XcodeBackup+${now}.zip" "${code_snippets}" "${font_and_color_themes}" "${key_bindings}" &
zip -r "${local_backup_dir}/XcodeBackup+${now}.zip" "${code_snippets}" "${font_and_color_themes}" "${key_bindings}" &

wait

# delete unnecessary backup files
num=`ls -l "${cloud_backup_dir}" |grep "^-"|wc -l`
if [ ${num} -gt 5 ]; then
    num=`expr ${num} - 5`
    cd "${cloud_backup_dir}"
    ls -tr "${cloud_backup_dir}" | head -${num} | xargs rm
fi

num=`ls -l "${local_backup_dir}" |grep "^-"|wc -l`
if [ ${num} -gt 5 ]; then
    num=`expr ${num} - 5`
    cd "${local_backup_dir}"
    ls -tr "${local_backup_dir}" | head -${num} | xargs rm
fi

后記

筆者簡單測試了一下,基本上能用遂鹊。以此思路振乏,應(yīng)該也可用在 Alfred、vimrc 等配置文件秉扑。不過依舊不是很方便昆码,不過筆者才疏學(xué)淺,目前也就這個(gè)水平了邻储,希望能對大家有所幫助赋咽,不知道大家有沒有什么好的建議?筆者認(rèn)為可以在 Xcode 關(guān)閉時(shí)自動運(yùn)行本腳本吨娜,但是尚未找到好的胡克點(diǎn)(:」∠)_脓匿,如果大家有什么好的建議,歡迎PR

就這樣吧宦赠,下臺鞠躬E阏薄C啄浮!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末毡琉,一起剝皮案震驚了整個(gè)濱河市铁瞒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌桅滋,老刑警劉巖慧耍,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異丐谋,居然都是意外死亡芍碧,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進(jìn)店門号俐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來泌豆,“玉大人,你說我怎么就攤上這事吏饿∽傥#” “怎么了?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵猪落,是天一觀的道長陨倡。 經(jīng)常有香客問我,道長许布,這世上最難降的妖魔是什么兴革? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮蜜唾,結(jié)果婚禮上杂曲,老公的妹妹穿的比我還像新娘。我一直安慰自己袁余,他們只是感情好擎勘,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著颖榜,像睡著了一般棚饵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上掩完,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天噪漾,我揣著相機(jī)與錄音,去河邊找鬼且蓬。 笑死欣硼,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的恶阴。 我是一名探鬼主播诈胜,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼豹障,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了焦匈?” 一聲冷哼從身側(cè)響起血公,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎缓熟,沒想到半個(gè)月后累魔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡荚虚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年薛夜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了籍茧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片版述。...
    茶點(diǎn)故事閱讀 40,664評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖寞冯,靈堂內(nèi)的尸體忽然破棺而出渴析,到底是詐尸還是另有隱情,我是刑警寧澤吮龄,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布俭茧,位于F島的核電站,受9級特大地震影響漓帚,放射性物質(zhì)發(fā)生泄漏母债。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一尝抖、第九天 我趴在偏房一處隱蔽的房頂上張望毡们。 院中可真熱鬧,春花似錦昧辽、人聲如沸衙熔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽红氯。三九已至,卻和暖如春咕痛,著一層夾襖步出監(jiān)牢的瞬間痢甘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工茉贡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留产阱,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓块仆,卻偏偏與公主長得像构蹬,于是被迫代替她去往敵國和親王暗。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容