OpenWrt之feeds.conf.default詳解

2022-07-26 18:00:29

OpenWrt之feeds.conf.default詳解


檔案內容

src-git-full packages https://git.openwrt.org/feed/packages.git
src-git-full luci https://git.openwrt.org/project/luci.git
src-git-full routing https://git.openwrt.org/feed/routing.git
src-git-full telephony https://git.openwrt.org/feed/telephony.git
#src-git-full video https://github.com/openwrt/video.git
#src-git-full targets https://github.com/openwrt/targets.git
#src-git-full oldpackages http://git.openwrt.org/packages.git
#src-link custom /usr/src/openwrt/custom-feed

OpenWrt的feeds.conf.default, 是新增一些應用和包的檔案, 看過之後下面解析命令用法


命令解釋

  • 先說# , 這個是註釋用, 不會有人不知道吧

  • 這個檔案主要是由scripts/feeds這個perl指令碼控制著, 貼一個命令的定義

    my %update_method = (
    	'src-svn' => {
    		'init'		=> "svn checkout '%s' '%s'",
    		'update'	=> "svn update",
    		'controldir'	=> ".svn",
    		'revision'	=> "svn info | grep 'Revision' | cut -d ' ' -f 2 | tr -d '\n'"},
    	'src-cpy' => {
    		'init'		=> "cp -Rf '%s' '%s'",
    		'update'	=> "",
    		'revision'	=> "echo -n 'local'"},
    	'src-link' => {
    		'init'		=> "ln -s '%s' '%s'",
    		'update'	=> "",
    		'revision'	=> "echo -n 'local'"},
    	'src-dummy' => {
    		'init'		=> "true '%s' && mkdir '%s'",
    		'update'	=> "",
    		'revision'	=> "echo -n 'dummy'"},
    	'src-git' => {
    		'init'          => "git clone --depth 1 '%s' '%s'",
    		'init_branch'   => "git clone --depth 1 --branch '%s' '%s' '%s'",
    		'init_commit'   => "git clone '%s' '%s' && cd '%s' && git checkout -b '%s' '%s' && cd -",
    		'update'	=> "git pull --ff-only",
    		'update_force'	=> "git pull --ff-only || (git reset --hard HEAD; git pull --ff-only; exit 1)",
    		'post_update'	=> "git submodule update --init --recursive",
    		'controldir'	=> ".git",
    		'revision'	=> "git rev-parse --short HEAD | tr -d '\n'"},
    	'src-git-full' => {
    		'init'          => "git clone '%s' '%s'",
    		'init_branch'   => "git clone --branch '%s' '%s' '%s'",
    		'init_commit'   => "git clone '%s' '%s' && cd '%s' && git checkout -b '%s' '%s' && cd -",
    		'update'	=> "git pull --ff-only",
    		'update_force'	=> "git pull --ff-only || (git reset --hard HEAD; git pull --ff-only; exit 1)",
    		'post_update'	=> "git submodule update --init --recursive",
    		'controldir'	=> ".git",
    		'revision'	=> "git rev-parse --short HEAD | tr -d '\n'"},
    	'src-gitsvn' => {
    		'init'	=> "git svn clone -r HEAD '%s' '%s'",
    		'update'	=> "git svn rebase",
    		'controldir'	=> ".git",
    		'revision'	=> "git rev-parse --short HEAD | tr -d '\n'"},
    	'src-bzr' => {
    		'init'		=> "bzr checkout --lightweight '%s' '%s'",
    		'update'	=> "bzr update",
    		'controldir'	=> ".bzr"},
    	'src-hg' => {
    		'init'		=> "hg clone '%s' '%s'",
    		'update'	=> "hg pull --update",
    		'controldir'	=> ".hg"},
    	'src-darcs' => {
    		'init'    => "darcs get '%s' '%s'",
    		'update'  => "darcs pull -a",
    		'controldir' => "_darcs"},
    );
    
    # src-git: pull broken
    # src-cpy: broken if `basename $src` != $name
    

src-svn與src-gitsvn

