mirror of
https://github.com/GXDE-OS/GXDE.git
synced 2026-08-09 14:00:51 +08:00
Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
23aba101a6 | ||
|
|
8ee15d5725 | ||
|
|
a6f6c26fb9 | ||
|
|
eebd5d7817 | ||
|
|
dd3d0e1a34 | ||
|
|
73a77bb9ca | ||
|
|
96feeb840f |
@@ -140,10 +140,8 @@ jobs:
|
||||
mkdir -p ~/.ssh/
|
||||
ssh-keyscan -p $UPORT -H $UHOST >> ~/.ssh/known_hosts
|
||||
tarName=$(ls | grep .tar | head -n 1)
|
||||
sudo sysctl -w net.ipv4.tcp_mtu_probing=1
|
||||
sshpass -p "$UPASSWD" scp -o HostKeyAlgorithms=ecdsa-sha2-nistp256 -o KexAlgorithms=ecdh-sha2-nistp256 -c aes128-ctr -O $tarName $UUSERS@$UHOST:$UPATH
|
||||
sshpass -p "$UPASSWD" ssh $UUSERS@$UHOST -o HostKeyAlgorithms=ecdsa-sha2-nistp256 -o KexAlgorithms=ecdh-sha2-nistp256 -c aes128-ctr -p $UPORT $UPROGRAM ${{ inputs.gxde-codename-upload }} $UPATH/$tarName > /dev/null
|
||||
sudo sysctl -w net.ipv4.tcp_mtu_probing=0
|
||||
sshpass -p "$UPASSWD" rsync -e "ssh -p $UPORT" $tarName $UUSERS@$UHOST:$UPATH
|
||||
sshpass -p "$UPASSWD" ssh $UUSERS@$UHOST -p $UPORT $UPROGRAM ${{ inputs.gxde-codename-upload }} $UPATH/$tarName > /dev/null
|
||||
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
|
||||
@@ -141,10 +141,8 @@ jobs:
|
||||
mkdir -p ~/.ssh/
|
||||
ssh-keyscan -p $UPORT -H $UHOST >> ~/.ssh/known_hosts
|
||||
tarName=$(ls | grep .tar | head -n 1)
|
||||
sudo sysctl -w net.ipv4.tcp_mtu_probing=1
|
||||
sshpass -p "$UPASSWD" scp -o HostKeyAlgorithms=ecdsa-sha2-nistp256 -o KexAlgorithms=ecdh-sha2-nistp256 -c aes128-ctr -O $tarName $UUSERS@$UHOST:$UPATH
|
||||
sshpass -p "$UPASSWD" ssh $UUSERS@$UHOST -o HostKeyAlgorithms=ecdsa-sha2-nistp256 -o KexAlgorithms=ecdh-sha2-nistp256 -c aes128-ctr -p $UPORT $UPROGRAM ${{ inputs.gxde-codename-upload }} $UPATH/$tarName > /dev/null
|
||||
sudo sysctl -w net.ipv4.tcp_mtu_probing=0
|
||||
sshpass -p "$UPASSWD" rsync -e "ssh -p $UPORT" $tarName $UUSERS@$UHOST:$UPATH
|
||||
sshpass -p "$UPASSWD" ssh $UUSERS@$UHOST -p $UPORT $UPROGRAM ${{ inputs.gxde-codename-upload }} $UPATH/$tarName > /dev/null
|
||||
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
|
||||
@@ -16,17 +16,15 @@ jobs:
|
||||
- name: Config
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install git python3-requests -y
|
||||
sudo apt install git -y
|
||||
|
||||
- name: Push
|
||||
env:
|
||||
GITHUBTOKEN: ${{ secrets.GITHUBTOKEN }}
|
||||
GITHUBUSER: ${{ secrets.GITHUBUSER }}
|
||||
GITCODETOKEN: ${{ secrets.GITCODETOKEN }}
|
||||
GITCODEUSER: ${{ secrets.GITCODEUSER }}
|
||||
ATOMGITTOKEN: ${{ secrets.ATOMGITTOKEN }}
|
||||
ATOMGITUSER: ${{ secrets.ATOMGITUSER }}
|
||||
GITEEUSER: ${{ secrets.GITEEUSER }}
|
||||
GITEETOCKEN: ${{ secrets.GITEETOCKEN }}
|
||||
run: |
|
||||
cd sync-gitee-to-github
|
||||
python3 sync.py $GITHUBUSER $GITHUBTOKEN $GITCODEUSER $GITCODETOKEN $ATOMGITUSER $ATOMGITTOKEN
|
||||
python3 sync.py $GITEEUSER $GITEETOCKEN $GITHUBUSER $GITHUBTOKEN
|
||||
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||

