diff --git a/courses/README.md b/courses/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7d057427e1bc9b61d65354d8afab7de0980737da --- /dev/null +++ b/courses/README.md @@ -0,0 +1,23 @@ +# Playground Courses +This Folder holds all the courses used by Playground Application + +# Courses +Using our example course as an example, the cource resources are organized in follow: +```shell +└── cources + └── create-course-101 # course name, a course can include a series of scenarios. + └── course-content.json # the course-content file describe the content of this course. + └── create-chapter # chapter name, a chapter can include a series of steps. + | └──index.json # scenario overall plan, indicating the arrangement of this scenario, this file is in JSON format. + | └──intro.md # introduction information, this will be displayed in the welcome page of this course, this file is in Markdown format. + | └──finish.md # finish information, this will be displayed in the end page of this coursethis file is in Markdown format. + | └──step1.md # detailed instruction for step1, this file is in Markdown format. + | └──step2.md # detailed instruction for step2, this file is in Markdown format. + └── create-course # chapter name, a chapter can include a series of steps. + └──index.json # scenario overall plan, indicating the arrangement of this scenario, this file is in JSON format. + └──intro.md # introduction information, this will be displayed in the welcome page of this course, this file is in Markdown format. + └──finish.md # finish information, this will be displayed in the end page of this coursethis file is in Markdown format. + └──step1.md # detailed instruction for step1, this file is in Markdown format. + └──step2.md # detailed instruction for step2, this file is in Markdown format. + └──step3.md # detailed instruction for step3, this file is in Markdown format. +``` diff --git a/courses/assets/openeuler-logo.png b/courses/assets/openeuler-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..06e8b4f2916131cc5de5f72075635269123ff1c0 Binary files /dev/null and b/courses/assets/openeuler-logo.png differ diff --git a/courses/course-list.json b/courses/course-list.json new file mode 100644 index 0000000000000000000000000000000000000000..fb3728ad795acb375557d5f4e48c265f6c760d85 --- /dev/null +++ b/courses/course-list.json @@ -0,0 +1,24 @@ +{ + "courses": [ + { + "id": "1", + "content_dir": "git-101", + "status": ["online", "test"] + }, + { + "id": "2", + "content_dir": "make-and-packaging", + "status": ["online", "test"] + }, + { + "id": "3", + "content_dir": "playground", + "status": ["online", "test"] + }, + { + "id": "99", + "content_dir": "create-courses-101", + "status": ["online", "test"] + } + ] +} \ No newline at end of file diff --git a/courses/create-courses-101/LICENSE b/courses/create-courses-101/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..a1c6a321fccaf6ff41fe0c92c7aa0400a6a9d7e9 --- /dev/null +++ b/courses/create-courses-101/LICENSE @@ -0,0 +1,128 @@ + 木兰宽松许可证, 第2版 + + 木兰宽松许可证, 第2版 + 2020年1月 http://license.coscl.org.cn/MulanPSL2 + + + 您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束: + + 0. 定义 + + “软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。 + + “贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。 + + “贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。 + + “法人实体”是指提交贡献的机构及其“关联实体”。 + + “关联实体”是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。 + + 1. 授予版权许可 + + 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。 + + 2. 授予专利许可 + + 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。 + + 3. 无商标许可 + + “本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。 + + 4. 分发限制 + + 您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。 + + 5. 免责声明与责任限制 + + “软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。 + + 6. 语言 + “本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。 + + 条款结束 + + 如何将木兰宽松许可证,第2版,应用到您的软件 + + 如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步: + + 1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字; + + 2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中; + + 3, 请将如下声明文本放入每个源文件的头部注释中。 + + Copyright (c) [Year] [name of copyright holder] + [Software Name] is licensed under Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. + + + Mulan Permissive Software License,Version 2 + + Mulan Permissive Software License,Version 2 (Mulan PSL v2) + January 2020 http://license.coscl.org.cn/MulanPSL2 + + Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions: + + 0. Definition + + Software means the program and related documents which are licensed under this License and comprise all Contribution(s). + + Contribution means the copyrightable work licensed by a particular Contributor under this License. + + Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License. + + Legal Entity means the entity making a Contribution and all its Affiliates. + + Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity. + + 1. Grant of Copyright License + + Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not. + + 2. Grant of Patent License + + Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken. + + 3. No Trademark License + + No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in Section 4. + + 4. Distribution Restriction + + You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software. + + 5. Disclaimer of Warranty and Limitation of Liability + + THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + 6. Language + + THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL. + + END OF THE TERMS AND CONDITIONS + + How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software + + To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps: + + i Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner; + + ii Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package; + + iii Attach the statement to the appropriate annotated syntax at the beginning of each source file. + + + Copyright (c) [Year] [name of copyright holder] + [Software Name] is licensed under Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. + \ No newline at end of file diff --git a/courses/create-courses-101/README.md b/courses/create-courses-101/README.md new file mode 100644 index 0000000000000000000000000000000000000000..714f43b2ef2efe1e4b9c55aaf85fa99b9011afc2 --- /dev/null +++ b/courses/create-courses-101/README.md @@ -0,0 +1,9 @@ +# openEuler MoocStudio 示例课程 +本课程将为用户展示openEuler MoocStudio课程的组成部分以及如何创建新的课程及章节。 + +# 课程目录 + - 第一章:如何在openEuler MoocStudio中添加新的章节 + - 第二章:如何在openEuler MoocStudio中添加新的课程 + +# Owners +Zhenyu Zheng diff --git a/courses/create-courses-101/assets/cover.png b/courses/create-courses-101/assets/cover.png new file mode 100644 index 0000000000000000000000000000000000000000..31c5bf1ca5a9f285f28a9348c08efabef34e47b8 Binary files /dev/null and b/courses/create-courses-101/assets/cover.png differ diff --git a/courses/create-courses-101/assets/logo.jpg b/courses/create-courses-101/assets/logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..160509019968c1ace5d5e34d19f664e5bc5f26b2 Binary files /dev/null and b/courses/create-courses-101/assets/logo.jpg differ diff --git a/courses/create-courses-101/assets/poster.png b/courses/create-courses-101/assets/poster.png new file mode 100644 index 0000000000000000000000000000000000000000..77091e4e0e9d7c7ab30f870d8ac82b5c7188ffb1 Binary files /dev/null and b/courses/create-courses-101/assets/poster.png differ diff --git a/courses/create-courses-101/course-content.json b/courses/create-courses-101/course-content.json new file mode 100644 index 0000000000000000000000000000000000000000..197a1667e9c518b5dfc4a5bab0842bc547952706 --- /dev/null +++ b/courses/create-courses-101/course-content.json @@ -0,0 +1,22 @@ +{ + "title": "创建openEuler MoocStudio章节与课程", + "description": "学习如何在openEuler MoocStudio中创建新的章节与课程", + "logo": "./assets/logo.jpg", + "poster": "./assets/poster.png", + "cover": "./assets/cover.png", + "container_live_time": "30", + "chapters": [ + { + "content_dir": "create-chapter", + "title": "创建openEuler MoocStudio-章节", + "description": "学习如何在openEuler MoocStudio中创建新的章节", + "estimated_time": "10 min" + }, + { + "content_dir": "create-course", + "title": "创建openEuler MoocStudio-课程", + "description": "学习如何在openEuler MoocStudio中创建新的课程", + "estimated_time": "10 min" + } + ] + } diff --git a/courses/create-courses-101/create-chapter/finish.md b/courses/create-courses-101/create-chapter/finish.md new file mode 100644 index 0000000000000000000000000000000000000000..da1c3faad2f610782cd6f78ea123b5653922a505 --- /dev/null +++ b/courses/create-courses-101/create-chapter/finish.md @@ -0,0 +1 @@ +恭喜!您已经掌握了在openEuler MoocStudio中创建章节内容的基本知识。 diff --git a/courses/create-courses-101/create-chapter/index.json b/courses/create-courses-101/create-chapter/index.json new file mode 100644 index 0000000000000000000000000000000000000000..9816707a9ba37e888de6ceb186c161ec270379e4 --- /dev/null +++ b/courses/create-courses-101/create-chapter/index.json @@ -0,0 +1,25 @@ +{ + "title": "创建你的第一个openEuler MoocStudio章节", + "description": "学习如何创建openEuler MoocStudio章节", + "details": { + "steps": [ + { + "title": "Step 1 - 章节结构", + "md_file": "step1.md" + }, + { + "title": "Step 2 - 语法", + "md_file": "step2.md" + } + ], + "introduction": { + "md_file": "intro.md" + }, + "finish": { + "md_file": "finish.md" + } + }, + "backend": { + "image_id": "openeuler-20.03-lts-sp1" + } +} diff --git a/courses/create-courses-101/create-chapter/intro.md b/courses/create-courses-101/create-chapter/intro.md new file mode 100644 index 0000000000000000000000000000000000000000..6c79349bd5ad25a8882a25b7044af307ff2b3283 --- /dev/null +++ b/courses/create-courses-101/create-chapter/intro.md @@ -0,0 +1 @@ +在本章节中,您将学会如何在openEuler MoocStudio中创建自己的课程章节。学习内容将包括用于描述章节的各个文件的组成部分以及编写章节所需要掌握的基本语法。 diff --git a/courses/create-courses-101/create-chapter/step1.md b/courses/create-courses-101/create-chapter/step1.md new file mode 100644 index 0000000000000000000000000000000000000000..b1605dfbb132fec08213d192163c2f664de64683 --- /dev/null +++ b/courses/create-courses-101/create-chapter/step1.md @@ -0,0 +1,23 @@ +一个openEuler MoocStudio章节中所包含的内容通过一系列的Markdown文件、Bash脚本以及JSON文件进行描述和组织。 + +## Task + +使用`git clone`将我们的示例目录进行克隆: + +`[[git clone https://github.com/opensourceways/playground-courses.git playground-course-examples]]{{RUN}}` + +在课程目录中,你将看到一系列openEuler Playground课程的相应示例,您现在正在阅读的示例就位于其中,使用下面的命令查看它是如何组织的: + +`[[ls -lha playground-course-examples/courses/create-courses-101/create-chapter]]{{RUN}}` + +目录名将与章节URL对应。 + +您现在正在阅读的步骤位于: + +`playground-course-examples/courses/create-courses-101/create-chapter/step1.md` + +本章节内所有的步骤(step)都通过一个名为index.json的JSON文件来进行组织: + +`playground-course-examples/courses/create-courses-101/create-chapter/index.json` + +index.json文件定义了章节的名称、简介、步骤顺序、UI风格以及运行环境。 diff --git a/courses/create-courses-101/create-chapter/step2.md b/courses/create-courses-101/create-chapter/step2.md new file mode 100644 index 0000000000000000000000000000000000000000..eca8c9d4838763e14bef171b585e2c4d949dd4ad --- /dev/null +++ b/courses/create-courses-101/create-chapter/step2.md @@ -0,0 +1,13 @@ +在每一个步骤中,我们通过Markdown扩展来提供更好的用户体验支持: + +例如, 命令 `[[ls -l]]{{RUN}}` 可以在点击命令后直接在Terminal中进行执行。 + +这是通过在Markdown代码片段前后后增加 `{{RUN}}` 字段进行实现的, 例如: +`[[ls -l]]{{RUN}}` + +例如, 命令 `[[ls -l]]{{PRINT}}` 可以在点击命令后直接在Terminal中打印但不执行。 + +这是通过在Markdown代码片段前后后增加 `{{PRINT}}` 字段进行实现的, 例如: +`[[ls -l]]{{PRINT}}` + +更多的扩展功能将在后续版本中进行支持。 diff --git a/courses/create-courses-101/create-course/finish.md b/courses/create-courses-101/create-course/finish.md new file mode 100644 index 0000000000000000000000000000000000000000..84005fdf094cf3b9ad01688ca671d560c9cffc39 --- /dev/null +++ b/courses/create-courses-101/create-course/finish.md @@ -0,0 +1 @@ +恭喜!您已经掌握了如何将一系列openEuler MoocStudio章节组织成为openEuler MoocStudio课程。 diff --git a/courses/create-courses-101/create-course/index.json b/courses/create-courses-101/create-course/index.json new file mode 100644 index 0000000000000000000000000000000000000000..242a251e4a2e6f0190e258dd944d44f0b27fc03d --- /dev/null +++ b/courses/create-courses-101/create-course/index.json @@ -0,0 +1,29 @@ +{ + "title": "创建openEuler MoocStudio课程", + "description": "学习如何将一系列openEuler MoocStudio章节组织成为openEuler MoocStudio课程", + "details": { + "steps": [ + { + "title": "Step 1 - 制定课程目录(1/2)", + "md_file": "step1.md" + }, + { + "title": "Step 2 - 制定课程目录(2/2)", + "md_file": "step2.md" + }, + { + "title": "Step 3 - 从其他课程中引用章节", + "md_file": "step3.md" + } + ], + "introduction": { + "md_file": "intro.md" + }, + "finish": { + "md_file": "finish.md" + } + }, + "backend": { + "image_id": "openeuler-20.03-lts-sp1" + } +} diff --git a/courses/create-courses-101/create-course/intro.md b/courses/create-courses-101/create-course/intro.md new file mode 100644 index 0000000000000000000000000000000000000000..671c8592e8ecd916c948de8999e2a3983eec30ff --- /dev/null +++ b/courses/create-courses-101/create-course/intro.md @@ -0,0 +1,3 @@ +在本章节中,您将学习如何将一系列openEuler MoocStudio章节组织成为openEuler MoocStudio课程。 + +通过将内容相关联的章节组织成为课程并按照顺序进行学习可以为用户提供更系统化的学习体验 diff --git a/courses/create-courses-101/create-course/step1.md b/courses/create-courses-101/create-course/step1.md new file mode 100644 index 0000000000000000000000000000000000000000..d1fe9afda740564b3ab51cd25ad83b6ea782e242 --- /dev/null +++ b/courses/create-courses-101/create-course/step1.md @@ -0,0 +1,26 @@ +openEuler MoocStudio课程通过创建course-content文件来进行组织,采用JSON格式,course-content文件用来定义哪些章节需要被包含在本课程内以及各章节的顺序。 + + +## 克隆示例 + +使用下面的命令克隆示例代码: +`[[git clone https://github.com/opensourceways/playground-courses.git playground-course-examples]]{{RUN}}` + +在`courses`目录中,创建了我们的示例课程`create-courses-101`,这个课程所对应的course-content定义在: +`playground-course-examples/courses/create-courses-101/course-content.json` . + +在`course-content`文件中,我们使用JSON格式对课程进行了定义, 例如: + +``` +{ + "title": "创建openEuler Playground章节与课程", + "description": "学习如何在openEuler Playground中创建新的章节与课程", + "logo": "openEuler", + "chapters": [ + ... + ] +} +``` + +定义中的**title**, **description** 和 **logo** 将会在课程欢迎页面进行展示。 +定义中的 **chapters** 用于定义课程中的各个章节,具体定义方式在下一节中进行展示。 diff --git a/courses/create-courses-101/create-course/step2.md b/courses/create-courses-101/create-course/step2.md new file mode 100644 index 0000000000000000000000000000000000000000..21dbeb1866e132c424561c7b72091a2f123f0b18 --- /dev/null +++ b/courses/create-courses-101/create-course/step2.md @@ -0,0 +1,23 @@ +openEuler MoocStudio课程通过创建course-content文件来进行组织,采用JSON格式,course-content文件用来定义哪些章节需要被包含在本课程内以及各章节的顺序。 + + +## 定义章节 + + +``` +{ + ... + chapters:[ + { + "chapter_id": "create-chapter", + "title": "创建openEuler MoocStudio章节", + "description": "学习如何在openEuler MoocStudio中创建新的章节" + }, + ... + ] +} +``` + +course-content中的**chapters**字段用列表定义本课程中所包和的各个章节,章节在课程页面中出现的顺序与列表属顺序保持一致。 +定义中的 **chapter_id** 与课程目录中的章节子目录相对应,如 `playground-course-examples/courses/create-courses-101/create-chapter`。 +定义中的**title** 和 **description** 将会在课程欢迎页面进行展示。 diff --git a/courses/create-courses-101/create-course/step3.md b/courses/create-courses-101/create-course/step3.md new file mode 100644 index 0000000000000000000000000000000000000000..66a5ac3bfea356a70a7476a28184341f589b1878 --- /dev/null +++ b/courses/create-courses-101/create-course/step3.md @@ -0,0 +1,20 @@ +openEuler MoocStudio课程还可以引用其他现有openEuler MoocStudio中的章节,以促进基础知识内容的重复利用。 + +可以通过使用下面的定义方式进行章节重用: + +``` +{ + ... + chapters:[ + { + "course_id": "reuseable-course", + "chapter_id": "test_chapter", + "title": "测试章节", + "description": "测试章节" + }, + ... + ] +} +``` + +这样就可以从`reusable-course`中引用`test-chapter`章节,如果该章节没有被包含在任何章节中,请将`course_id`留空。 diff --git a/courses/git-101/assets/conflict.bmp b/courses/git-101/assets/conflict.bmp new file mode 100644 index 0000000000000000000000000000000000000000..945bf278939e9b08b327e7f20ae3d1367ff35b92 Binary files /dev/null and b/courses/git-101/assets/conflict.bmp differ diff --git a/courses/git-101/assets/cover.png b/courses/git-101/assets/cover.png new file mode 100644 index 0000000000000000000000000000000000000000..b98b015696c753b6323834640b1753a1d8b2ddcb Binary files /dev/null and b/courses/git-101/assets/cover.png differ diff --git a/courses/git-101/assets/logo.png b/courses/git-101/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..51f4ae5404fc79be09e69171bfc9d34d48810297 Binary files /dev/null and b/courses/git-101/assets/logo.png differ diff --git a/courses/git-101/assets/poster.png b/courses/git-101/assets/poster.png new file mode 100644 index 0000000000000000000000000000000000000000..77091e4e0e9d7c7ab30f870d8ac82b5c7188ffb1 Binary files /dev/null and b/courses/git-101/assets/poster.png differ diff --git a/courses/git-101/assets/rebase.bmp b/courses/git-101/assets/rebase.bmp new file mode 100644 index 0000000000000000000000000000000000000000..e856801106736752546917d1b82544ebf29491a4 Binary files /dev/null and b/courses/git-101/assets/rebase.bmp differ diff --git a/courses/git-101/committing-changes/finish.md b/courses/git-101/committing-changes/finish.md new file mode 100644 index 0000000000000000000000000000000000000000..83181fd276ccf43143340f4c013f756615df5e79 --- /dev/null +++ b/courses/git-101/committing-changes/finish.md @@ -0,0 +1 @@ +恭喜完成课程!继续学习下一章节掌握更多有关Git的知识和使用。 \ No newline at end of file diff --git a/courses/git-101/committing-changes/index.json b/courses/git-101/committing-changes/index.json new file mode 100644 index 0000000000000000000000000000000000000000..d56bb4b4e1e9e0413e294b01756a867c829d88a9 --- /dev/null +++ b/courses/git-101/committing-changes/index.json @@ -0,0 +1,37 @@ +{ + "title": "提交修改", + "description": "学习如何初始化Git仓库并提交修改", + "details": { + "steps": [ + { + "title": "Step 1 - 配置你的Git", + "md_file": "step1.md" + }, + { + "title": "Step 2 - Git Init", + "md_file": "step2.md" + }, + { + "title": "Step 3 - Git Add", + "md_file": "step3.md" + }, + { + "title": "Step 4 - Git Commit", + "md_file": "step4.md" + }, + { + "title": "Step 5 - Git Ingore", + "md_file": "step5.md" + } + ], + "introduction": { + "md_file": "intro.md" + }, + "finish": { + "md_file": "finish.md" + } + }, + "backend": { + "image_id": "openEuler-20.03-lts-sp1" + } +} \ No newline at end of file diff --git a/courses/git-101/committing-changes/intro.md b/courses/git-101/committing-changes/intro.md new file mode 100644 index 0000000000000000000000000000000000000000..de4649a86b4ccf35cb46e531ca981ca4f2e72b0e --- /dev/null +++ b/courses/git-101/committing-changes/intro.md @@ -0,0 +1 @@ +Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目,是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。通过本系列课程的学习,你将掌握如何使用Git来管理你的代码仓库。 \ No newline at end of file diff --git a/courses/git-101/committing-changes/step1.md b/courses/git-101/committing-changes/step1.md new file mode 100644 index 0000000000000000000000000000000000000000..4987c1591b914a13c0964a062f668ed1438ef539 --- /dev/null +++ b/courses/git-101/committing-changes/step1.md @@ -0,0 +1,15 @@ +安装完 Git 之后,要做的第一件事就是设置你的用户名和邮件地址。 这一点很重要,因为每一个 Git 提交都会使用这些信息,它们会写入到你的每一次提交中。 + +## 任务 + +通过下面的命令来配置Git, `" "`中的内容根据实际情况进行替换。 + +`[[git config --global user.name ]]{{PRINT}}"your name"` + +`[[git config --global user.email ]]{{PRINT}}"your email"` + +## Tips + +如果使用了`--global`选项,那么该命令只需要运行一次,因为之后无论你在该系统上做任何事情, Git 都会使用那些信息。 当你想针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运行没有`--global`选项的命令来配置。 + +使用`git config -l`可以查看当前环境中的Git配置情况。 \ No newline at end of file diff --git a/courses/git-101/committing-changes/step2.md b/courses/git-101/committing-changes/step2.md new file mode 100644 index 0000000000000000000000000000000000000000..e6ac40bb9369e70133929967368f30facba26b09 --- /dev/null +++ b/courses/git-101/committing-changes/step2.md @@ -0,0 +1,7 @@ +如果你有一个尚未进行版本控制的项目目录,想要用 Git 来控制它,那么首先需要进入该项目目录中。并运行`git init`,该命令将创建一个名为`.git`的子目录,这个子目录含有你初始化的 Git 仓库中所有的必须文件,这些文件是 Git 仓库的骨干。 但是,在这个时候,我们仅仅是做了一个初始化的操作,你的项目里的文件还没有被跟踪。 + +## 任务 + +执行 `[[cd /home/coder/git-101/workspace/project_1/]]{{RUN}}` 进入本章工作目录 + +执行 `[[git init]]{{RUN}}` 在当前目录下初始化Git仓库 diff --git a/courses/git-101/committing-changes/step3.md b/courses/git-101/committing-changes/step3.md new file mode 100644 index 0000000000000000000000000000000000000000..d931d97bce3c2bba1c2b73aa8d54c62844b4205e --- /dev/null +++ b/courses/git-101/committing-changes/step3.md @@ -0,0 +1,20 @@ +如果在一个已存在文件的文件夹(而非空文件夹)中进行版本控制,或在初始化完成的Git目录中添加了新的文件后,你应该开始追踪这些文件并进行初始提交。可以通过`git add`命令来指定所需的文件来进行追踪。 + +Git包含三个区域:工作目录(Working Directory)、 暂存区域(Staging Area)以及仓库本身。开发者首先在工作目录中对文件进行修改, 修改完成后将修改提交到暂存区域,并最终提交到仓库中。 + +Git的核心思想之一就是将开发活动分散的尽量小和频繁的提交中(small and frequent)。 暂存区域可以很好的帮助开发者每次只从工作目录中选取一部分修改提交到仓库中。 + +## 任务 + +使用 `[[git status]]{{RUN}}` 查看当前目录状态,可以看到有一个未被跟踪的文件`untracked` + +使用 `[[git add untracked]]{{RUN}}` 添加该文件(修改)到暂存区域(Staging Area)。 + +再次使用 `[[git status]]{{RUN}}` 查看当前目录状态,可以看到所有文件已被跟踪。 + + +## Tips + +如果你对某些文件进行了重命名或删除,你可能需要再次将其添加 +到暂存区域(Staging Area),你也可以使用`git mv`和`git rm` +来进行相应的操作,这样Git会自动完成其他工作。 \ No newline at end of file diff --git a/courses/git-101/committing-changes/step4.md b/courses/git-101/committing-changes/step4.md new file mode 100644 index 0000000000000000000000000000000000000000..ef51c5e9e93c5f1c76cd13b69beef084f07814e3 --- /dev/null +++ b/courses/git-101/committing-changes/step4.md @@ -0,0 +1,13 @@ +现在的暂存区已经准备就绪,可以进行你的第一次提交了。Git提交通常需要包含提交消息(Commit Message)以便帮助你和其他合作者理解这次提交的内容。可以使用`git commit -m "commit message"` 来创建提交并将提交信息与命令放在同一行。 + +## 任务 + +运行下面的命令,创建你的第一个提交(提交untracked到仓库),`" "`中的内容请自行替换。 + +`[[git commit -m ]]{{PRINT}}"your commit message"` + +运行 `[[git log]]{{RUN}}` 查看最新的提交记录。 + +## Tips + +在 `git commit` 后添加 `-s` 选项可以自动在commit message中添加 `signed-off-by: xxx` 信息。 diff --git a/courses/git-101/committing-changes/step5.md b/courses/git-101/committing-changes/step5.md new file mode 100644 index 0000000000000000000000000000000000000000..64eaaefb5bbe8a75875bc158fce20f5439fe5762 --- /dev/null +++ b/courses/git-101/committing-changes/step5.md @@ -0,0 +1,25 @@ +一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。 通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。 在这种情况下,我们可以创建一个名为 `.gitignore` 的文件,列出要忽略的文件的模式。 + +## 任务 + +运行下面的命令为你的Git目录创建`.gitignore`文件: + +`[[echo '*.tmp' > .gitignore]]{{RUN}}` + +`[[git add .gitignore]]{{RUN}}` + +`[[git commit -m 'add .gitigonre file']]{{RUN}}` + +## Tips + +文件 `.gitignore` 的格式规范如下: + +- 所有空行或者以 `#` 开头的行都会被 Git 忽略。 + +- 可以使用标准的 `glob` 模式匹配,它会递归地应用在整个工作区中。 + +- 匹配模式可以以 `/` 开头防止递归。 + +- 匹配模式可以以 `/` 结尾指定目录。 + +- 要忽略指定模式以外的文件或目录,可以在模式前加上叹号 `!` 取反。 \ No newline at end of file diff --git a/courses/git-101/course-content.json b/courses/git-101/course-content.json new file mode 100644 index 0000000000000000000000000000000000000000..2684e2caf7df5a3fbc5f86f01a91f491c64c5dd9 --- /dev/null +++ b/courses/git-101/course-content.json @@ -0,0 +1,35 @@ +{ + "title": "Git分布式版本控制工具", + "description": "学习Git分布式版本控制工具的基础知识与基本使用", + "logo": "./assets/logo.png", + "poster": "./assets/poster.png", + "cover": "./assets/cover.png", + "container_live_time": "60", + "chapters": [ + { + "content_dir": "committing-changes", + "title": "提交修改", + "description": "学习如何初始化Git仓库并提交修改", + "estimated_time": "10 min" + }, + { + "content_dir": "working-remotely-1", + "title": "远端操作-1", + "description": "学习如何推送修改到远端仓库", + "estimated_time": "10 min" + }, + { + "content_dir": "working-remotely-2", + "title": "远端操作-2", + "description": "学习如何推送修改到远端仓库", + "estimated_time": "10 min" + }, + { + "content_dir": "solving-conflict", + "title": "解决冲突", + "description": "学习如何解决冲突", + "estimated_time": "10 min" + } + ] + } + diff --git a/courses/git-101/solving-conflict/finish.md b/courses/git-101/solving-conflict/finish.md new file mode 100644 index 0000000000000000000000000000000000000000..83181fd276ccf43143340f4c013f756615df5e79 --- /dev/null +++ b/courses/git-101/solving-conflict/finish.md @@ -0,0 +1 @@ +恭喜完成课程!继续学习下一章节掌握更多有关Git的知识和使用。 \ No newline at end of file diff --git a/courses/git-101/solving-conflict/index.json b/courses/git-101/solving-conflict/index.json new file mode 100644 index 0000000000000000000000000000000000000000..011876f9f363cf76e40be06c12238d2fe482d22b --- /dev/null +++ b/courses/git-101/solving-conflict/index.json @@ -0,0 +1,38 @@ +{ + "title": "解决冲突", + "description": "学习如何解决冲突", + "details": { + "steps": [ + { + "title": "Step 1 - Git Branch & Checkout", + "md_file": "step1.md" + }, + { + "title": "Step 2 - Git Commit", + "md_file": "step2.md" + }, + { + "title": "Step 3 - Set-upstream-to", + "md_file": "step3.md" + }, + { + "title": "Step 4 - Solving Conflict", + "md_file": "step4.md" + }, + { + "title": "Step 5 - Git Rebase", + "md_file": "step5.md" + } + + ], + "introduction": { + "md_file": "intro.md" + }, + "finish": { + "md_file": "finish.md" + } + }, + "backend": { + "image_id": "openEuler-20.03-lts-sp1" + } +} \ No newline at end of file diff --git a/courses/git-101/solving-conflict/intro.md b/courses/git-101/solving-conflict/intro.md new file mode 100644 index 0000000000000000000000000000000000000000..134e85a4ea3cf0e3febc39d40249a0112079b788 --- /dev/null +++ b/courses/git-101/solving-conflict/intro.md @@ -0,0 +1 @@ +Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目,是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。通过本系列课程的学习,你将掌握如何使用Git来管理你的代码仓库。 diff --git a/courses/git-101/solving-conflict/step1.md b/courses/git-101/solving-conflict/step1.md new file mode 100644 index 0000000000000000000000000000000000000000..ebe94ac4457785d6059135aaa073dd1b28258275 --- /dev/null +++ b/courses/git-101/solving-conflict/step1.md @@ -0,0 +1,16 @@ +NOTE: 本章节工作依赖前一章节所作操作,请确保《第三章:远端操作-2》的操作内容已完成(若容器环境已被清理,需要重新完成)。 + + +在进行接下来的操作前,我们首先创建需要创建一个新的分支并切换到这个分支。 + +可以使用 `git branch "branch name"` 来创建新的分支,使用 `git checkout "branch name"` 来在不同的分支之间进行切换。同时,`git checkout -b "branch name"` 可以直接创建一个新的分支并切换到该分支。 + +## 任务 + +执行 `[[cd /home/coder/git-101/workspace/project_2]]{{RUN}}` 进入工作目录。 + +执行 `[[git branch "new_branch"]]{{RUN}}` 创建一个新的分支 `new_branch`。 + +执行 `[[git branch]]{{RUN}}` 查看所有分支。 + +执行 `[[git checkout new_branch]]{{RUN}}` 切换到新创建的分支。 \ No newline at end of file diff --git a/courses/git-101/solving-conflict/step2.md b/courses/git-101/solving-conflict/step2.md new file mode 100644 index 0000000000000000000000000000000000000000..d7d2051789b8dd7628a48a49470f9e80ec14bb20 --- /dev/null +++ b/courses/git-101/solving-conflict/step2.md @@ -0,0 +1,14 @@ +在进行接下来的操作前,我们首先创建需要创建一个新的文件`conflict`并写入一行内容,在远端仓库 +同样的分支中同样会有这样一个文件并且内容并不相同(当我们在开发时,其他开发者可能修改了这个文 +件)。当我们从远端拉取这个分支的代码时,就会产生冲突(Conflict),这种情况在多人合作时非常常见。 +当这种情况发生时,我们就需要学习如何解决冲突。 + +## 任务 + +执行下面的命令,创建一个文件并写入内容: + +`[[echo 'This is a new line' > conflict_file]]{{RUN}}` + +`[[git add .]]{{RUN}}` + +`[[git commit -m]]{{PRINT}} "commit message"` diff --git a/courses/git-101/solving-conflict/step3.md b/courses/git-101/solving-conflict/step3.md new file mode 100644 index 0000000000000000000000000000000000000000..d34d759732ce740445999a573427e8c51d8bf074 --- /dev/null +++ b/courses/git-101/solving-conflict/step3.md @@ -0,0 +1,7 @@ +在运行拉取前,需要将我们本地的新分支与远端的分支进行关联。 + +## 任务 + +执行 `[[git branch --set-upstream-to=origin/new_branch new_branch]]{{RUN}}` 将我们在上一步中创建的新分支 `new_branch` 进行关联。 + +执行 `[[git pull]]{{RUN}}` 从远端拉取该分支的最新修改。 diff --git a/courses/git-101/solving-conflict/step4.md b/courses/git-101/solving-conflict/step4.md new file mode 100644 index 0000000000000000000000000000000000000000..a8724d185f61a4dfd286b6047aa94c5a0ebc814e --- /dev/null +++ b/courses/git-101/solving-conflict/step4.md @@ -0,0 +1,23 @@ +与我们料想的一样,由于远端代码的同一文件中存在着不同的内容(其他开发者进行了修改并同步到了远端分支), +我们在从远端拉取(pull)代码时,与我们在本地的修改产生了冲突(conflict)。接下来我们将学习如何解决冲突。 + +## 任务 + +执行 `[[git status]]{{RUN}}` 查看当前目录的状态,输出中将会包含存在冲突的文件。 + +执行 `[[vi conflict_file]]{{RUN}}` 打开存在冲突的文件,并手动解决冲突,文件内容应如下图所示: + +![avatar](../assets/conflict.bmp) + +对于存在冲突的位置,本地仓库的修改将位于上方,处于特殊字符串 +`<<<<<<< HEAD` 和 `=======` 之间,远端修改则位于特殊字符串 `=======` 和 +`>>>>>>> remotes/origin/master` 之间。 + +通过vim编辑器完成冲突解决后,需要重新使用`git add`将存在冲突的文件添加到 +暂存区域进行跟踪。执行下面的命令完成操作: + +`[[git add .]]{{RUN}}` + +`[[git commit]]{{RUN}}` + +`[[git merge]]{{RUNc}}` diff --git a/courses/git-101/solving-conflict/step5.md b/courses/git-101/solving-conflict/step5.md new file mode 100644 index 0000000000000000000000000000000000000000..10e8571587629d37a65bcd1a952b79aa83db37b7 --- /dev/null +++ b/courses/git-101/solving-conflict/step5.md @@ -0,0 +1,37 @@ +有时为了保证仓库中提交记录的间接,项目的维护者会要求将相关的多次提交合并到一次提交中, +使用`git rebase`命令可以很好的完成这个工作。 + +## 任务 + +依次执行下面的命令完成准备工作: + +1. 切换回`master`分支: + `[[git checkout master]]{{RUN}}` + +2. 创建并切换到一个新的分支,准备进行接下来的操作: + `[[git checkout -b new_branch_2]]{{RUN}}` + +3. 创建新文件 `file1` 并提交: + ``` + [[echo 'This is new_file1' > new_file1]]{{RUN}} + [[git add .]]{{RUN}} + [[git commit -m 'Added new_file1']]{{RUN}} + ``` + +4. 创建新文件 `file2` 并提交: + ``` + [[echo 'This is new_file2' > new_file2]]{{RUN}} + [[git add .]]{{RUN}} + [[git commit -m 'Added new_file2']]{{RUN}} + ``` + +5. 使用 `[[git log]]{{RUN}}` 查看提交历史,可以看到产生了两次提交; +6. 对于一些项目,维护者要求相关的commit需要合并到一个commit后再提交到上游仓库,使用下面的命令将最近的两次commit进行合并: + `[[git rebase -i HEAD~2]]{{RUN}}` +在弹出的编辑器中进行编辑修改为`pick xxx` `s` + +## Tips + +`rebase` 时可以通过命令选择多种操作方式,可以根据实际需求进行选择,如图: + +![avatar](../assets/rebase.bmp) \ No newline at end of file diff --git a/courses/git-101/working-remotely-1/finish.md b/courses/git-101/working-remotely-1/finish.md new file mode 100644 index 0000000000000000000000000000000000000000..83181fd276ccf43143340f4c013f756615df5e79 --- /dev/null +++ b/courses/git-101/working-remotely-1/finish.md @@ -0,0 +1 @@ +恭喜完成课程!继续学习下一章节掌握更多有关Git的知识和使用。 \ No newline at end of file diff --git a/courses/git-101/working-remotely-1/index.json b/courses/git-101/working-remotely-1/index.json new file mode 100644 index 0000000000000000000000000000000000000000..3eed69c6cbf2cd02e4fa6b8a198075f1b6e907e1 --- /dev/null +++ b/courses/git-101/working-remotely-1/index.json @@ -0,0 +1,33 @@ +{ + "title": "远端操作-1", + "description": "学习如何进行远端操作", + "details": { + "steps": [ + { + "title": "Step 1 - Git Diff", + "md_file": "step1.md" + }, + { + "title": "Step 2 - Git Remote", + "md_file": "step2.md" + }, + { + "title": "Step 3 - Git Commit", + "md_file": "step3.md" + }, + { + "title": "Step 4 - Git Push", + "md_file": "step4.md" + } + ], + "introduction": { + "md_file": "intro.md" + }, + "finish": { + "md_file": "finish.md" + } + }, + "backend": { + "image_id": "openEuler-20.03-lts-sp1" + } +} \ No newline at end of file diff --git a/courses/git-101/working-remotely-1/intro.md b/courses/git-101/working-remotely-1/intro.md new file mode 100644 index 0000000000000000000000000000000000000000..de4649a86b4ccf35cb46e531ca981ca4f2e72b0e --- /dev/null +++ b/courses/git-101/working-remotely-1/intro.md @@ -0,0 +1 @@ +Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目,是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。通过本系列课程的学习,你将掌握如何使用Git来管理你的代码仓库。 \ No newline at end of file diff --git a/courses/git-101/working-remotely-1/step1.md b/courses/git-101/working-remotely-1/step1.md new file mode 100644 index 0000000000000000000000000000000000000000..15aee0912412df6e5cedbb7c18f06556e8d3a84e --- /dev/null +++ b/courses/git-101/working-remotely-1/step1.md @@ -0,0 +1,17 @@ +可以用 `git diff` 命令查看已暂存和未暂存的修改,以便更详细的了解当前Git目录的差异情况,`git diff` 命令用来查看尚未暂存的文件更新了哪些部分,而`git diff --staged`查看已暂存的将要添加到下次提交里的内容,这条命令将比对已暂存文件与最后一次提交的文件差异。 + +## 任务 + +运行 `[[echo 'This is a new line' > untracked]]{{RUN}}` 对该文件进行修改。 + +运行 `[[echo 'This is a new file' > new_file]]{{RUN}}` 创建一个新的文件并写入内容。 + +运行 `[[git add new_file]]{{RUN}}` 将新文件添加到暂存区域。 + +运行 `[[git diff]]{{RUN}}` 及 `[[git diff --staged]]{{RUN}}` 并观察结果 + + + +## Tips + +`git diff` 本身只显示尚未暂存的改动,而不是自上次提交以来所做的所有改动。 所以有时候你一下子暂存了所有更新过的文件,运行 `git diff` 后却什么也没有,就是这个原因。 \ No newline at end of file diff --git a/courses/git-101/working-remotely-1/step2.md b/courses/git-101/working-remotely-1/step2.md new file mode 100644 index 0000000000000000000000000000000000000000..d76617adda9a07d7e3326971430586717c428aea --- /dev/null +++ b/courses/git-101/working-remotely-1/step2.md @@ -0,0 +1,22 @@ +通过远端仓库(Remote Repository)可以将你的修改对外进行分析 +或是从远端获取其他开发者所作的修改。通常远端仓库部署在可远程 +访问的服务器或是服务中,例如Github和Gitee。可以通过 +`git remote`命令来将某个远端仓库和你的仓库进行关联,远端仓库通常使用 +SSH链接或HTTPS URL地址,例如: +https://gitee.com/openeuler/community.git 和 +git@gitee.com:openeuler/community.git + +可以通过为远端仓库指定名称用于在其他命令中引用这些仓库。 + +远端仓库也可以配置为本机的某个目录,本例就使用这种方式来进行演示。 + +## 任务 + +当前环境中有一个位于 `/home/coder/git-101/remote-project/project_1` 的远端仓库,使用 +`[[git remote add origin /home/coder/git-101/remote-project/project_1]]{{RUN}}` +命令添加这个远端仓库并命名为`origin`。 + +## Tips + +如果你使用`git clone`命令(将在未来的章节中单独介绍),你所 +克隆的仓库将会被自动添加到`origin`。 \ No newline at end of file diff --git a/courses/git-101/working-remotely-1/step3.md b/courses/git-101/working-remotely-1/step3.md new file mode 100644 index 0000000000000000000000000000000000000000..298ba8fe07fe9b89ea8bd1015eee09b4cc1f6bd6 --- /dev/null +++ b/courses/git-101/working-remotely-1/step3.md @@ -0,0 +1,5 @@ +在准备推送本地修改到远端仓库前,我们需要将最新的修改提交到本地的Git仓库中。 + +## 任务 + +使用 `[[git commit -a -m ]]{{PRINT}}"your commit message"` 将前两步所作的修改提交到Git本地目录。 \ No newline at end of file diff --git a/courses/git-101/working-remotely-1/step4.md b/courses/git-101/working-remotely-1/step4.md new file mode 100644 index 0000000000000000000000000000000000000000..12e27f0ff18a06db7ce63e6ec85b17d7c45e30d7 --- /dev/null +++ b/courses/git-101/working-remotely-1/step4.md @@ -0,0 +1,13 @@ +当你准备好将你的修改推送到远端仓库时,你需要使用`git push` +命令。一个典型的Git工作流通常在完成若干次小的修改和 +提交(Commit)后,例如完成某一个具体的任务或重要节点后, +使用`git push`将代码推送到远端以便他人可以使用。 + +`git push`命令后可附加两个参数,第一个参数是远端仓库的名称, +如在上一步中添加的`origin`。第二个参数是期望提交到的分支(Branch) +的名称。默认情况下,所有Git仓库都有(main/master)分支作为默认 +的工作分支。 + +## 任务 + +使用 `[[git push -u origin master]]{{RUN}}` 命令将提交推送到远端仓库。 diff --git a/courses/git-101/working-remotely-2/finish.md b/courses/git-101/working-remotely-2/finish.md new file mode 100644 index 0000000000000000000000000000000000000000..83181fd276ccf43143340f4c013f756615df5e79 --- /dev/null +++ b/courses/git-101/working-remotely-2/finish.md @@ -0,0 +1 @@ +恭喜完成课程!继续学习下一章节掌握更多有关Git的知识和使用。 \ No newline at end of file diff --git a/courses/git-101/working-remotely-2/index.json b/courses/git-101/working-remotely-2/index.json new file mode 100644 index 0000000000000000000000000000000000000000..e86521021bb8bfe75fe065ad25b35e08dd585d9b --- /dev/null +++ b/courses/git-101/working-remotely-2/index.json @@ -0,0 +1,37 @@ +{ + "title": "远端操作-2", + "description": "学习如何进行远端操作", + "details": { + "steps": [ + { + "title": "Step 1 - Git Clone", + "md_file": "step1.md" + }, + { + "title": "Step 2 - Git Log", + "md_file": "step2.md" + }, + { + "title": "Step 3 - Git Branch & Checkout", + "md_file": "step3.md" + }, + { + "title": "Step 4 - Git Reset", + "md_file": "step4.md" + }, + { + "title": "Step 5 - Git Revert", + "md_file": "step5.md" + } + ], + "introduction": { + "md_file": "intro.md" + }, + "finish": { + "md_file": "finish.md" + } + }, + "backend": { + "image_id": "openEuler-20.03-lts-sp1" + } +} \ No newline at end of file diff --git a/courses/git-101/working-remotely-2/intro.md b/courses/git-101/working-remotely-2/intro.md new file mode 100644 index 0000000000000000000000000000000000000000..de4649a86b4ccf35cb46e531ca981ca4f2e72b0e --- /dev/null +++ b/courses/git-101/working-remotely-2/intro.md @@ -0,0 +1 @@ +Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目,是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。通过本系列课程的学习,你将掌握如何使用Git来管理你的代码仓库。 \ No newline at end of file diff --git a/courses/git-101/working-remotely-2/step1.md b/courses/git-101/working-remotely-2/step1.md new file mode 100644 index 0000000000000000000000000000000000000000..c4a7535d2e105eef4bffd358e3f8c48c6a2444de --- /dev/null +++ b/courses/git-101/working-remotely-2/step1.md @@ -0,0 +1,16 @@ +如果你想获得一份已经存在了的 Git 仓库的拷贝,比如说,你想为某个开源项目贡献自己的一份力,这时就要用到 `git clone` 命令。 如果你对其它的 VCS 系统(比如说 Subversion)很熟悉,请留心一下你所使用的命令是 `clone` 而不是 `checkout`。 这是 Git 区别于其它版本控制系统的一个重要特性,Git 克隆的是该 Git 仓库服务器上的几乎所有数据,而不是仅仅复制完成你的工作所需要文件。 当你执行 `git clone` 命令的时候,默认配置下远程 Git 仓库中的每一个文件的每一个版本都将被拉取下来。 + +## 任务 + +执行 `[[cd /home/coder/git-101/workspace/]]{{RUN}}` 切换到新的目录 + +执行 `[[git clone /home/coder/git-101/remote-project/project_2]]{{RUN}}` 克隆远端仓库到目录下。 + +执行 `[[cd project_2]]{{RUN}}` 进入到刚刚克隆的项目中。 + +## Tips + +如果你想在克隆远程仓库的时候,自定义本地仓库的名字,你可以通过额外的参数指定新的目录名: + +`git clone https://github.com/libgit2/libgit2 mylibgit` +这会执行与上一条命令相同的操作,但目标目录名变为了 `mylibgit`。 \ No newline at end of file diff --git a/courses/git-101/working-remotely-2/step2.md b/courses/git-101/working-remotely-2/step2.md new file mode 100644 index 0000000000000000000000000000000000000000..302c6bd556073ada9c64ea571b9b1ba2c1482947 --- /dev/null +++ b/courses/git-101/working-remotely-2/step2.md @@ -0,0 +1,9 @@ +克隆了某个项目之后,你也许想回顾下提交历史。 完成这个任务最简单而又有效的工具是 `git log` 命令。不传入任何参数的默认情况下,`git log` 会按时间先后顺序列出所有的提交,最近的更新排在最上面。 这个命令会列出每个提交的 SHA-1 校验和、作者的名字和电子邮件地址、提交时间以及提交说明。 + +若想查看某次提交中更详细的内容可以使用 `git show` 命令来进行查看。 + +## 任务 + +使用 `[[git log]]{{RUN}}` 命令查看我们克隆下来的项目的提交历史。 + +使用 `[[git show ]]{{PRINT}}"commit id"` 命令来查看某次提交的具体修改内容(`" "`内的内容请根据实际情况进行修改)。 \ No newline at end of file diff --git a/courses/git-101/working-remotely-2/step3.md b/courses/git-101/working-remotely-2/step3.md new file mode 100644 index 0000000000000000000000000000000000000000..d6dc4f753aea8a63fed9abcfef836bb05523e855 --- /dev/null +++ b/courses/git-101/working-remotely-2/step3.md @@ -0,0 +1,7 @@ +几乎所有的版本控制系统都以某种形式支持分支。使用分支意味着你可以把你的工作从开发主线上分离开来,以免影响开发主线。在开发过程中,开发者们通常为每次开发活动创建新的分支,在完成所有开发工作(开发、测试、检视等)后再将开发分支与主干分支合并。Git 处理分支的方式可谓是难以置信的轻量,创建新分支这一操作几乎能在瞬间完成,并且在不同分支之间的切换操作也是一样便捷。 + +可以使用 `git branch "branch name"` 来创建新的分支,使用 `git checkout "branch name"` 来在不同的分支之间进行切换。同时,`git checkout -b "branch name"` 可以直接创建一个新的分支并切换到该分支。 + +## 任务 + +通过 `[[git checkout -b ]]{{PRINT}}"branch name"` 来创建一个分支并切换到该分支进行开发(`" "`中内容根据实际情况替换)。 \ No newline at end of file diff --git a/courses/git-101/working-remotely-2/step4.md b/courses/git-101/working-remotely-2/step4.md new file mode 100644 index 0000000000000000000000000000000000000000..9e4b6e4868d8f03657f4d7f13d85a582df652739 --- /dev/null +++ b/courses/git-101/working-remotely-2/step4.md @@ -0,0 +1,38 @@ +在任何一个阶段,你都有可能想要撤消某些操作。注意,有些撤消操作是不可逆的。 这是在使用 Git 的过程中,会因为操作失误而导致之前的工作丢失的少有的几个地方之一。 + +如果已经修改了两个文件并且想要将它们作为两次独立的修改提交, 但是却意外地输入 `git add *` 暂存了它们两个,那么使用 `git reset` 命令可以将文件从暂存区中移除。 + +如果你需要连工作目录中的修改一并回退,则可以使用 `git reset --hard` 命令,这个命令将会将你的工作目录连同暂存区域一并回退到Git仓库中上一次提交的状态。 + +## 任务 + +依次运行下面的命令,并观察系统的输出: + +1. 添加一个新文件: + ``` + [[echo 'This is a new file' > new_file]]{{RUN}} + [[git add new_file]]{{RUN}} + ``` + +2. 查看当前状态: + ``` + [[git status]]{{RUN}} + ``` + +3. 回退暂存区修改,并查看状态: + ``` + [[git reset]]{{RUN}} + [[git status]]{{RUN}} + ``` + +4. 修改现有文件,并将新增文件提交到暂存区: + ``` + [[echo 'This is a new line' > old_file]]{{RUN}} + [[git add .]]{{RUN}} + ``` + +5. 回退所有修改,并查看状态: + ``` + [[git reset --hard]]{{RUN}} + [[git status]]{{RUN}} + ``` \ No newline at end of file diff --git a/courses/git-101/working-remotely-2/step5.md b/courses/git-101/working-remotely-2/step5.md new file mode 100644 index 0000000000000000000000000000000000000000..fd98e9150d75928402ae9f1263928a979adf0b35 --- /dev/null +++ b/courses/git-101/working-remotely-2/step5.md @@ -0,0 +1,13 @@ +如果你在完成了一些修改的提交(committed)后,又想回退这些修改,那么需要使用 `git revert` 命令来完成这个操作。 `git revert` 命令会产生一个新的提交(commit),这个提交的内容则是指定提交的反作用。 + +## 任务 + +使用下面的命令回退最新的一次提交: + +``` +[[git revert HEAD --no-edit]]{{RUN}} +``` + +## Tips + +如果你的修改还没有推送到远端,那么 `git reset HEAD~1` 同样可以用来回退最后一次提交。 diff --git a/courses/make-and-packaging/assets/cover.png b/courses/make-and-packaging/assets/cover.png new file mode 100644 index 0000000000000000000000000000000000000000..e38ee30d67bc1fdec4ca713a39d0523ac95c33f6 Binary files /dev/null and b/courses/make-and-packaging/assets/cover.png differ diff --git a/courses/make-and-packaging/assets/logo.png b/courses/make-and-packaging/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2b3fcb251d16a599fb3503164de5e77ff70564b8 Binary files /dev/null and b/courses/make-and-packaging/assets/logo.png differ diff --git a/courses/make-and-packaging/assets/poster.png b/courses/make-and-packaging/assets/poster.png new file mode 100644 index 0000000000000000000000000000000000000000..77091e4e0e9d7c7ab30f870d8ac82b5c7188ffb1 Binary files /dev/null and b/courses/make-and-packaging/assets/poster.png differ diff --git a/courses/make-and-packaging/course-content.json b/courses/make-and-packaging/course-content.json new file mode 100644 index 0000000000000000000000000000000000000000..bbbb16a5998aacc8fd71b083eddda3e3a3167da7 --- /dev/null +++ b/courses/make-and-packaging/course-content.json @@ -0,0 +1,29 @@ +{ + "title": "在Linux环境下编译与构建软件包", + "description": "学习如何在Linux环境下进行软件开发、编译以及发布软件包", + "logo": "./assets/logo.png", + "poster": "./assets/poster.png", + "cover": "./assets/cover.png", + "container_live_time": "120", + "chapters": [ + { + "content_dir": "dev-under-linux", + "title": "在Linux环境下进行软件开发", + "description": "学习如何在Linux环境下进行软件开发", + "estimated_time": "30 min" + }, + { + "content_dir": "make-basics", + "title": "使用make编译你的代码", + "description": "学习如何使用make来编译你的程序", + "estimated_time": "30 min" + }, + { + "content_dir": "install-packages", + "title": "安装与分发软件", + "description": "学习如何在Linux中安装软件,以及如何构建和分发自己的软件包", + "estimated_time": "30 min" + } + ] + } + diff --git a/courses/make-and-packaging/dev-under-linux/finish.md b/courses/make-and-packaging/dev-under-linux/finish.md new file mode 100644 index 0000000000000000000000000000000000000000..0da4860852c1db856ce6a861c5a0cf219156b4b2 --- /dev/null +++ b/courses/make-and-packaging/dev-under-linux/finish.md @@ -0,0 +1 @@ +恭喜完成课程!继续学习下一章节掌握更多有关Linux环境下软件开发的知识和技能。 \ No newline at end of file diff --git a/courses/make-and-packaging/dev-under-linux/index.json b/courses/make-and-packaging/dev-under-linux/index.json new file mode 100644 index 0000000000000000000000000000000000000000..167d16a4da2c89ba43e401cd0dfa2b29a5402f15 --- /dev/null +++ b/courses/make-and-packaging/dev-under-linux/index.json @@ -0,0 +1,37 @@ +{ + "title": "在Linux环境下进行软件开发", + "description": "学习如何在Linux环境下进行软件开发", + "details": { + "steps": [ + { + "title": "Step 1 - 环境准备", + "md_file": "step1.md" + }, + { + "title": "Step 2 - 编写程序代码-1", + "md_file": "step2.md" + }, + { + "title": "Step 3 - 编译-1", + "md_file": "step3.md" + }, + { + "title": "Step 4 - 编写程序代码-2", + "md_file": "step4.md" + }, + { + "title": "Step 5 - 编译-2", + "md_file": "step5.md" + } + ], + "introduction": { + "md_file": "intro.md" + }, + "finish": { + "md_file": "finish.md" + } + }, + "backend": { + "image_id": "openEuler-20.03-lts-sp1" + } +} \ No newline at end of file diff --git a/courses/make-and-packaging/dev-under-linux/intro.md b/courses/make-and-packaging/dev-under-linux/intro.md new file mode 100644 index 0000000000000000000000000000000000000000..50cde333c71de0ef1ed94b67b751fe95dae3fcf7 --- /dev/null +++ b/courses/make-and-packaging/dev-under-linux/intro.md @@ -0,0 +1 @@ +通过本章内容,你将学习到Linux的基本操作以及在Linux环境下进行软件开发工作的基本能力。 \ No newline at end of file diff --git a/courses/make-and-packaging/dev-under-linux/step1.md b/courses/make-and-packaging/dev-under-linux/step1.md new file mode 100644 index 0000000000000000000000000000000000000000..1a7ae11c6c33d1ec4875c8b50db7e10193ddd96a --- /dev/null +++ b/courses/make-and-packaging/dev-under-linux/step1.md @@ -0,0 +1,19 @@ +在Linux下,软件开发工具通常被切割成一个个独立的小工具,各自处理不同的问题。以C语言软件开发为例,编辑器(emacs, vim等)用来进行编辑程序的,调试器(gdb)用来调试程序,编译器(GCC)用来编译和链接程序的,性能分析工具(gcov, gprof)用来优化程序,文档生成器(doxygen)用来生成文档等等。 + +本课程中我们将使用最基本的Vim编辑器以及Gcc编译器来演示如何在Linux下进行最基本的软件开发,在正式开始前,我们首先要检查环境中是否有这些软件以及其版本。 + +## 任务 + +使用`which`命令来检查所要用到的软件是否在环境中正确安装与配置。 + +``` +[[which gcc]]{{RUN}} +[[which vi]]{{RUN}} +``` + +使用下面命令来检查所要用到的软件版本是否满足你的开发需求。 + +``` +[[gcc --version]]{{RUN}} +[[vi --version]]{{RUN}} +``` \ No newline at end of file diff --git a/courses/make-and-packaging/dev-under-linux/step2.md b/courses/make-and-packaging/dev-under-linux/step2.md new file mode 100644 index 0000000000000000000000000000000000000000..3335fe894d70229bd7910188face7fb144a20156 --- /dev/null +++ b/courses/make-and-packaging/dev-under-linux/step2.md @@ -0,0 +1,28 @@ +在学习几乎任何一款编程语言时,第一个示例通常是编写一个在屏幕上打印`Hello World!`的示例程序,在本节中我们同样通过使用C语言编写这样一个示例程序来进行相应的学习。 + +## 任务 + +进入工作目录进行下一步学习: +`[[cd chapter1]]{{RUN}}` + +1. 执行 `[[vi hello.c]]{{RUN}}` 创建并打开一个新的名为`hello.c`的C语言程序代码文件。 + +2. 在键盘上点击 `a` 或 `i` 或 `s` 进入编辑模式。 + +3. 将下面的内容输入到终端中: +``` +#include + +int main(void){ + printf("Hello, World!\n"); +} +``` + +4. 在键盘上点击 `ESC` ,然后输入 `:wq` 保存并退出Vim编辑器 + +这样,我们就通过Vim编辑器完成了 `hello.c` 代码的开发。 + +## Tips + +更多有关Vim编辑器使用的学习内容,请参考: +https://www.vim.org/docs.php \ No newline at end of file diff --git a/courses/make-and-packaging/dev-under-linux/step3.md b/courses/make-and-packaging/dev-under-linux/step3.md new file mode 100644 index 0000000000000000000000000000000000000000..f258658ca87b820e3853d009d1e712d74552783c --- /dev/null +++ b/courses/make-and-packaging/dev-under-linux/step3.md @@ -0,0 +1,24 @@ +我们平时所说的程序,是指双击后就可以直接运行的程序,这样的程序被称为可执行程序(Executable Program)在 Windows 下,可执行程序的后缀有 `.exe` 和 `.com`(其中 `.exe` 比较常见);在类 UNIX 系统(Linux、Mac OS 等)下,可执行程序没有特定的后缀,系统根据文件的头部信息来判断是否是可执行程序。 + +可执行程序的内部是一系列计算机指令和数据的集合,它们都是二进制形式的,CPU 可以直接识别,毫无障碍;但是对于程序员,它们非常晦涩,难以记忆和使用,因此诞生了诸如我们刚才编写的C语言程序等高级编程语言。 + +但是对于CPU,C语言代码就是天书,根本不认识,CPU只认识几百个二进制形式的指令。这就需要一个工具,将C语言代码转换成CPU能够识别的二进制指令,也就是将代码加工成可执行程序;这个工具是一个特殊的软件,叫做编译器(Compiler)。 + +Linux 下常用的是 GUN 组织开发的 GCC,Linux 发行版通常都自带 GCC。 + + +## 任务 + +执行: + +`[[gcc hello.c -o hello]]{{RUN}}` + +执行 `[[ls -l]]{{RUN}}` 查看当前目录,可以看到生成了名为 `hello` 的可执行文件。 + +执行 `[[./hello]]{{RUN}}` 运行该可执行文件并查看运行结果。 + + +## Tips + +更多有关GCC的使用方法请参考: +https://www.runoob.com/w3cnote/gcc-parameter-detail.html \ No newline at end of file diff --git a/courses/make-and-packaging/dev-under-linux/step4.md b/courses/make-and-packaging/dev-under-linux/step4.md new file mode 100644 index 0000000000000000000000000000000000000000..99d5cc35dae191ff219fa2012753894ea7488285 --- /dev/null +++ b/courses/make-and-packaging/dev-under-linux/step4.md @@ -0,0 +1,36 @@ +通常实际可用的程序都是由多个子程序组合而成的,如果在一个主程序里调用了另一个子程序,那么该如何进行编译呢? + +## 任务 + +1. 执行 `[[vi hello.c]]{{RUN}}` 再次打开 `hello.c` C语言程序代码文件,我们将以这个程序作为主程序。 + +2. 使用键盘上的方向键将光标移动到 `}` 一行的结尾。 + +3. 在键盘上点击 `a` 或 `i` 进入编辑模式。 + +4. 修改文件内容为: +``` +#include + +int main(void){ + printf("Hello, World!\n"); + thanks(); +} +``` + +5. 在键盘上点击 `ESC` ,然后输入 `:wq` 保存并退出Vim编辑器 + +6. 执行 `[[vi thanks.c]]{{RUN}}` 创建并打开一个新的名为`thanks.c`的C语言程序代码文件,我们将以这个程序作为子程序。 + +7. 在键盘上点击 `a` 或 `i` 或 `s` 进入编辑模式。 + +8. 将下面的内容输入到终端中: +``` +#include + +int thanks(void){ + printf("Thank you!\n"); +} +``` + +9. 在键盘上点击 `ESC` ,然后输入 `:wq` 保存并退出Vim编辑器 diff --git a/courses/make-and-packaging/dev-under-linux/step5.md b/courses/make-and-packaging/dev-under-linux/step5.md new file mode 100644 index 0000000000000000000000000000000000000000..0fe173ebf80c2f9a9bf84e7816faf6103f087a6f --- /dev/null +++ b/courses/make-and-packaging/dev-under-linux/step5.md @@ -0,0 +1,20 @@ +在编译多个子程序所组成的程序时,需要首先将它们编译成目标文件(object),再以连接制作为最终的可执行文件。 + +## 任务 + +将源文件编译为目标文件: + +`[[gcc -c hello.c thanks.c]]{{RUN}}` + +通过 `[[ls -l]]{{RUN}}` 观察目录变化, `*.o` 是上一条命令编译产生的新文件。 + +将 `hello.o` 与 `thanks.o` 共同编译成可执行文件 `thanks` : +`[[gcc -o thanks hello.o thanks.o]]{{RUN}}` + +执行 `[[./thanks]]{{RUN}}` 并观察运行结果 + +执行 `[[cd ..]]{{RUN}}`返回到课程主目录 + +## Tips + +更复杂的程序间调用通常需要制作 `.h` 头文件并在程序源代码最顶端以 `#include ` 进行引用。 \ No newline at end of file diff --git a/courses/make-and-packaging/install-packages/finish.md b/courses/make-and-packaging/install-packages/finish.md new file mode 100644 index 0000000000000000000000000000000000000000..720c816d27eafc3b14d87aa26f36d2e476f3d514 --- /dev/null +++ b/courses/make-and-packaging/install-packages/finish.md @@ -0,0 +1 @@ +恭喜完成课程!继续学习下一章节掌握更多有关Linux系统的知识。 \ No newline at end of file diff --git a/courses/make-and-packaging/install-packages/index.json b/courses/make-and-packaging/install-packages/index.json new file mode 100644 index 0000000000000000000000000000000000000000..f17de57d4b716f27c326fb38cfb3b088b60acf29 --- /dev/null +++ b/courses/make-and-packaging/install-packages/index.json @@ -0,0 +1,33 @@ +{ + "title": "在Linux环境下安装软件", + "description": "学习如何在Linux环境下安装软件", + "details": { + "steps": [ + { + "title": "Step 1 - Tarball", + "md_file": "step1.md" + }, + { + "title": "Step 2 - RPM", + "md_file": "step2.md" + }, + { + "title": "Step 3 - DNF", + "md_file": "step3.md" + }, + { + "title": "Step 4 - rpmbuild", + "md_file": "step4.md" + } + ], + "introduction": { + "md_file": "intro.md" + }, + "finish": { + "md_file": "finish.md" + } + }, + "backend": { + "image_id": "openEuler-20.03-lts-sp1" + } +} \ No newline at end of file diff --git a/courses/make-and-packaging/install-packages/intro.md b/courses/make-and-packaging/install-packages/intro.md new file mode 100644 index 0000000000000000000000000000000000000000..fd51b45070ee09dcae5544b196a9e1c087c6328b --- /dev/null +++ b/courses/make-and-packaging/install-packages/intro.md @@ -0,0 +1 @@ +通过本章内容,你将学习到如何在Linux环境下安装新的软件。 \ No newline at end of file diff --git a/courses/make-and-packaging/install-packages/step1.md b/courses/make-and-packaging/install-packages/step1.md new file mode 100644 index 0000000000000000000000000000000000000000..98760225e5308e83c72f2332e81691d3ecab5075 --- /dev/null +++ b/courses/make-and-packaging/install-packages/step1.md @@ -0,0 +1,34 @@ +在上一章中我们学习到了如何在Linux环境下编译自己的软件包,那么如果我们想安装其他开发者开发的软件应该如何操作呢? + +Linux开源软件通常有多种发布形式,其中最基本的发布方式是以Tarball进行发布:软件开发者将将软件的所有源码文件以 tar 打包,然后再压缩(通常是 gzip),所以 tarball 文件一般的扩展名为 `*.tar.gz` 或是简写为 `*tgz`。不过,近来由于 bzip2 与 xz 的压缩率较佳,因此它对应的后缀名为 `*.tar.bz2` 、`*.tar.xz` 。 + +所以,Tarball 是一个软件包,将它解压之后,里面的文件通常会有: + +- 源代码文件 +- 检测程序(可能是 configure 或 config) +- 本软件的简易说明与安装说明(INSTALL 或 README) + +通过阅读解压后的项目目录中的`INSTALL`或`README`文档就可以按照步骤完成安装,下面为大家展示典型的Tarball安装过程。 + + +## 任务 + +我们将上一章的示例代码以Tarball形式进行了发布,依次执行下面的命令完成 `angle` 的安装。 + +1. 执行 `[[cd chapter3]]{{RUN}}` 进入章节目录 + +2. 执行 `[[ls -l]]{{RUN}}` 查看当前目录中的文件情况 + +3. 执行 `[[tar -xzvf angle-0.1.tar.gz]]{{RUN}}` 将Tarball进行解压缩 + +4. 执行 `[[cd angle && ls -l]]{{RUN}}` 进入项目源码目录并查看目录内容,可以看到目录有包含项目源码的 `src` 文件夹、说明文件 `README.md` 以及若干其他文件 + +5. 执行 `[[mkdir build && cd build]]{{RUN}}` 创建 `build` 文件夹并进入,这样做的好处是可以保持原项目目录的整洁 + +6. 执行 `[[../configure]]{{RUN}}` 进行项目配置,这个操作会启动对系统依赖、配置等的自动检查和配置,并生成针对于当前主机的 `Makefile` ,有关 `Makefile` 的内容我们已经在前面的章节中介绍过。由于软件开发者与使用者的实际环境可能存在不一致的情况(架构不同、软件版本不同等等),因此对于复杂的项目使用工具根据使用者环境的实际情况生成 `Makefile` 是最为合理的 + +7. 执行 `[[make]]{{RUN}}` 完成项目的编译 + +8. 执行 `[[sudo make install]]{{RUN}}` 完成项目的安装 + +9. 执行 `[[angle]]{{RUN}}` 并与程序进行交互 \ No newline at end of file diff --git a/courses/make-and-packaging/install-packages/step2.md b/courses/make-and-packaging/install-packages/step2.md new file mode 100644 index 0000000000000000000000000000000000000000..e0296c549d7cd177b8271f0d95c348a1992036d5 --- /dev/null +++ b/courses/make-and-packaging/install-packages/step2.md @@ -0,0 +1,40 @@ +在上一节内容中,我们学习了如何将从网上下载得到的Tarball安装到机器中,虽然只需要简单的几行命令就可以完成配置和安装,但是由于安装过程中包含了配置、编译等等过程,对于复杂庞大的项目来说,还是非常耗时的。同时,也不是每个人都会进行源码编译,因此如果能预先在相同的硬件与操作系统上编译好才发布的话,就可以让相同的操作系统发行版具有完全一致的软件版本了,再加上简易的安装、移除、管理等机制的话,对于软件管理就容易多了。 + +基于这个需求,就诞生了软件管理程序,知名的软件管理程序有`RPM`、`DPKG`等,下面的内容将以 `RPM` 为例进行介绍。 + +RPM 全名 RPM Package Manager(http://rpm.org/),是以一种数据库记录的方式将你所需要的软件安装到你的 Linux 系统的一套管理机制 + +最大的特点:将你要安装的软件先编译过,并且达成 RPM 机制的包装文件,通过包装文件里面的默认的数据库记录,记录这个软件要安装的时候必须具备的相依属性软件,当安装在你的 Linux 主机时,RPM 会先依照软件里的数据查询 Linux 主机的相依属性是否满足,若满足则安装,若不满足,则不安装。那么安装的时候就将该软件的信息整个写入 RPM 的数据库,以便未来的查询、验证与卸载,优点: + +1. 不需要再重新编译:由于已经变异完成并且打包完毕,所以软件传输与安装上很方便 +2. 由于软件的信息都已经记录在 Linux 主机的数据库上,很方便查询、升级与卸载 + +我们已经将之前的三角函数计算软件打包成了名为 `anglerpm-0.1-1.x86_64.rpm` 的 `rpm` 软件包,其命名可以体现如下信息: + +- 文件名通常遵循这样的格式:`{Name}-{Version}-{Release}.{Arch}.rpm` +- `anglerpm`: 软件名为 `anglerpm` (rpm后缀与手动安装方式区分) +- `0.1-1`: 软件版本为 `0.1` ,编译版本为 `1`(在源代码主体版本没有变化的情况下,编译过程中可能加入了新的patch补丁,修改了编译脚本等等情况下需要重新编译时,bump编译版本) +- `x86_64`: 该rpm软件包支持的平台为x86_64,不同架构的rpm版本通常不能通用 + +下面我们将展示如何安装该rpm软件包 + +## 任务 + +1. 执行 `[[cd /home/coder/make-and-packaging/chapter3/]]{{RUN}}` 返回章节目录。 + +2. 执行 `[[wget https://github.com/opensourceways/playground-courses/releases/download/v0.1/anglerpm-0.1-1.x86_64.rpm]]{{RUN}}` 下载rpm软件包。 + +3. 执行 `[[sudo rpm -i anglerpm-0.1-1.x86_64.rpm]]{{RUN}}` 安装rpm软件包。 + +4. 执行 `[[anglerpm]]{{RUN}}` 并与程序交互,查看安装结果 + +可以看到使用 `rpm` ,可以仅用一条命令就完成我们编写的软件的安装,非常方便,那么对于更复杂的软件呢? + +5. 执行下面的命令,下载openEuler 20.03 LTS SP1中的 `mariadb-server-10.3.9` : + ``` + `[[wget https://mirrors.tuna.tsinghua.edu.cn/openeuler/openEuler-20.03-LTS-SP1/everything/x86_64/Packages/mariadb-server-10.3.9-9.oe1.x86_64.rpm]]{{RUN}}` + ``` + +6. 执行 `[[sudo rpm -i mariadb-server-10.3.9-9.oe1.x86_64.rpm]]{{RUN}}` 尝试安装这个rpm + +可以看到安装失败了,因为软件 `mariadb-server` 有其他依赖,但是在我们的系统中并没有安装这些依赖,如果要正常安装,则需要先安装完这些依赖的软件。对于庞大且复杂的软件来说,软件的依赖可能达到上百款,同时依赖又有自己的依赖,手动完成软件依赖的查找和安装几乎是不可能完成的任务。 \ No newline at end of file diff --git a/courses/make-and-packaging/install-packages/step3.md b/courses/make-and-packaging/install-packages/step3.md new file mode 100644 index 0000000000000000000000000000000000000000..02ef7b4041e73843958779c6bc5d20db65c688ff --- /dev/null +++ b/courses/make-and-packaging/install-packages/step3.md @@ -0,0 +1,26 @@ +上一节内容的最后我们了解到对于依赖复杂的项目来说,手动完成所有依赖的安装是非常困难的,如果能有工具帮助我们完成这样的工作就好了。 + +DNF(Dandified YUM)就是RPM软件包体系下的这样一款工具,DNF通过分析 RPM 的标头数据后,根据各软件的相关性制作出依赖时的解决方案,然后可以自动处理软件的依赖问题,以解决软件安装或移除或升级的问题。 + +操作系统发行版首先将软件打包成RPM软件包,然后将软件放置于YUM(DNF的上一代)服务器上,提供客户端的使用。因此我们想要使用DNF的功能时,必须要先找到适合的 yum server 才行,而每个 yum server 可能都会提供许多不同的软件功能,这就"软件库(Repo, Repository)"。 + + +## 任务 + +1. 执行 `[[sudo rm -f /etc/yum.repos.d/openEuler.repo]]{{RUN}}` 删除旧的yum repo配置文件。 + +2. 执行 `[[sudo vi /etc/yum.repos.d/openEuler-2003.repo]]{{RUN}}` 创建并编辑yum repo配置文件。 + +3. 按照下面的内容进行配置,该命令将会创建一条指向 `openEuler-21.09 Everything` 软件仓库的配置: + + ``` + [everything] + name=everything + baseurl=http://mirrors.tuna.tsinghua.edu.cn/openeuler/openEuler-20.03-LTS-SP1/everything/$basearch/ + enabled=1 + gpgcheck=1 + gpgkey=http://mirrors.tuna.tsinghua.edu.cn/openeuler/openEuler-20.03-LTS-SP1/everything/$basearch/RPM-GPG-KEY-openEuler + + ``` + +4. 执行 `[[sudo dnf install -y mariadb-server]]{{RUN}}` ,可以看到 `mariadb-server` 和它所需要的依赖被一并安装了。 \ No newline at end of file diff --git a/courses/make-and-packaging/install-packages/step4.md b/courses/make-and-packaging/install-packages/step4.md new file mode 100644 index 0000000000000000000000000000000000000000..605a78b157699ca20f1d3518678bc51937c4dcd2 --- /dev/null +++ b/courses/make-and-packaging/install-packages/step4.md @@ -0,0 +1,103 @@ +在本章前面的几节内容中,我们已经了解到了如何使用 `Tarball`、`RPM` 以及 `DNF` 来安装软件。在本节我们将学习如何创建一个简单的RPM软件包。 + +RPM软件包使用 `rpmbuild` 工具进行制作,工具初始化完成后,会在当前用户的家目录下创建相应的工作目录(以root用户为例): + +- `/root/rpmbuild/SPECS/`:该软件的配置文件,例如软件的信息参数、设置项目等 +- `/root/rpmbuild/SOURCES/`:软件的原始文件(*.tar.gz 的文件) 以及 config 配置文件 +- `/root/rpmbuild/BUILD/`:在编译过程中,有些暂存的数据都会放置在该目录中 +- `/root/rpmbuild/RPMS/`:经过编译之后,并且顺利编译成功之后,将打包完成的文件放在该目录中,包含了 x86_64,noarch... 等的次要目录 +- `/root/rpmbuild/SRPMS/`:与 RPMS 目录相似,放置的是 SRPM 封装的文件 + +在开始制作的过程前,我们需要做的是: +1. 将源码文件放置到 `/root/rpmbuild/SOURCES/` 目录中 +2. 编写 `*.spec` 文件并放置到 `/root/rpmbuild/SPECS/` 目录中 + +SPEC文件是指导 `rpmbuild` 工作的配置文件,通常包含了该软件包的名称、版本、开源协议等相关信息以及构建各环节的脚本等配置: + +- `Summary`:软件的主要说明 +- `Name`:软件的名称(最终会是 RPM 文件的名称构成之一) +- `Version`:软件的版本(也是 RPM 文件名构成之一) +- `Release`:该版本打包的次数说明(也是 RPM 文件名构成之一)。 +- `License`:软件的授权模式,看起来涵盖了所有知名的 Open source 授权 +- `URL`:源码的主要官网 +- `SourceN`:软件的来源,如果是网络上下载的软件,通常这里一定会有这个信息来告诉大家这个原始文件的来源,此外,如果有多个软件来源,则会以 Source0、Source1... 开处理源码 +- `PatchN`:作为补丁的 patch file,也是可以有多个 +- `BuildRoot`:作为编译时,该使用哪个目录来暂存中间文件(如果编译过程的目标文件、链接文件等) +上述信息为必须存在的项目,下面的则为可使用的额外设置 +- `Requires`:如果这个软件运行时还需要其他的软件支持,就必须配置,则当你制作成 RPM 后,系统就会自动去检查,这就是软件依赖的来源 +- `BuildRequires`:编译过程中所需要的软件。Requires 指的是安装时需要检查,因为与实际运行有关,而 BuildRequires 则是 编译时 所需要的软件,只有在 SRPM 编译为 RPM 时才会检查的项目 + +对于软件构建的脚本控制则位于指定的宏定义后: + +- `%description`: 将你的软件做一个简短的说明,这个也是必须的,在使用 rpm -qi 软件名称 出现的一些基础说明就包括这里的设置信息 + +- `%prep` 尚未进行设置或安装之前,你要编译完成的 RPM 帮你实现做的事情,就是 prepare 的简写,它的主要任务可以包括: + - 进行软件的补丁(patch)等相关工作 + - 寻找软件所需要的目录是否已经存在 + +- `%build`: 该段落在配置 make 编译称为可执行的程序。会发现在此部分的程序代码,就是 ./configure,make 等命令。 + +- `%install`: 编译完成后,就要安装了,也就是类似 Tarball 里面的 make install + +- `%files`: 这个软件安装的文件都需要写到这里来,也包括目录,以备查验用。此外也可以指定每个文件的类型,包括帮助文件(%doc 后面接的文件)与配置文件 %config 后面接的文件 + +- `%changelog`: 主要记录该软件曾经的更新记录,星号 * 后面应该要以时间、修改者、email 与软件版本来作为说明,减号 - 后面则是你详细的说明。 + +## 任务 + +1. 执行 `[[sudo rpm -e anglerpm-0.1-1.x86_64.rpm]]{{RUN}}` 卸载上一节中完成安装的软件。 + +2. 执行 `[[mkdir -p /home/coder/rpmbuild/SOURCES/ && cd /home/coder/rpmbuild/SOURCES/ && wget https://github.com/opensourceways/playground-courses/releases/download/v0.1/anglerpm-0.1.tar.gz]]{{RUN}}` 下载Tarball软件包并放置到 `SOURCES` 目录下。 + +3. 执行 `[[mkdir -p /home/coder/rpmbuild/SPECS/ && cd /home/coder/rpmbuild/SPECS/ && vi anglerpm.spec]]{{RUN}}` 创建并开始编辑spec文件。 + +4. 按照以下内容编辑 `anglerpm.spec`, 其中`changelog`部分请根据实际情况填写 : + ``` + Name: anglerpm + Version: 0.1 + Release: 1%{?dist} + Summary: Get your name and show sin and cos value. + + Group: Scientific Support + License: GPLv2 + URL: http:/playground.openeuler.org/ + Source0: anglerpm-0.1.tar.gz + + # BuildRequires: + + %description + This package will let you input your name and calculate sin cos value + + %prep + %setup -q + + + %build + ./configure + make + + %install + mkdir -p %{buildroot}/usr/local/bin + install -m 755 anglerpm %{buildroot}/usr/local/bin + + %files + /usr/local/bin/anglerpm + + %changelog + * Mon Feb 14 2022 openEuler Playground - 0.1 + - Build the program & Happy Valentine's Day + + ``` + +5. 执行 `[[rpmbuild -ba anglerpm.spec]]{{RUN}}` 开始制作rpm软件包 + +6. 执行 `[[cd /home/coder/rpmbuild/RPMS/x86_64 && ls -l]]{{RUN}}` 进入到生成目录并查看内容。 + +7. 执行 `[[sudo rpm -i anglerpm-0.1-1.x86_64.rpm]]{{RUN}}` 尝试安装新构建完成的rpm软件包。 + +8. 执行 `[[anglerpm]]{{RUN}}` 运行并与程序交互。 + +## Tips + +更多有关 `rpmbuild` 的详细内容请参考:https://rpm-software-management.github.io/rpm/manual/ + diff --git a/courses/make-and-packaging/make-basics/finish.md b/courses/make-and-packaging/make-basics/finish.md new file mode 100644 index 0000000000000000000000000000000000000000..58295995433457d1e35e078f8d494272ec455818 --- /dev/null +++ b/courses/make-and-packaging/make-basics/finish.md @@ -0,0 +1 @@ +恭喜完成课程!继续学习下一章节掌握更多有关Linux系统的知识和使用。 \ No newline at end of file diff --git a/courses/make-and-packaging/make-basics/index.json b/courses/make-and-packaging/make-basics/index.json new file mode 100644 index 0000000000000000000000000000000000000000..14dce79a4971166e186e53729e2af18330524bc5 --- /dev/null +++ b/courses/make-and-packaging/make-basics/index.json @@ -0,0 +1,33 @@ +{ + "title": "在Linux环境下进行软件开发", + "description": "学习如何在Linux环境下进行软件开发", + "details": { + "steps": [ + { + "title": "Step 1 - 手动编译", + "md_file": "step1.md" + }, + { + "title": "Step 2 - make & makefile - 1", + "md_file": "step2.md" + }, + { + "title": "Step 3 - make", + "md_file": "step3.md" + }, + { + "title": "Step 4 - make clean", + "md_file": "step4.md" + } + ], + "introduction": { + "md_file": "intro.md" + }, + "finish": { + "md_file": "finish.md" + } + }, + "backend": { + "image_id": "openEuler-20.03-lts-sp1" + } +} \ No newline at end of file diff --git a/courses/make-and-packaging/make-basics/intro.md b/courses/make-and-packaging/make-basics/intro.md new file mode 100644 index 0000000000000000000000000000000000000000..50cde333c71de0ef1ed94b67b751fe95dae3fcf7 --- /dev/null +++ b/courses/make-and-packaging/make-basics/intro.md @@ -0,0 +1 @@ +通过本章内容,你将学习到Linux的基本操作以及在Linux环境下进行软件开发工作的基本能力。 \ No newline at end of file diff --git a/courses/make-and-packaging/make-basics/step1.md b/courses/make-and-packaging/make-basics/step1.md new file mode 100644 index 0000000000000000000000000000000000000000..a9b20f510dbdf4f78ca98665e769f4f281d3ac1c --- /dev/null +++ b/courses/make-and-packaging/make-basics/step1.md @@ -0,0 +1,29 @@ +在上一章中我们学习到了如何在linux环境下进行软件开发工作,以及如何将一个简单的程序编译成可执行文件,接下来我们将学习如何编译更复杂的程序。 + + +## 任务 + +1. 执行 `[[cd chapter2]]{{RUN}}` 进入章节目录 + +2. 执行 `[[ls -l]]{{RUN}}` 查看当前目录中的文件情况: + + 可以看到执行文档里面包含了 4 个源码文件,分别是 `main.c`、 `hello.c`、 `sin_value.c` 和 `cos_value.c` : + + `main.c`:主要目的是让用户输入角度数据与调用其他三个子程序 + + `hello.c`:输出欢迎信息 + + `sin_value.c`:计算使用者输入的角度(360)sin 数值 + + `cos_value.c`:计算使用者输入的角度(360)cos 数值 + +3. 编译项目: + + 执行 `[[gcc -c main.c hello.c sin_value.c cos_value.c]]{{RUN}}` 进行目标文件的编译,最终会有 4 个 *.o 的文件出现. + + 执行 `[[gcc -o angle_cal main.o hello.o sin_value.o cos_value.o -lm]]{{RUN}}` 连结所有目标文件为执行文件,并加入 libm 的函数,产生名为 `angle_cal` 的执行文件 + +4. 执行程序并与程序进行交互,查看程序执行结果: + + 执行 `[[./angle_cal]]{{RUN}}` + diff --git a/courses/make-and-packaging/make-basics/step2.md b/courses/make-and-packaging/make-basics/step2.md new file mode 100644 index 0000000000000000000000000000000000000000..4276f4c227604f9d82d7bc827d67f204002340be --- /dev/null +++ b/courses/make-and-packaging/make-basics/step2.md @@ -0,0 +1,39 @@ +可以看到,相对与第一章中程序的编译,刚才的编译指令就变得复杂起来了,如果要重新编译,上述流程还需要重新来一次。对于更为复杂的项目来说,这样操作不仅麻烦,还容易出错。 + +可以使用 `make` 工具简化我们的工作,`make` 工具执行时,需要一个 `Makefile` 文件,以告诉 `make` 工具需要怎么样的去编译和链接程序。 + +## 任务 + +1. 执行 `[[vi Makefile]]{{RUN}}` 为项目创建 `Makefile`。 + +2. 在键盘上点击 `a` 或 `i` 或 `s` 进入编辑模式。 + +3. 将下面的内容输入到终端中: + ``` + main: main.o hello.o sin_value.o cos_value.o + gcc -o main main.o hello.o sin_value.o cos_value.o -lm + ``` + 注意第 2 行数据,是按 `TAB` 键产生的空格 + +4. 在键盘上点击 `ESC` ,然后输入 `:wq` 保存并退出Vim编辑器 + +这样,我们就通过Vim编辑器完成了 `Makefile` 的编写。 + +## Tips + +`Makefile` 的语法多而复杂,可以参考 GUN 官网文档,这里仅做一些基本的介绍: + +在 makefile 中的规则基本上是: + +`\#` 代表批注 + +`` 需要在命令行的第一个字符 + +目标 target 与相依文件(目标文件)之间以 `:` 分割 + +例如: + +``` +目标(target):目标文件1 目标文件2 + gcc -o 欲建立的执行文件 目标文件1 目标文件2 +``` \ No newline at end of file diff --git a/courses/make-and-packaging/make-basics/step3.md b/courses/make-and-packaging/make-basics/step3.md new file mode 100644 index 0000000000000000000000000000000000000000..2519a7efaffccfdf9192d714d058ba2cfe9f6620 --- /dev/null +++ b/courses/make-and-packaging/make-basics/step3.md @@ -0,0 +1,19 @@ +下面我们将尝试使用刚刚编写好的 `Makefile` 来进行项目的编译 + +## 任务 + +删除上一步中产生的 `*.o` 文件: + +`[[rm -f *.o]]{{RUN}}` + +执行 `[[make]]{{RUN}}` 进行编译,此时 make 会读取 makefile 的内容,并根据内容直接编译相关的文件 + +执行 `[[./main]]{{RUN}}` 并与程序进行交互,查看程序执行结果。 + +## Tips + +上面的执行,从命令行输出来看,获取你会觉得 shell script 也可以做到,的确是这样,但是 make 提供了增量编译的机制,不需要你自己去写那么复杂的流程判断了。好处如下: + +简化编译时所需要下达的指令 +若在编译完成之后,修改了某个源码文件,则 make 仅会针对被修改了的文件进行编译,其他的 object file 不会变动 +最后可以依照相依性来更新(update)执行文件 \ No newline at end of file diff --git a/courses/make-and-packaging/make-basics/step4.md b/courses/make-and-packaging/make-basics/step4.md new file mode 100644 index 0000000000000000000000000000000000000000..583dbbd62d944f6163035ad63a56f66d4113ecd2 --- /dev/null +++ b/courses/make-and-packaging/make-basics/step4.md @@ -0,0 +1,30 @@ +对上这个示例,如果有两个以上的执行动作时,如何做?比如增加一个指令,直接清除所有的目标文件与执行文件。 + +## 任务 + +1. 执行 `[[vi Makefile]]{{RUN}}` 再次打开`Makefile`文件。 + +2. 使用键盘上的方向键将光标移动到文件的结尾。 + +3. 在键盘上点击 `a` 或 `i` 进入编辑模式。 + +4. 修改文件内容为: + ``` + main: main.o hello.o sin_value.o cos_value.o + gcc -o main main.o hello.o sin_value.o cos_value.o -lm + + clean: + rm -rf main.o hello.o sin_value.o cos_value.o + ``` + +5. 在键盘上点击 `ESC` ,然后输入 `:wq` 保存并退出Vim编辑器 + + +6. 执行: + + `[[make clean]]{{RUN}}` 清除所有 `*.o` 文件 + + `[[ls -l]]{{RUN}}` 观察目录结果 + +7. 返回课程目录: + 执行 `[[cd ..]]{{RUN}}` diff --git a/courses/playground/LICENSE b/courses/playground/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..a1c6a321fccaf6ff41fe0c92c7aa0400a6a9d7e9 --- /dev/null +++ b/courses/playground/LICENSE @@ -0,0 +1,128 @@ + 木兰宽松许可证, 第2版 + + 木兰宽松许可证, 第2版 + 2020年1月 http://license.coscl.org.cn/MulanPSL2 + + + 您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束: + + 0. 定义 + + “软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。 + + “贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。 + + “贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。 + + “法人实体”是指提交贡献的机构及其“关联实体”。 + + “关联实体”是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。 + + 1. 授予版权许可 + + 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。 + + 2. 授予专利许可 + + 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。 + + 3. 无商标许可 + + “本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。 + + 4. 分发限制 + + 您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。 + + 5. 免责声明与责任限制 + + “软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。 + + 6. 语言 + “本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。 + + 条款结束 + + 如何将木兰宽松许可证,第2版,应用到您的软件 + + 如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步: + + 1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字; + + 2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中; + + 3, 请将如下声明文本放入每个源文件的头部注释中。 + + Copyright (c) [Year] [name of copyright holder] + [Software Name] is licensed under Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. + + + Mulan Permissive Software License,Version 2 + + Mulan Permissive Software License,Version 2 (Mulan PSL v2) + January 2020 http://license.coscl.org.cn/MulanPSL2 + + Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions: + + 0. Definition + + Software means the program and related documents which are licensed under this License and comprise all Contribution(s). + + Contribution means the copyrightable work licensed by a particular Contributor under this License. + + Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License. + + Legal Entity means the entity making a Contribution and all its Affiliates. + + Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity. + + 1. Grant of Copyright License + + Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not. + + 2. Grant of Patent License + + Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken. + + 3. No Trademark License + + No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in Section 4. + + 4. Distribution Restriction + + You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software. + + 5. Disclaimer of Warranty and Limitation of Liability + + THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + 6. Language + + THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL. + + END OF THE TERMS AND CONDITIONS + + How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software + + To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps: + + i Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner; + + ii Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package; + + iii Attach the statement to the appropriate annotated syntax at the beginning of each source file. + + + Copyright (c) [Year] [name of copyright holder] + [Software Name] is licensed under Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. + \ No newline at end of file diff --git a/courses/playground/README.md b/courses/playground/README.md new file mode 100644 index 0000000000000000000000000000000000000000..513e6a1ba9a1ad889fab1e34f9f6f65cf0305457 --- /dev/null +++ b/courses/playground/README.md @@ -0,0 +1,8 @@ +# openEuler Playground +在浏览器中体验openEuler + +# 课程目录 + - 第一章:在浏览器中体验openEuler + +# Owners +Zhenyu Zheng diff --git a/courses/playground/assets/cover.png b/courses/playground/assets/cover.png new file mode 100644 index 0000000000000000000000000000000000000000..31c5bf1ca5a9f285f28a9348c08efabef34e47b8 Binary files /dev/null and b/courses/playground/assets/cover.png differ diff --git a/courses/playground/assets/logo.png b/courses/playground/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2b3fcb251d16a599fb3503164de5e77ff70564b8 Binary files /dev/null and b/courses/playground/assets/logo.png differ diff --git a/courses/playground/assets/poster.png b/courses/playground/assets/poster.png new file mode 100644 index 0000000000000000000000000000000000000000..77091e4e0e9d7c7ab30f870d8ac82b5c7188ffb1 Binary files /dev/null and b/courses/playground/assets/poster.png differ diff --git a/courses/playground/course-content.json b/courses/playground/course-content.json new file mode 100644 index 0000000000000000000000000000000000000000..c527a35e86e96cb9d98af2eb78d9a64f4dc370e1 --- /dev/null +++ b/courses/playground/course-content.json @@ -0,0 +1,16 @@ +{ + "title": "openEuler Playground: 在浏览器中体验openEuler", + "description": "openEuler Playground: 在浏览器中体验openEuler", + "logo": "./assets/logo.png", + "poster": "./assets/poster.png", + "cover": "./assets/cover.png", + "container_live_time": "120", + "chapters": [ + { + "content_dir": "playground", + "title": "openEuler Playground: 在浏览器中体验openEuler", + "description": "openEuler Playground: 在浏览器中体验openEuler", + "estimated_time": "120 min" + } + ] + } diff --git a/courses/playground/playground/finish.md b/courses/playground/playground/finish.md new file mode 100644 index 0000000000000000000000000000000000000000..e2cd40f8c5aedf13013cfcdc6cd78df79624deaa --- /dev/null +++ b/courses/playground/playground/finish.md @@ -0,0 +1 @@ +感谢体验openEuler Playground! \ No newline at end of file diff --git a/courses/playground/playground/index.json b/courses/playground/playground/index.json new file mode 100644 index 0000000000000000000000000000000000000000..bc1bef94aff47a010010a517514cdbdde72e65fb --- /dev/null +++ b/courses/playground/playground/index.json @@ -0,0 +1,25 @@ +{ + "title": "创建你的第一个openEuler Playground章节", + "description": "学习如何创建openEuler Playground章节", + "details": { + "steps": [ + { + "title": "Step 1 - 章节结构", + "md_file": "step1.md" + }, + { + "title": "Step 2 - 语法", + "md_file": "step2.md" + } + ], + "introduction": { + "md_file": "intro.md" + }, + "finish": { + "md_file": "finish.md" + } + }, + "backend": { + "image_id": "openeuler-20.03-lts-sp1" + } +} diff --git a/courses/playground/playground/intro.md b/courses/playground/playground/intro.md new file mode 100644 index 0000000000000000000000000000000000000000..c2019fcbc4836a5cb7359af927f917c107a2de67 --- /dev/null +++ b/courses/playground/playground/intro.md @@ -0,0 +1 @@ +在浏览器中体验openEuler真实环境! diff --git a/courses/playground/playground/step1.md b/courses/playground/playground/step1.md new file mode 100644 index 0000000000000000000000000000000000000000..3ad8bbf6847fe18f794bb371ddf413c31343d6f6 --- /dev/null +++ b/courses/playground/playground/step1.md @@ -0,0 +1 @@ +在浏览器中体验openEuler真实环境! \ No newline at end of file