'src-svn' => {
		'init'		=> "svn checkout '%s' '%s'",
		'update'	=> "svn update",
		'controldir'	=> ".svn",
		'revision'	=> "svn info | grep 'Revision' | cut -d ' ' -f 2 | tr -d '\n'"},
'src-gitsvn' => {
		'init'	=> "git svn clone -r HEAD '%s' '%s'",
		'update'	=> "git svn rebase",
		'controldir'	=> ".git",
		'revision'	=> "git rev-parse --short HEAD | tr -d '\n'"},
  • 用法:
src-svn NueXini_Packages https://github.com/NueXini/NueXini_Packages/trunk/
# 拉取預設分支
src-svn NueXini_Packages https://github.com/NueXini/NueXini_Packages/branches/v20220620
# 拉取指定分支
src-svn NueXini_Packages https://github.com/NueXini/NueXini_Packages/trunk/luci-app-disableipv6/
# 拉取指定資料夾
src-gitsvn NueXini_Packages https://github.com/NueXini/NueXini_Packages.git

src-git與src-git-full

'src-git' => {
		'init'          => "git clone --depth 1 '%s' '%s'",
		'init_branch'   => "git clone --depth 1 --branch '%s' '%s' '%s'",
		'init_commit'   => "git clone '%s' '%s' && cd '%s' && git checkout -b '%s' '%s' && cd -",
		'update'	=> "git pull --ff-only",
		'update_force'	=> "git pull --ff-only || (git reset --hard HEAD; git pull --ff-only; exit 1)",
		'post_update'	=> "git submodule update --init --recursive",
		'controldir'	=> ".git",
		'revision'	=> "git rev-parse --short HEAD | tr -d '\n'"},
		
'src-git-full' => {
		'init'          => "git clone '%s' '%s'",
		'init_branch'   => "git clone --branch '%s' '%s' '%s'",
		'init_commit'   => "git clone '%s' '%s' && cd '%s' && git checkout -b '%s' '%s' && cd -",
		'update'	=> "git pull --ff-only",
		'update_force'	=> "git pull --ff-only || (git reset --hard HEAD; git pull --ff-only; exit 1)",
		'post_update'	=> "git submodule update --init --recursive",
		'controldir'	=> ".git",
		'revision'	=> "git rev-parse --short HEAD | tr -d '\n'"},
  • 這兩者共同操作是git clone區別是clone的深度不一樣, src-git-full是全clone, 而src-git的深度為--depth 1
  • 用法: src-git-full / src-git-full 儲存的資料夾名 倉庫地址
  • 注: 後面可指定 分支, tag, commit , 不填則是拉取預設分支
src-git NueXini_Packages https://github.com/NueXini/NueXini_Packages.git;main
# 指定branch
src-git NueXini_Packages https://github.com/NueXini/NueXini_Packages.git;v20220620
# 指定tag
src-git NueXini_Packages https://github.com/NueXini/NueXini_Packages.git^47e35dd380b88d5cffc267eabe7a125da86d194b
# 指定commit

'src-cpy' => {
		'init'		=> "cp -Rf '%s' '%s'",
		'update'	=> "",
		'revision'	=> "echo -n 'local'"},
'src-link' => {
		'init'		=> "ln -s '%s' '%s'",
		'update'	=> "",
		'revision'	=> "echo -n 'local'"},

這兩個命令的唯一區別是src-cpy會複製一份源到feeds目錄, src-link則是ln -s建立一個軟連結, 我個人是比較傾向src-link的, 這樣可以修改原始碼能及時響應.

  • 用法: src-cpy / src-link 儲存的檔名 源目錄
src-link NueXini_Packages package/NueXini_Packages
# 拉取package目錄下的NueXini_Packages目錄

其他的src命令

  • bzr, hg, darcs 一些其他的分散式版本控制系統, 基本很少用到, 可以自行參考命令解釋瞭解使用方法

feeds命令用法