|
||||
|
||||
<div>
|
||||
<div style="float: left; display: flex; align-items: center" >
|
||||
<a href='https://gitee.com/GXDE-OS/GXDE/stargazers'><img src='https://gitee.com/GXDE-OS/GXDE/badge/star.svg?theme=dark' alt='star'></img></a>
|
||||
<img src='https://gitcode.com/GXDE-OS/GXDE/star/badge.svg' alt='G-Star'></img>
|
||||
</div>
|
||||
<div style="float: right">
|
||||
<a href="./README.zh.md">中文版</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
## Welcome to GXDE OS Community
|
||||
|
||||
**[中文](/README.zh.md)**
|
||||
|
||||
GXDE OS is an Debian based Linux distro featuring GXDE Desktop Environment. It offers an elegant, beautifu, light weight and out-of-the-box experience.
|
||||
|
||||
### Classic and Extended Deepin DE Experience
|
||||
@@ -88,4 +97,7 @@ The author is online and hungry for support (nom nom~). Feeding might even get u
|
||||
|
||||
<p><img src="https://www.gxde.top/install/gf.jpg" style="border-radius: 4px;" ></p>
|
||||
|
||||
# ©2023~Now gfdgd xi
|
||||
|
||||
<span style="color: #E6004C; font-size: 20px"><b>©2023~Now gfdgd xi</b></span>
|
||||
|
||||
<div style="background: #E6004C; width: 100%; height: 3px;"></div>
|
||||
+12
-8
@@ -1,11 +1,14 @@
|
||||
<center><img src=new-logo-long.png width=300/></center>
|
||||
<hr>
|
||||

|
||||
|
||||
<div>
|
||||
<div style="float: left; display: flex; align-items: center" >
|
||||
<a href='https://gitee.com/GXDE-OS/GXDE/stargazers'><img src='https://gitee.com/GXDE-OS/GXDE/badge/star.svg?theme=dark' alt='star'></img></a>
|
||||
|
||||

