repo指令碼是作為整個repo工具的入口,只要負責repo環境的初始化和轉殖repo庫。repo有兩處if __name== 『__main__』,位於開始部分主要是給shell執行用的,位於末尾的部分是給python執行用的。
來看看repo引導指令碼的前幾行。
1 #!/bin/sh
2
3 repo_url='git:'
4 repo_rev='stable'
6 magic='--calling-python-from-/bin/sh--'
7 """exec"python -e "$0" "$@" """#$magic"
8 if __name__ == '__main__':
9 import sys
10 if sys.argv[-1] == '#%s' % magic:
11 delsys.argv[-1]
12 del magic
從第1行可以看出,這個指令碼是用shell指令碼寫的。第7行既是一條合法的shell語句,又是一條合法的python語句。如果作為shell語句,執行exec,用python呼叫本指令碼,並替換本程序。三引號在這裡相當於乙個空字串和乙個單獨的引號。如果作為python語句,三引號定義的是乙個字串,字串後面是乙個注釋。實際上第1行到第7行,既是合法的shell語句又是合法的python語句。從第8行開始都是python語句。repo引導指令碼無論是用shell執行,還是用python執行,效果都相當於使用python執行這個指令碼。
在引導指令碼repo的main函式中,首先呼叫_findrepo()函式,從當前目錄開始依次向上遞迴查詢.repo/repo/main.py檔案。如果找到了.repo/repo/main.py指令碼,則把程式的控制權交給.repo/repo/main.py指令碼。
從main主方法開始看起:
1、執行_findrepo()函式,返回找到的.repo/repo/main.py指令碼檔案,以及包含repo/main.py的.repo目錄。
2、執行_parsearguments()函式,分析命令列引數,分析出哪些是命令,哪些是引數。
3、執行_runself()函式,判斷本次執行所需的指令碼和目錄(main.p檔案、git_config.py、project.py、.git目錄和subcmds目錄)是否存在,如果存在返回main.py檔案和.git目錄的絕對路徑。
4、如果main.py不存在,則執行_init()函式(如執行repoinit命令)。如果沒有指定--repo-url或者--repo-branch,則採用指令碼開始定義的repo_url或者repo_rev作為預設值。repo先在本地建立乙個空的repo庫,然後設定註冊遠端庫,最後呼叫_clone()函式轉殖repo庫。
5、如果main.py存在(如執行reposync命令),則移交控制權給main.py,並將引數傳遞給main.py。
這裡完成權利交接,下面就該
main.py
顯身手了。
在main.py中有這麼一句:from subcmds import all_commands,它表示從模組包subcmds中匯入所有命令。在包的每個目錄中必須包含乙個名為」__init__.py」(init的前後均是兩條下劃線)的檔案。」__init__.py」可以是乙個空檔案,僅用來表示該目錄為乙個包。__init__.py是初始化模組,from-import語句匯入子包時需要用到它。
「__init__.py」的主要用途是設定」__all__」變數以及包含包初始化所需的**。在匯入包內所有名字時在from中使用」*」萬用字元,」__all__」可以保證名字的正確匯入。
__init__.py的**如下:
1 import os
2 all_commands = {}
4 my_dir = os.path.dirname(__file__)
5 print __file__, 'variable --> my_dir',my_dir
6 for py in os.listdir(my_dir):
7 ifpy == '__init__.py':
8 continue
9 ifpy.endswith('.py'):
10 name = py[:-3]
11 clsn = name.capitalize()
12 while clsn.find('_') >0:
13 h =clsn.index('_')
14 clsn =clsn[0:h] + clsn[h + 1:].capitalize()
15 mod =__import__(__name__,
16 globals(),
17 locals(),
18 ['%s' % name])
19 mod = getattr(mod, name)
20 try:
21 cmd =getattr(mod, clsn)()
22 except attributeerror:
23 raisesyntaxerror, '%s/%s does not define class %s' % (
24 __name__, py, clsn)
25 name = name.replace('_','-')
26 print __file__, 'variable--> cmd_name', name
27 cmd.name = name
28 all_commands[name]= cmd
29 if 'help' in all_commands:
30 all_commands['help'].commands= all_commands
main.py負責具體命令的執行,包括manifests庫的轉殖的檢出。main.py的結構和repo指令碼類似。
1、從subcmds匯入repo的相關命令。
2、執行init_ssh()函式(在git_confit.py中實現),完成ssh驗證,包括使用者名稱、郵箱位址等。
3、執行init_http()函式,進行網路驗證。
4、解析manifest.xml,沒有指定的就是預設名稱。
5、通過getattr方式執行命令。_run()函式根據命令的名稱,執行subcmds下相應的檔案。例如,repoinit就是執行subcmds/init.py,repo sync就是執行subcmds/sync.py。
鏈結指令碼分析
鏈結三要素 鏈結順序,鏈結位址,載入位址 1.連線順序的問題 倘若有鏈結指令碼,則會按照鏈結指令碼的規則進行鏈結。例如 sections second x30000000 at 4096 這個規則中定義了兩個大段,first和second。first的鏈結順序為head.o init.o nand....
openwrt啟動指令碼分析
openwrt啟動指令碼分析 1.linux核心的配置檔案由下面兩個檔案組成 a.target linux generic 2.4 config default b.target linux brcm 2.4 config default 在配置檔案中可以看到 config cmdline root...
bbb 燒寫指令碼分析
ftp伺服器位址,即ccs uniflash的位址 server ip 192.168.2.1 boot partition boot partition.tar.gz rootfs partition rootfs partition.tar.gz 要燒寫的emmc的裝置名稱 drive dev ...