Linux系统下SVN服务器的搭建过程详解

Linux系统下SVN服务器的搭建过程详解 
 1 环境: 
  服务器放在redhatAS4.0上,客户端在windows 2000。 
 
  2 软件包 
 
  2.1 服务器: 
 
 
 
 
 
  subversion-1.3.2-1.rh90.i386.rpm。可能还会用到其他依赖组件,在我的配置中要用到:apr-0.9.5- 0.2.i386.rpm , neon-0.24.7-1.i386.rpm,apr-util-0.9.5-0.1.i386.rpm。 
 
  2.2 客户端: 
 
  TortoiseSVN-1.3.2.5840-svn-1.3.0 
 
  3 安装服务器 
 
  [root@localhost root]#rpm –ivh apr-0.9.5-0.2.i386.rpm 
 
  [root@localhost root]#rpm –ivh neon-0.24.7-1.i386.rpm 
 
  [root@localhost root]#rpm –ivh apr-util-0.9.5-0.1.i386.rpm 
 
  [root@localhost root]#rpm –ivh subversion-1.3.2-1.rh90.i386.rpm 
 
  安装完成以后,要测试是否已经安装成功,则要输入以下命令: 
 
  [root@localhost root]#svnserve –version 
 
  若显示如下,安装成功: 
 
  svnserve, version 1.4.0 (r21228) 
 
  compiled Oct 12 2006, 10:18:56 
 
  Copyright (C) 2000-2006 CollabNet. 
 
  Subversion is open source software, see http://subversion.tigris.org/ 
 
  This product includes software developed by CollabNet (http://www.Collab.Net/). 
 
  The following repository back-end (FS) modules are available: 
 
  * fs_fs : Module for working with a plain file (FSFS) repository. 
 
  4 Svn配置 
 
  4.1 建立版本库目录 
 
  [root@localhost root] #mkdir –p /svn 
 
  svn是我自己建立的目录,各人根据具体情况设计名字 
 
  4.2 建立一个用户,用与管理这个版本库目录 
 
  [root@localhost root] #useradd -m -s /bin/bash lyl 
 
  lyl是建立的用户名,可以根据习惯改 
 
  4.3 用建立的用户管理我们刚建的版本库目录 
 
  [root@localhost root] #chown –R lyl.lyl /svn 
 
  用lyl来管理我们的版本库目录/svn 
 
  4.4 启动服务器 
 
  用用户lyl来管理版本库目录/svn,则须转为lyl,命令如下: 
 
  [root@localhost root] #su lyl 
 
  启动svn服务 
 
  [root@localhost root] #svnserve -d -r /svn/; 
 
  -d表示以daemon方式(后台运行)运行 
 
  -r/svn/指定根目录是/svn/ 
 
  检查服务器是否启动正常: 
 
  [svn_leader@localhost root]$ ps –ef|grep svnserve 
 
  如果显示如下,即为启动成功: 
 
  lyl  6941   1 0 15:07 ?  00:00:00 svnserve -d ——listen-port 9999 -r /svn 
 5 建立版本库 
 
  [root@localhost home]# cd /svn 
 
  [root@localhost svnrepos]# svnadmin create p1; 
 
  P1可以改,在p1目录下会有下面目录:conf dav db format hooks locks README.txt 
 
 
 
 
 
  6 配置允许访问test的用户 
 
  进入到conf,命令为: 
 
  [root@localhost safety]# cd conf 
 
  出现三个文件:authz passwd svnserve.conf 
 
  6.1 修改svnserve.conf 
 
  [root@localhost conf]# vi svnserve.conf 
 
  出现: 
 
  [general] 
 
  ……………………… 
 
  # anon-access = read 
 
  # auth-access = write 
 
  ……………………… 
 
  # password-db = passwd 
 
  ……………………… 
 
  # authz-db = authz 
 
  内容修改为: 
 
  [general] 
 
  ……………………… 
 
  anon-access = none 
 
  auth-access = write 
 
  ……………………… 
 
  password-db = passwd 
 
  ……………………… 
 
  authz-db = authz 
 
  6.2 修改passwd 
 
  [root@localhost conf]# vi passwd 
 
  文件格式如下: 
 
[users] 
 
<用户1> = <密码1> 
 
<用户2> = <密码2> 
 
 其中,[users]是必须的。下面列出要访问svn的用户,每个用户一行。示例: 
 
  [users] 
 
  alan = password 
 
  king = hello 
 
  这个里面的user表示当前test版本库的成员. 
 
  6.3 修改authz 
 
  [root@localhost conf]# vi authz 
 
  用户组格式: 
 
[groups] 
 
<用户组名> = <用户1>,<用户2> 
 
  其中,1个用户组可以包含1个或多个用户,用户间以逗号分隔。用户必须要在passwd文件里能找到,它是给那个里面的user赋权限. 
 
  版本库目录格式: 
 
[/目录] 
 
@<用户组名> = <权限> 
 
<用户名> = <权限> 
 
  示例: 
 
  [groups] 
 
  admin = alan 
 
  [/] 
 
  @admin = rw 
 
  [/svn/p1/WebProject] 
 
  king = rw(表示king能够读写/svn/p1/WebProject目录下的所有信息) 
 
  [/svn/p1/web] 
 
  zp=r(表示zp能够读/svn/p1/web目录下的所有信息) 
 
  到此svn服务器的的安装和配置就已经完成了。 
网上看到的教程,拿来学习一下: 
 
简单的说SVN是一个GPL版本控制软件,其创始人是从CVS项目中出来了,其目标就是替换掉CVS,SVN尽力维持CVS的用法习惯,并增加了一些很方便但CVS做不到功能,如目录改名等。笔者使用了两个月的SVN后,感觉SVN确实做到了。 
 
SVN简介及使用说明 
 
作者:mirclle 
 
一、概述 
 
简单的说SVN是一个GPL版本控制软件,其创始人是从CVS项目中出来了,其目标就是替换掉CVS,SVN尽力维持CVS的用法习惯,并增加了一些很方便但CVS做不到功能,如目录改名等。笔者使用了两个月的SVN后,感觉SVN确实做到了。 
 
二、SVN能够做什么 
 
1、从CVS继承的功能 
 
(1)、程式码版本的存储与维护 
 
(2)、程式码版本的追踪回溯 
 
(3)、程式码版本的分合控制 
 
(4)、职员多人合作开发专案 
 
(5)、程式码远端管理维护 
 
(6)、程式码匿名截取 
 
2、在CVS基础上增添的新功能 
 
(1)、目录版本控制,目录更名 
 
在CVS 中,一个目录是没有版本历程的,假如原来一个名为doc/的目录,在经过一段时间之后,发现它应该要称为manual/比较恰当,此时我们只能建立一个新 manual/,把doc/目录下的档案复制过去,把manual/下的档案新增至CVS系统中,再把doc/删除。而且必须注意的是,在档案的复制与删除过程中,我们也同样地遗失了这些档案的历史历程。版本控制最主要的资料就这样丢掉了。 
 
但是在SVN中,目录与项目文件同样都是纳入版本控制之中。也就是说,我们可以随时要求SVN将某个项目文件恢复到某个时间点的状态,也可以对目录进行更名的动作。 
 
(2)、对多个项目文件进行不分割送交 
 
在CVS中,虽然我们可同时对多个项目文件进行送交,但是CVS并不保证一次的送交是不可分割的,而SVN的送交就没有这个问题。送交的结果不是全都进系统,就是全都没有进系统,不会只有一部分及系统的状况。 
 
(3)、更佳的二进制资料处理 
 
首先,SVN不主动更动项目内容,除非使用者加上这样的设定。再者,它使用可适用于文字与二进制资料的内容差异演算法,在项目储存上,文字与二进制资料都具有相同的优势。现在,不只是文字资料适合置于版本控制系统中,连二进制资料也可以很方便地放进来。 
 
(4)、高效率的分支与标记 
 
在SVN系统的标记是以目录的副本的方式建立的,而副本是以类似链接的方式来建立。也就是说,不管涉及的目录与项目有多少,它所花费的时间都是固定的,不会因为档案越多而耗时越久。同样的,SVN的分支也是以目录的副本来实现的。 
 
注释:1-6条是SVN继承了CVS的特点,因此,在这里不再进行详细的描述。7-10条为SVN在CVS基础上增加的新功能。 其他详细内容请参考关键词(SVN CVS SOURCESAFE 版本控制 源代码管理)。 
 
三、名词解释 
 
1、Check out——从服务器端取得代码 
 
把服务器资料库里存放的某个项目代码取出来,放到本地主机中,这个动作叫做“check out”。使用具体步骤:进入要安装项目文件的目录中,点击鼠标右键,选择SVN Check out项,然后填写项目的原始路径和安装路径后点击“ok”即可。 
 
2、Update——更新项目代码 
 
以前checkout过的一个项目代码,当服务器上有了更新的代码,或者本地代码损坏或丢失,update可以自动判断本地哪些文件较旧,或者缺少,都会自动更新。当然,你也可以删除掉本地代码,重新check out。使用具体步骤为:在要更新的项目上点击鼠标右键,选择“SVN Update”项即可。 
 
3、Commit——将本地代码上传到服务器 
 
当修改(增加,删除,修改等所有写操作)过本地代码后,这个动做会把新代码提交到SVN。如果本地代码做了修改,不执行commit操作,SVN服务器上是不会有这个新版本的,也就是说其它人也得不到。对代码做过修改后,应尽快commit。使用具体步骤:在修改完待上传的项目上点击鼠标右键,选择“SVN Commit”项即可。 
 
4、Export——将项目导出到本地 
 
如果想要得到一个完整的项目,且不需要再进行版本的改动,可以直接把该项目导出版本控制系统,成为一个普通文件进行使用。具体步骤为:单击鼠标右键,选择TortoiseSVN——>>Export项,然后填入要导出的项目既可。 
 
5、Show Log——显示所有版本 
 
如果项目成员想查看本地下载的属于版本控制内的某个项目以前的所有版本,就在该项目上单击鼠标右键,选择TortoiseSVN菜单下的Show Log项。则该项目的所有版本及其每个版本的修改信息都将显示在出现的新对话框下,供项目成员进行参考。 
 
6、Update To Revision——恢复到某个版本 
 
当项目成员想要把某个项目恢复到以前的某个版本时,在该项目上单击鼠标右键,选择TortoiseSVN菜单下的Update To Revision,于是,在出现的Update对话框中可以先点击“Show Log”来查看及确定要恢复到的版本号,或者直接将要恢复到的版本号填入“Revision”旁的编辑区内,最后点击“OK”。于是,该项目就恢复到想要的项目版本了。 
 
7、Add——增加文件 
 
当项目成员想在项目中添加一个新文件时,请把该文件先拷贝到项目文件加下,然后,在该文件上单击鼠标右键,选择TortoiseSVN菜单下的Add项,于是,该文件就可以被添加到项目中了。 
 
四、高级特性 
 
1、Update to revision 
 
Update默认更新到最新版本,update to revision则可以更新到指定版本(可以是更旧的版本)。 
 
2、增删项目文件及目录的操作 
 
增删项目内文件或目录,请一定使用svn add ,或svn del 或svn rename,然后做commit操作 
 
 
上文来自于:http://mirclle.itpub.net/post/7306/40790 
 
 
 
客户端svn的使用 
 
这里只是记录Linux下命令行客户端svn的使用。 
 
1. 第一次导入本地文件到SVN 
首先你的本地projet应该有文件夹branches, tags, trunk(为啥我暂时不知道) 
然后导入: 
 
svn import /your_projec_path file:///svn_project_path -m "initial import" 
 
2. 取出工作拷贝 
 
svn checkout file:///svn_project_path /your_local_file_name 
 
最后一个参数为下载下来的文件名字,随便起都行。 
 
3. 常用命令 
 
在checkout了拷贝之后,拷贝的目录下面有一个./.svn目录,里面记录了相关信息。 
 
svn diff : 检查本地拷贝和svn中的文件的区别 
svn log : 列出修改日志 
svn add : 把文件和目录放入版本控制中,会在下一次提交的时候加入 
svn update :更新你的拷贝 
svn commit :提交你的拷贝 
 
省下的直接 svn help command 来查询好了 
 
4.典型的工作周期是这样的: 
 

 
更新你的工作拷贝 

 
svn update 

 
做出修改 

 
svn add 

 
svn delete 

 
svn copy 

 
svn move 

 
检验修改 

 
svn status 

 
svn diff 

 
svn revert 

 
合并别人的修改到工作拷贝 

 
svn update 

 
svn resolved 

 
提交你的修改 

 
svn commit 
 
以上是基本入门的东西,复杂的合并什么的慢慢研究。 
 
 
svn命令 通常都有帮助,可通过如下方式查询: 
 
$ svn help  
 
知道了子命令,但是不知道子命令的用法,还可以查询: 
 
$ svn help add  
 
 
开发人员常用命令 
 
(1) 导入项目 
 
$ cd ~/project 
$ mkdir -p svntest/{trunk,branches,tags} 
$ svn import svntest https://localhost/test/svntest --message "Start project" 
... 
$ rm -rf svntest 
 
我们新建一个项目svntest,在该项目下新建三个子目录:trunk,开发主干;branches,开发分支;tags,开发阶段性标签。然后导入到版本库test下,然后把svntest拿掉。 
 
(2) 导出项目 
 
$ svn checkout https://localhost/test/svntest/trunk 
 
修订版本号的指定方式是每个开发人员必须了解的,以下是几个参考例子,说明可参考svn推荐书。 
 
$ svn diff --revision PREV:COMMITTED foo.c 
# shows the last change committed to foo.c 
 
$ svn log --revision HEAD 
# shows log message for the latest repository commit 
 
$ svn diff --revision HEAD 
# compares your working file (with local changes) to the latest version 
# in the repository 
 
$ svn diff --revision BASE:HEAD foo.c 
# compares your “pristine” foo.c (no local changes) with the  
# latest version in the repository 
 
$ svn log --revision BASE:HEAD 
# shows all commit logs since you last updated 
 
$ svn update --revision PREV foo.c 
# rewinds the last change on foo.c 
# (foo.c's working revision is decreased) 
 
$ svn checkout --revision 3 
# specified with revision number 
 
$ svn checkout --revision {2002-02-17} 
$ svn checkout --revision {15:30} 
$ svn checkout --revision {15:30:00.200000} 
$ svn checkout --revision {"2002-02-17 15:30"} 
$ svn checkout --revision {"2002-02-17 15:30 +0230"} 
$ svn checkout --revision {2002-02-17T15:30} 
$ svn checkout --revision {2002-02-17T15:30Z} 
$ svn checkout --revision {2002-02-17T15:30-04:00} 
$ svn checkout --revision {20020217T1530} 
$ svn checkout --revision {20020217T1530Z} 
$ svn checkout --revision {20020217T1530-0500} 
 
(3) 日常指令 
 
$ svn update 
 
$ svn add foo.file 
$ svn add foo1.dir 
$ svn add foo2.dir --non-recursive 
$ svn delete README 
$ svn copy foo bar 
$ svn move foo1 bar1 
 
$ svn status 
$ svn status --verbose 
$ svn status --verbose --show-updates 
$ svn status stuff/fox.c 
 
$ svn diff 
$ svn diff > patchfile 
 
$ svn revert README 
$ svn revert 
 
修改冲突发生时,会生成三个文件:.mine, .rOLDREV, .rNEWREV。比如: 
 
$ ls -l 
sandwich.txt 
sandwich.txt.mine 
sandwich.txt.r1 
sandwich.txt.r2 
 
解决修改冲突方式之一:修改冲突的文件sandwich.txt,然后运行命令: 
 
$ svn resolved sandwich.txt 
 
方式之二:用库里的新版本覆盖你的修改: 
 
$ cp sandwich.txt.r2 sandwich.txt 
$ svn resolved sandwich.txt 
 
方式之三:撤销你的修改,这种方式不需要运行resolved子命令: 
 
$ svn revert sandwich.txt 
Reverted 'sandwich.txt' 
$ ls sandwich.* 
sandwich.txt 
 
确保没问题后,就可以提交了。 
 
$ svn commit --message "Correct some fatal problems" 
$ svn commit --file logmsg 
$ svn commit 
 
(4) 检验版本历史 
 
$ svn log 
$ svn log --revision 5:19 
$ svn log foo.c 
$ svn log -r 8 -v 
 
$ svn diff 
$ svn diff --revision 3 rules.txt  
$ svn diff --revision 2:3 rules.txt  
$ svn diff --revision 4:5 http://svn.red-bean.com/repos/example/trunk/text/rules.txt 
 
$ svn cat --revision 2 rules.txt  
$ svn cat --revision 2 rules.txt > rules.txt.v2 
 
$ svn list http://svn.collab.net/repos/svn 
$ svn list --verbose http://svn.collab.net/repos/svn 
 
$ svn checkout --revision 1729 # Checks out a new working copy at r1729 
… 
$ svn update --revision 1729 # Updates an existing working copy to r1729 
… 
 
(5) 其他有用的命令 
 
svn cleanup 
 
为失败的事务清场。 
 
(6) 分支和合并 
 
建立分支方法一:先checkout然后做拷贝,最后提交拷贝。 
 
$ svn checkout http://svn.example.com/repos/calc bigwc 
A bigwc/trunk/ 
A bigwc/trunk/Makefile 
A bigwc/trunk/integer.c 
A bigwc/trunk/button.c 
A bigwc/branches/ 
Checked out revision 340. 
 
$ cd bigwc 
$ svn copy trunk branches/my-calc-branch 
$ svn status 
A + branches/my-calc-branch 
 
$ svn commit -m "Creating a private branch of /calc/trunk." 
Adding branches/my-calc-branch 
Committed revision 341. 
 
建立分支方法二:直接远程拷贝。 
 
$ svn copy http://svn.example.com/repos/calc/trunk / 
http://svn.example.com/repos/calc/branches/my-calc-branch / 
-m "Creating a private branch of /calc/trunk." 
 
Committed revision 341. 
 
建立分支后,你可以把分支checkout并继续你的开发。 
 
$ svn checkout http://svn.example.com/repos/calc/branches/my-calc-branch 
 
假设你已经checkout了主干,现在想切换到某个分支开发,可做如下的操作: 
 
$ cd calc 
$ svn info | grep URL 
URL: http://svn.example.com/repos/calc/trunk 
$ svn switch http://svn.example.com/repos/calc/branches/my-calc-branch 
U integer.c 
U button.c 
U Makefile 
Updated to revision 341. 
$ svn info | grep URL 
URL: http://svn.example.com/repos/calc/branches/my-calc-branch 
 
合并文件的命令参考: 
 
$ svn diff -r 343:344 http://svn.example.com/repos/calc/trunk 
$ svn merge -r 343:344 http://svn.example.com/repos/calc/trunk 
$ svn commit -m "integer.c: ported r344 (spelling fixes) from trunk." 
$ svn merge -r 343:344 http://svn.example.com/repos/calc/trunk my-calc-branch 
$ svn merge http://svn.example.com/repos/branch1@150 / 
http://svn.example.com/repos/branch2@212 / 
my-working-copy 
$ svn merge -r 100:200 http://svn.example.com/repos/trunk my-working-copy 
$ svn merge -r 100:200 http://svn.example.com/repos/trunk 
$ svn merge --dry-run -r 343:344 http://svn.example.com/repos/calc/trunk 
 
最后一条命令仅仅做合并测试,并不执行合并操作。 
 
建立标签和建立分支没什么区别,不过是拷贝到不同的目录而已。 
 
$ svn copy http://svn.example.com/repos/calc/trunk / 
http://svn.example.com/repos/calc/tags/release-1.0 / 
-m "Tagging the 1.0 release of the 'calc' project." 
 
$ ls 
my-working-copy/ 
$ svn copy my-working-copy http://svn.example.com/repos/calc/tags/mytag 
Committed revision 352. 
 
后一种方式直接把本地的工作拷贝复制为标签。 
 
此外,你还可以删除某个分支。 
 
$ svn delete http://svn.example.com/repos/calc/branches/my-calc-branch / 
-m "Removing obsolete branch of calc project." 
 
管理人员常用命令 
 
(7) 版本库管理 
 
$ svnadmin help 
... 
$ svnadmin help create 
... 
$ svnadmin create --fs-type bdb /usr/local/repository/svn/test 
$ chown -R svn.svn /usr/local/repository/svn/test 
 
建立版本库,库类型为bdb(使用Berkeley DB做仓库),库名称为test。 
svn版本库有两种存储方式:基于Berkeley DB(bdb)或者基于文件系统(fsfs),通过 --fs-type可指定存储方式。 
 
(8) 查询版本库信息 
 
$ svnlook help 
... 
$ svnlook help tree 
... 
$ svnlook tree /usr/local/repository/svn/test --show-ids 

 

subversion+apache

linux下svn服务器端+apache安装文档2007-10-19 04:26 P.M.1.下载subversion和apache的最新src包 
2. 新建一个用户:svnroot ,以下操作非特别说明皆为root用户操作 
#groupadd svn 
#useradd svnroot -g svn 
#passwd svnroot 
3. 编译安装httpd: 
//解压apache2安装包 
# tar xvzf httpd-2.2.3.tar.tar 
//进入解压后的目录 
# cd httpd-2.2.3 
//配置apache安装 
# ./configure --enable-dav --enable-so --prefix=/usr/local/apache2/ 
# make 
//安装 
# make install 
//启动apache服务 
# /usr/local/apache2/bin/apachectl start 
//打开浏览器http://localhost/如果有测试页"It works!"出现则证明已经安装成功。 
 
4. 安装Subversion 
//解压SubVersion安装包 
# tar xvzf Subversion-1.4.0.tar.gz 
//进入解压后的目录 
# cd Subversion-1.4.0 
//配置subversion安装 
#./configure --with-apxs=/usr/local/apache2/bin/apxs --prefix=/usr/local/subversion --with-apr=/usr/local/apache2 --with-apr-util=/usr/local/apache2 --with-ssl --with-zlib --enable-maintainer-mode 
# make 
//安装 
# make install 
//创建库文件所在的目录 (svnroot用户进行下面的操作) 
# mkdir /home/svnroot/repository 
//创建仓库"test" 
# /usr/local/subversion/bin/svnadmin create /home/svnroot/repository/test 
//查看svn是否安装成功 
# /usr/local/subversion/bin/svnadmin --version 
//不让其他人有该目录的权限 
# chmod 700 /home/svnroot/repository 
(svnroot用户操作结束) 
 
5. 修改Apache配置文件 
# vi /usr/local/apache2/conf/httpd.conf  
//找到下列语句,如果没有则自行添加 
LoadModule dav_svn_module modules/mod_dav_svn.so  
LoadModule authz_svn_module modules/mod_authz_svn.so  
//在后面添加  
<Location /svn>  
DAV svn  
SVNParentPath /home/svnroot/repository/ //svn父目录  
AuthzSVNAccessFile /home/svnroot/repository/authz.conf //权限配置文件  
AuthType Basic //连接类型设置  
AuthName "Subversion.zoneyump" //连接框提示  
AuthUserFile /home/svnroot/repository/authfile //用户配置文件  
Require valid-user //采用何种认证  
</Location> 
 
//重启apache 
# /usr/local/apache2/bin/apachectl restart  
//打开浏览器访问http://localhost/svn/test/,如果有东西显示就说明成功。 
 
6. 权限管理 
1)增加用户 
# htpasswd -c /home/svnroot/repository/authfile 用户名 
//第一次设置用户时使用-c表示新建一个用户文件。回车后输入用户密码,完成对用户的增加 
# htpasswd /home/svnroot/repository/authfile 用户名(加入新的用户,就不用-c了) 
 
2)权限分配 
# vi /home/svnroot/repository/authz.conf  
[groups] 
admin=useradmin 
devteamcs = useradmin,user1,user2//这里定义了一个用户组 
[/]//对所有的项目,所有的用户都有读权限,admin用户有读写权限 
@admin = rw 
* = r 
[test:/]//对test项目, 
@devteamcs = rw 
// 在 /usr/local/apache2/conf/httpd.conf 文件中配置,找到文件中的这两行: 
User daemon  
Group daemon 
// 将daemon改为svnroot,组也做相应更改,让apache进程以svnroot的身份运行  
//改完后是这个样子 
User svnroot 
Group svn 
//重启apache 
# /usr/local/apache2/bin/apachectl restart  
访问http://localhost/svn/test ,现在需要身份验证,且通过验证后应该可以看到信息 
补充:在xp的环境下,如果你运行着卡巴斯基,可能会导致无法访问svn,通常会报400 Bad Request错误 
解决办法是:进入卡巴斯基的设置-->网络设置--->端口设置,然后从端口列表中去掉80端口即可 
再次补充:eclipse有svn的插件,subclipse,安装路径为:http://subclipse.tigris.org/update 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值