|
||||
|
||||
|
||||
**[English](/README.md)**
|
||||
<img src='https://gitcode.com/GXDE-OS/GXDE/star/badge.svg' alt='G-Star'></img>
|
||||
</div>
|
||||
<div style="float: right">
|
||||
<a href="./README.md">English Version</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
## 简介
|
||||
@@ -87,5 +90,6 @@ Gitcode:https://gitcode.com/GXDE-OS
|
||||
|
||||
<p><img src="https://www.gxde.top/install/gf.jpg" style="border-radius: 4px;" ></p>
|
||||
|
||||
<span style="color: #E6004C; font-size: 20px"><b>©2023~Now gfdgd xi</b></span>
|
||||
|
||||
# ©2023~Now gfdgd xi
|
||||
<div style="background: #E6004C; width: 100%; height: 3px;"></div>
|
||||
|
||||
Vendored
+3
-2
@@ -1,4 +1,4 @@
|
||||
gxde (2026.07.11) UNRELEASED; urgency=medium
|
||||
gxde (2026.08.06) UNRELEASED; urgency=medium
|
||||
|
||||
* 新增 remmina 以解决远程问题
|
||||
* 改为安装 dde-printer
|
||||
@@ -25,8 +25,9 @@ gxde (2026.07.11) UNRELEASED; urgency=medium
|
||||
* 更改 gxde-desktop-extra 推荐依赖
|
||||
* 推荐安装 firmware-atheros | firmware-ath9k-htc
|
||||
* gxde-desktop-android 指定安装 spark-store 而不是可选安装 aptss
|
||||
* 添加推荐依赖 deepin-liferaft
|
||||
|
||||
-- gfdgd_xi <3025613752@qq.com> Sat, 11 Jul 2026 14:12:50 +0800
|
||||
-- gfdgd_xi <3025613752@qq.com> Thu, 06 Aug 2026 18:08:23 +0800
|
||||
|
||||
gxde (2024.10.20) UNRELEASED; urgency=medium
|
||||
|
||||
|
||||
Vendored
+1
@@ -50,6 +50,7 @@ Recommends: ${misc:Depends},
|
||||
fcitx5-pinyin-zhwiki,
|
||||
dde-cooperation,
|
||||
firmware-atheros,
|
||||
deepin-liferaft,
|
||||
Description: GXDE New Desktop Environment Extra - Next
|
||||
This is a meta package depends GXDE New Desktop Envrionment Extra.
|
||||
.
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 83 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 83 KiB |
+135
-57
@@ -1,68 +1,146 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
将 Gitee 上的 GXDE-OS 组织仓库镜像同步到 GitHub(GXDE-OS 组织)。
|
||||
|
||||
用法:
|
||||
python3 sync.py <gitee用户名> <gitee密码或Token> <github用户名> <githubToken>
|
||||
|
||||
流程:
|
||||
1. 通过 Gitee API v5 分页获取 GXDE-OS 组织下的全部仓库列表(带 token 失败时回退匿名)
|
||||
2. 多线程 clone --bare 拉取 Gitee 仓库
|
||||
3. 逐个 push --mirror 推送到 GitHub,失败自动重试并在结束时汇总报告
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import requests
|
||||
import threading
|
||||
import urllib.parse
|
||||
import urllib.request
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
|
||||
programPath = os.path.split(os.path.realpath(__file__))[0] # 返回 string
|
||||
dataHeaders = {
|
||||
"accept": "application/json"
|
||||
}
|
||||
pullUrl = "https://gitee.com/GXDE-OS/"
|
||||
pushUrl = [
|
||||
"https://@USER@:@PASS@@github.com/GXDE-OS/",
|
||||
"https://@USER@:@PASS@@gitcode.com/GXDE-OS/",
|
||||
"https://@USER@:@PASS@@atomgit.com/GXDE-OS/"
|
||||
]
|
||||
programPath = os.path.split(os.path.realpath(__file__))[0]
|
||||
cloneDir = os.path.join(programPath, "git-clone")
|
||||
orgName = "GXDE-OS"
|
||||
perPage = 100
|
||||
threadMax = 8
|
||||
|
||||
if (len(sys.argv) < 1 + len(pushUrl) * 2):
|
||||
print(f"请输入用于推送的账户和密码(需要 {len(pushUrl)} 组以推送不同的平台,提供顺序如下)")
|
||||
for i in pushUrl:
|
||||
print(f" {i}")
|
||||
exit(1)
|
||||
|
||||
# 读取参数
|
||||
userName = []
|
||||
password = []
|
||||
for i in range(1, len(sys.argv)):
|
||||
# 输入账户
|
||||
if (i % 2 == 1):
|
||||
userName.append(sys.argv[i])
|
||||
# 输入密码
|
||||
if (i % 2 == 0):
|
||||
password.append(sys.argv[i])
|
||||
def usage():
|
||||
print("用法: python3 sync.py <gitee用户名> <gitee密码或Token> <github用户名> <githubToken>")
|
||||
sys.exit(1)
|
||||
|
||||
def sync(i):
|
||||
global thread
|
||||
# 拉取代码进行同步
|
||||
if (not os.path.exists(f"{programPath}/git-clone")):
|
||||
os.makedirs(f"{programPath}/git-clone")
|
||||
print(f"======================> {pullUrl}/{i}")
|
||||
os.system(f"cd '{programPath}/git-clone' ; git clone --bare '{pullUrl}/{i}'")
|
||||
# 推送
|
||||
for j in range(len(pushUrl)):
|
||||
# git remote set-url origin
|
||||
gitUrl = pushUrl[j].replace("@USER@", userName[j]).replace("@PASS@", password[j]) + "/" + i
|
||||
os.system(f"cd '{programPath}/git-clone/{i}.git' ; git remote set-url origin '{gitUrl}'")
|
||||
os.system(f"cd '{programPath}/git-clone/{i}.git' ; git push --mirror")
|
||||
# 移除临时文件
|
||||
os.system(f"rm -rf '{programPath}/git-clone/{i}.git'")
|
||||
thread -= 1
|
||||
|
||||
data = requests.get("https://api.github.com/users/GXDE-OS/repos", headers=dataHeaders).json()
|
||||
repoList = []
|
||||
# 获取仓库列表
|
||||
for i in data:
|
||||
repoList.append(i["name"])
|
||||
# 多线程处理以提升速度
|
||||
thread = 0
|
||||
threadMax = 32
|
||||
for i in repoList:
|
||||
def apiGet(path, params):
|
||||
"""调用 Gitee API v5 的单个请求"""
|
||||
params["per_page"] = str(perPage)
|
||||
url = "https://gitee.com/api/v5" + path + "?" + urllib.parse.urlencode(params)
|
||||
req = urllib.request.Request(url, headers={"User-Agent": "GXDE-Sync/1.0"})
|
||||
with urllib.request.urlopen(req, timeout=30) as resp:
|
||||
return json.loads(resp.read().decode("utf-8"))
|
||||
|
||||
|
||||
def getGiteeRepos(token):
|
||||
"""分页获取 Gitee 组织下全部仓库的 path(URL 安全路径)
|
||||
|
||||
Gitee API 返回的 name 是仓库别名(可能含大写、中文或括号,如
|
||||
"CTranslate2"),不能直接用作 clone URL 的路径组件;path 才是 URL
|
||||
安全的仓库路径(如 "ctranslate2"),用它拼接 clone/push URL 才合法。
|
||||
"""
|
||||
repoList = []
|
||||
page = 1
|
||||
while True:
|
||||
time.sleep(0.1)
|
||||
if (thread < threadMax):
|
||||
threading.Thread(target=sync, args=[i]).start()
|
||||
thread += 1
|
||||
params = {"page": str(page)}
|
||||
if token:
|
||||
params["access_token"] = token
|
||||
data = apiGet(f"/orgs/{orgName}/repos", params)
|
||||
if not isinstance(data, list) or len(data) == 0:
|
||||
break
|
||||
repoList.extend([i["path"] for i in data])
|
||||
page += 1
|
||||
return repoList
|
||||
|
||||
|
||||
def runGit(args, cwd=None):
|
||||
return subprocess.run(args, cwd=cwd, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT, text=True)
|
||||
|
||||
|
||||
def syncRepo(name, pullUrl, pushUrl):
|
||||
repoDir = os.path.join(cloneDir, name + ".git")
|
||||
try:
|
||||
# 1. 从 Gitee clone --bare(重试 3 次)
|
||||
ok = False
|
||||
lastOut = ""
|
||||
for attempt in range(3):
|
||||
result = runGit(["git", "clone", "--bare", pullUrl + name, repoDir])
|
||||
if result.returncode == 0:
|
||||
ok = True
|
||||
break
|
||||
lastOut = result.stdout
|
||||
time.sleep(5)
|
||||
if not ok:
|
||||
print(f"[FAIL] clone 失败: {name}\n{lastOut}")
|
||||
return False
|
||||
|
||||
# 2. push --mirror 到 GitHub(重试 3 次)
|
||||
ok = False
|
||||
lastOut = ""
|
||||
for attempt in range(3):
|
||||
result = runGit(["git", "-C", repoDir, "push", "--mirror", pushUrl + name])
|
||||
if result.returncode == 0:
|
||||
ok = True
|
||||
break
|
||||
lastOut = result.stdout
|
||||
time.sleep(5)
|
||||
if not ok:
|
||||
print(f"[FAIL] push 失败: {name}\n{lastOut}")
|
||||
return False
|
||||
|
||||
print(f"[ OK ] 同步完成: {name}")
|
||||
return True
|
||||
finally:
|
||||
# 清理临时目录
|
||||
runGit(["rm", "-rf", repoDir])
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 5:
|
||||
usage()
|
||||
giteeUser, giteeToken = sys.argv[1], sys.argv[2]
|
||||
githubUser, githubToken = sys.argv[3], sys.argv[4]
|
||||
|
||||
pullUrl = f"https://{urllib.parse.quote(giteeUser)}:{urllib.parse.quote(giteeToken)}@gitee.com/{orgName}/"
|
||||
pushUrl = f"https://{urllib.parse.quote(githubUser)}:{urllib.parse.quote(githubToken)}@github.com/{orgName}/"
|
||||
|
||||
os.makedirs(cloneDir, exist_ok=True)
|
||||
|
||||
# 获取仓库列表:优先带 token,失败则回退到匿名(仅公开仓库)
|
||||
try:
|
||||
repoList = getGiteeRepos(giteeToken)
|
||||
except Exception:
|
||||
repoList = getGiteeRepos("")
|
||||
print(f"共获取到 {len(repoList)} 个仓库")
|
||||
if not repoList:
|
||||
print("未能获取仓库列表,退出")
|
||||
sys.exit(1)
|
||||
|
||||
failed = []
|
||||
with ThreadPoolExecutor(max_workers=threadMax) as pool:
|
||||
futures = {pool.submit(syncRepo, n, pullUrl, pushUrl): n for n in repoList}
|
||||
for future in as_completed(futures):
|
||||
if not future.result():
|
||||
failed.append(futures[future])
|
||||
|
||||
print("=" * 50)
|
||||
print(f"同步完成: 成功 {len(repoList) - len(failed)} / {len(repoList)}")
|
||||
if failed:
|
||||
print("以下仓库同步失败:")
|
||||
for name in failed:
|
||||
print(" -", name)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user