sub usage() {
	print <<EOF;
Usage: $0 <command> [options]
Commands:
	list [options]: List feeds, their content and revisions (if installed)
	Options:
	    -n :            List of feed names.
	    -s :            List of feed names and their URL.
	    -r <feedname>:  List packages of specified feed.
	    -d <delimiter>: Use specified delimiter to distinguish rows (default: spaces)
	    -f :            List feeds in feeds.conf compatible format (when using -s).
	install [options] <package>: Install a package
	Options:
	    -a :           Install all packages from all feeds or from the specified feed using the -p option.
	    -p <feedname>: Prefer this feed when installing packages.
	    -d <y|m|n>:    Set default for newly installed packages.
	    -f :           Install will be forced even if the package exists in core OpenWrt (override)
	search [options] <substring>: Search for a package
	Options:
	    -r <feedname>: Only search in this feed
	uninstall -a|<package>: Uninstall a package
	Options:
	    -a :           Uninstalls all packages.
	update -a|<feedname(s)>: Update packages and lists of feeds in feeds.conf .
	Options:
	    -a :           Update all feeds listed within feeds.conf. Otherwise the specified feeds will be updated.
	    -i :           Recreate the index only. No feed update from repository is performed.
	    -f :           Force updating feeds even if there are changed, uncommitted files.
	clean:             Remove downloaded/generated files.
EOF
	exit(1);
}

my %commands = (
	'list' => \&list,
	'update' => \&update,
	'install' => \&install,
	'search' => \&search,
	'uninstall' => \&uninstall,
	'feed_config' => \&feed_config,
	'clean' => sub {
		system("rm -rf ./feeds ./package/feeds ./target/linux/feeds");
	}
);

branch與commit的分割符號

sub update_feed_via($$$$$) {
	my $type = shift;
	my $name = shift;
	my $src = shift;
	my $relocate = shift;
	my $force = shift;

	my $m = $update_method{$type};
	my $localpath = "./feeds/$name";
	my $safepath = $localpath;
	$safepath =~ s/'/'\\''/;
	my ($base_branch, $branch) = split(/;/, $src, 2);
	my ($base_commit, $commit) = split(/\^/, $src, 2);

	if( $relocate || !$m->{'update'} || !-d "$localpath/$m->{'controldir'}" ) {
		system("rm -rf '$safepath'");
		if ($m->{'init_branch'} and $branch) {
			system(sprintf($m->{'init_branch'}, $branch, $base_branch, $safepath)) == 0 or return 1;
		} elsif ($m->{'init_commit'} and $commit) {
			system(sprintf($m->{'init_commit'}, $base_commit, $safepath, $safepath, $commit, $commit)) == 0 or return 1;
		} else {
			system(sprintf($m->{'init'}, $src, $safepath)) == 0 or return 1;
		}
	} elsif ($m->{'init_commit'} and $commit) {
		# in case git hash has been provided don't update the feed
	} else {
		my $update_cmd = $m->{'update'};
		if ($force && exists $m->{'update_force'}) {
			$update_cmd = $m->{'update_force'};
		}
		system("cd '$safepath'; $update_cmd") == 0 or return 1;
	}
	if ($m->{'post_update'}) {
		my $cmd = $m->{'post_update'};
		system("cd '$safepath'; $cmd") == 0 or return 1;
	}

	return 0;
}
  • 透過以上程式碼, 主要能看見branchcommit的分割是不一樣的
  • branch用的分割符號是;
  • commit用的分割符號是^
my ($base_branch, $branch) = split(/;/, $src, 2);
my ($base_commit, $commit) = split(/\^/, $src, 2);

branch與tag的區別

  • tag就是給commit的hash校驗和取的一個名字,比較直觀,方便記憶和使用

  • tag就像是一個里程碑一個標誌一個點,branch是一個新的征程一條線;tag是靜態的,branch要向前走;

  • tag 對應某次 commit, 是一個點,是不可移動的。
    branch 對應一系列 commit,是很多點連成的一根線,有一個HEAD 指標,是可以依靠 HEAD 指標移動的。

    所以,兩者的區別決定了使用方式,改動程式碼用 branch ,不改動只檢視用 tag。

  • 參考https://git-scm.com/book/zh/v2/Git-%E5%9F%BA%E7%A1%80-%E6%89%93%E6%A0%87%E7%AD%BE


Enjoy it ~