![ErrorEutopia ErrorEutopia](/assets/uploads/profile/741-profileavatar-1717584298452.png)
*
-
[原创]不许笑,否则我就自爆(参考末日菇) -
Linux打包流程 for wine Appimage首先,感谢一下linuxgame.cn提供的标准化打包工具
再感谢一下shinnku.com的Gal
(笑)
请让我把工具准备好:
一个Linux发行版(WSL也可以),我选用的是KaliLinux
Appimagetool(Github上有)以及来自linuxgame网站的打包工具 链接{自带旧版本appimagetool以及wine依赖,但我们不需要}
记得下好游戏并成功运行在本机wine环境上
以及打包的灵魂
wine (可从archlinux包仓库或者debian包仓库获得)
这里我们演示的是...... GINKA !
成品演示:
在开始之前,我觉得我得解释一下,Wine是什么
Wine (“Wine Is Not an Emulator” 的首字母缩写)是一个能够在多种 POSIX-compliant 操作系统(诸如 Linux,macOS 及 BSD 等)上运行 Windows 应用的兼容层。Wine 不是像虚拟机或者模拟器一样模仿内部的 Windows 逻辑,而是將 Windows API 调用翻译成为动态的 POSIX 调用,免除了性能和其他一些行为的内存占用,让你能够干净地集合 Windows 应用到你的桌面。
Wine 项目由 Bob Amstadt 于 1993 年发起,旨在寻求一种在 Linux 上运行 Windows 3.1 程序的办法。不久之后,Alexandre Julliard 开始接手领导 Wine 的开发,从此由他管理这个项目。 多年以来,随着 Windows API 和应用为了适应新硬件及软件而不断演变,Wine 也一直不断发展来支持新的特性,移植到更多其他系统,并且更加稳定,提供着更好的用户体验。
通过确立一个宏伟的目标,在 2008 年项目到达 v1.0 之前,Wine 一直稳健地持续了 15 年之久,那是第一个稳定版。 多个版本以后,虽然还有许多工作要做,但今天 Wine 仍然在活跃地开发着。 并且有大约数以百万人计的人们使用 Wine 在他们所选择的系统上运行 Windows 软件。
开放源代码和用户驱动的Wine 将会永远是自由软件。 大约一半的 Wine 代码由志愿者编写,其余部分由商业公司赞助。特别是 CodeWeavers,出售着一个 Wine 的支持版本。
Wine 也是高度依赖用户社区的。用户自愿贡献时间在我们的 Application Database 上分享技巧和他们程序的运行测试结果,在我们的 Bug-Tracker 上撰写 bug 报告提醒开发者问题所在,或者在论坛上回复问题。
(来自wine官网 链接)
(注:无论是最近苹果的游戏打包工具还是安卓的win模拟器,本质上都是wine哦~)关于APPIMAGE
简单.
AppImage的核心思想是一个应用程序 = 一个文件 。每个AppImage都包含应用程序以及应用程序运行所需的所有文件。换句话说,除了操作系统本身的基础组件,Appimage不需要依赖包即可运行。
可靠.
AppImage 格式是上游应用打包的理想选择,这意味着你可以直接从开发者那里获取软件,而不需要任何中间步骤,这完全符合开发者意图。非常迅速。
快速.
AppImage应用可以直接下载并且运行,无需安装,并且不需要root权限。
(来自appimage官网链接)打包流程
事实上没什么可以讲的,请看图:
这个是软件入口,gamux将它指向了文件"$(pwd)/usr/bin/games"(好像还有一种是指向.desktop桌面文件的)我们再来看看脚本内容
首先是config,这是一个配置文件
#!/bin/bash ###设置,根据需要修改### #游戏名称,可以随意起,请务必使用英文,游戏名切勿包含空格及其他符号 GAMUX_GAME_NAME="GINKA" #游戏所在文件夹的名称,默认为game GAMUX_GAME_BIN_DIR="game" #game文件夹中游戏执行文件 GAMUX_GAME_EXEC="run" #是否启用steam-runtime,0为不启用,1为启用。若不启用,可以删除当前目录的steam-runtime节省游戏体积 #非x86游戏不支持steam-runtime GAMUX_STEAMRUNTIME=0 #x86平台只支持在64位系统运行,不论游戏是32或64位 #arm平台只支持在arm64系统运行,不论armel、armhf或arm64的游戏 PLATFORM=amd64 ###定义变量部分,无需修改### HERE=$(cd "$(dirname "$0")";pwd) cd "${HERE}" GAMUX_GAME_READONLY="${HERE}/${GAMUX_GAME_BIN_DIR}" GAMUX_GAME_DIR="${HOME}/.local/share/gamux/${GAMUX_GAME_NAME}" GAMUX_GAME_DATA="${GAMUX_GAME_DIR}/data" GAMUX_GAME_DATA_TMP="${GAMUX_GAME_DIR}/${GAMUX_GAME_NAME}_gamux_mountdir" ###自定义部分,补充默认脚本的不足### function gamux_function1() { # if [ ! -d "${GAMUX_GAME_READONLY}/characters" ];then # tar zxvf "${HERE}/characters.tar.gz" -C "${GAMUX_GAME_DATA_TMP}" # fi return 10086 }
大佬写的注释挺详细的哈,我们应该向ta学习[笑]
基本上就是定义了游戏名称"GINKA",游戏所在文件夹"game",以及"game"文件夹中的可执行文件"run",其余的对于我们打包而言,意义不大(但是没有shell基础不要乱改哈)我们再来看看games
#!/bin/bash source "$(cd "$(dirname "$0")";pwd)/config" "${HERE}"/game_run fusermount -u -z "${GAMUX_GAME_DATA_TMP}" rmdir "${GAMUX_GAME_DATA_TMP}"
我们先来看看第一行#!/bin/bash
这是设定一个解释器,这里是bash,你也可以设置为dash,sh,zsh等
往下看,这是一个经典的当前路径获取代码,获取当前脚本文件的父目录,注意 $0 为脚本执行时传入的脚本路径名,翻译过来就是:打开并运行当前脚本文件父目录下的config脚本,这是配置了环境变量
(关于${HERE},请查看config文件的 ###定义变量部分,无需修改### 部分)
下面两行是挂载与垃圾清理,不重要(其实就是懒,毕竟已经23:01了)game_run文件,看名字就知道是干什么的了吧......
#!/bin/bash # figure out the absolute path to the script being run a bit # non-obvious, the ${0%/*} pulls the path out of $0, cd's into the # specified directory, then uses $PWD to figure out where that # directory lives - and all this in a subshell, so we don't affect # $PWD source "$(cd "$(dirname "$0")";pwd)/config" if [ ! -d "${GAMUX_GAME_DATA}" ];then mkdir -p "${GAMUX_GAME_DATA}" fi if [ ! -d "${GAMUX_GAME_DATA_TMP}" ];then mkdir "${GAMUX_GAME_DATA_TMP}" fi UNIONFS="unionfs_${PLATFORM}" "${HERE}"/${UNIONFS} -o big_writes,umask=0002,direct_io,auto_cache,sync_read,nonempty,uid=$(id -u),gid=$(id -g),cow "${GAMUX_GAME_DATA}"=RW:"${GAMUX_GAME_READONLY}"=RO ${GAMUX_GAME_DATA_TMP} #自定义代码 gamux_function1 ############################################################################################### #启动游戏 cd "${GAMUX_GAME_DATA_TMP}" if [ ${GAMUX_STEAMRUNTIME} -eq 0 ];then "${GAMUX_GAME_DATA_TMP}/${GAMUX_GAME_EXEC}" "$@" else "${HERE}/steam-runtime/run.sh" "${GAMUX_GAME_DATA_TMP}/${GAMUX_GAME_EXEC}" "$@" fi
接下来就是我自己写的脚本了,位于game文件夹中的run脚本,
#!/bin/sh export WINEHOME=$(pwd) export WINEPREFIX=$(pwd)/C #export WINEARCH=none export WINE=./bin/wine $WINE game/run.exe export WINEDLLPATH=$(pwd)/lib/wine/i386-windows/:$(pwd)/lib/wine/x86_64-windows/
非常简单的几句代码,分别设定了wine主目录的环境变量,wine c盘的环境变量,wine的架构(没有设定,为none),以及wine的可执行程序
$WINE game/run.exe (用wine运行game目录下的run.exe)
打包
打包之前要注意以下几点:
1.在此之前先运行一下games文件,检查game/C 文件夹是否有以下文件,没有就失败了(可以运行,但喜提 -1GB空间,你可以理解为这是优化)
2.一个game.png文件推荐256x256(不是也行)
3.编辑desktop
附赠desktop文件内容(以免损坏)[Desktop Entry] Name=GINKA Exec=games Icon=game Type=Application Categories=Game; Comment= Path= Terminal=false StartupNotify=false
开始打包
准备好appimagetool.appimage,在此打开终端,输入
ARCH=x86_64 ./appimagetool-x86_64.AppImage squashfs-root GINKA.Appimage
解释:
[ARCH=架构] [运行appimagetool] [参数1:所要打包的文件夹] [参数2:打包成什么]出现以下场景就成功了
作者的小声哔哔:写这个时候才21:20左右,现在是23:34了,现在脑子一团糟,文章后期也开始偷懒,有什么纰漏请见谅
-
[PDF/中文]マンガでわかる 系列学习漫画 (目前已收录14部)暗号密码,材料力学,电气数学,电子电路,流体力学,统计学回归分析,统计学,因子分析,微分方程,微积分,物理力学,线性代数,虚数与复数,顺序控制マンガでわかる暗号漫画密码 (三谷政昭,佐藤 伸一,ひのき いでろう,ウェルテ,李光东(译) 李纯(译) 刘敏亮(译)) (Z-Library).pdf
マンガでわかる材料力学漫画材料力学 (末益 博志,長嶋 利夫,円茂 竹縄,オフィスsawa,滕永红(译)) (Z-Library).pdf
マンガでわかる 電気数学漫画电气数学 (田中 賢一 ,松下 マイ,オフィスsawa,高丕娟(译)) (Z-Library).pdf
マンガでわかる電子回路漫画电子电路 (田中 賢一,高山 ヤマ,トレンド・プロ,单美玲(译)) (Z-Library).pdf
マンガでわかる流体力学漫画流体力学 (武居昌宏,松下マイ,オフィスsawa,高丕娟(译)) (Z-Library).pdf
マンガでわかる統計学 回帰分析編漫画统计学之回归分析 (高橋 信,井上 いろは,トレンド・プロ,张仲恒(译)) (Z-Library).pdf
マンガでわかる統計学漫画统计学 (高橋 信,トレンド・プロ,陈刚(译)) (Z-Library).pdf
マンガでわかる統計学 因子分析編漫画统计学之因子分析 (高橋 信,井上 いろは,トレンド・プロ,张仲恒(译)) (Z-Library).pdf
マンガでわかる微分方程式漫画微分方程 (佐藤 実, あづま 笙子, トレンド・プロ,乌日娜(译)) (Z-Library).pdf
マンガでわかる微分積分漫画微积分 (小島 寛之,十神 真,ビーコム,张仲恒(译)) (Z-Library).pdf
マンガでわかる物理 力学編漫画物理之力学 (新田 英雄,高津 ケイタ,トレンド・プロ,张芳(译)) (Z-Library).pdf
マンガでわかる線形代数漫画线性代数 (高橋 信,井上 いろは,トレンド・プロ,腾永红(译)) (Z-Library).pdf
マンガでわかる虚数・複素数漫画虚数和复数 (相知 政司,石野 人衣,トレンド・プロ,高丕娟(译)) (Z-Library).pdf
マンガでわかる シーケンス制御漫画顺序控制 (藤瀧和弘,高山ヤマ,トレンド・プロ,刘卫颖(译)) (Z-Library).pdf
-
[R18]幻想生物図鑑 20 (獣獣) 作者:Sharine(人丸) -
我要回归正轨的生活啦!时间总是流的很快,在不经意间,它奔疾向前--就这样,28天过去了...
这是我来到这个论坛的第28(或许是29?)天,在这些天里,我过得十分充实
但......
我终究是一个普通人,没有富二代般的生活,亦没有富二代的空闲时间.
就这样,看着我项目最后更改的时间,还是在去年11月份,至后,便再也没有动过......我并不是有钱人,也不是什么长生者.
我的时间精力有限,最近水帖也渐渐不上心了
唉...这何尝不是一种悲哀
我必须继续我的生活了!但,我有严重的社恐,甚至害怕到想想就想吐的地步了,也就是说--我不能外出打工
但还是得生活啊...我看着正在写的语句不通的帖子,看着反复强调不适合的,丑陋的画作,以及刺耳的音乐与嗓音,艺术方向是很难走通了......
或许......可以换个方向?
虽然我一开始的确有这个想法,但时间已经不允许了,再过几个月我就成年了,就算拿学校学习当挡箭牌我也只能再拖一年!(因为小学6年级至初中出了点我不愿说明的问题,导致我现在只能读专科学校)想法不能是想法了!
因为......作为一个自称"还算人类"的残缺人类,ta不能像常人一样:没钱,没本事,没学历,没背景,什么都没有,甚至听不懂人说话,无法理解其意思--这种人真不该存在啊!
算了,干脆一咬牙,走上了开发的道路......
什么都好,随便学点,我不想出门...我不想出门!!!
那年春节,口袋仅仅只有600元的我打算淘来一款电脑,无论几手!能用就行!
然后...我爸仿佛是古希腊掌管压岁钱的神一般来收钱,我钱刚好淘了一个久经沙场的Surface4,然后就是被我祂查账......最后估计是可怜我才买了一台电脑......非常卡......
这台电脑最初装得是windows11,最初几天还好,之后就跟抽风了似的--群死机,时不时蓝屏
窝一气之下!换了Linux(这又是另一个故事了,注:虽然之前没有电脑,但当时我是有Linux基础的,并且做了很多功课,小白们老老实实的用windows就好)
这样,我开发的生涯就算正式开始了:
C/C++ (包括Arduino的C语言) & Shell -> Python -> Lua -> Java -> {HTML/CSS} ->RenPyScript -> GDScript(这时确定了游戏开发的道路) -> C# -> Haskell -> CoffeeScript/Javascript/Vue......
每个都学过,每个都一知半解
这样是不行的......
完全比不过......
我需要更多的学习!
但我累了,非常累,精神状态也十分糟糕
于是便有了上面的"看着我项目最后更改的时间,还是在去年11月份,至后,便再也没有动过......
"
休息够了?怎么可能!
我现在依旧非常累,精神状态并没有太大的好转,但是......
我能怎么办呢?
就像最初仅仅只是"不喜欢人多的地方"会变成"遇见陌生人就会生理不适"一样一言难尽
我只能牺牲娱乐时间,一点一点减少
我只能背负"成年"之名,一步一步离去
直到我猝死卧榻,这是最好的解脱好累啊,好累啊,死神带走我
好累啊,好累啊,孟婆灌醉我
好累啊,好累啊,轮回超度我好想变回小时候啊,如果距离成年还远就好了,我还没玩够啊
如果我有能力就好,至少不用担心资金来源...
好烦...为什么要把担子压我身上...17年没停歇了...
小时看父母打架,直到离异
稍微长大就开始学习,在我什么都不知道的情况给我送学校了--我原本可以多玩几年
............
然后...黑暗不会结束,他只会越来越黑暗
好像越来越跑题了...简单来说:我预计今年也许明年,这破家庭的负担需要压在我身上一角,但是用我爸的话说:我这只"不会交流的废物"无法正常与人交流,为了生存,我需要一份室内工作
嘛,也不会有什么大影响,只能看成不成了......
不成的话......我就离死不远了
总之如果我长期没回来,不是账号忘了就是人没了
日后可能发言的频率会变低,直至消失(失败的话)
赌上生命吧,我讨厌这星球越来越离题的Error书
2024.02.03
-
快把浴霸关上!!!Daisuke-横田商会
-
[Arcaea/韵律源点]游戏官网
Altair - 沙野カモメ、you、spiLa
Arghena - Laur、Feryquitous
Defection - TeddyLoid
Jump - Rasmus Faber
Loveless Dress - かねこちはるParticle Arts (What A Shino Frenchcore Edit) - What A Shino、Virtual Self
-
[Linux]妈妈再也不用担心我背不会单词啦! -
甘城なつき 画集(还有其他的?一堆图片混在一起了搞不清楚,又或者这是她以前画风?)
-
[Ren'Py]Gal开发快速入门(Ren'py)-人物对话与图像人物对话与图像
首先下载好renpy引擎及其资源如果没有点此链接: ren-py资源
打开引擎后就是这个样子:
分支头:看的懂英语可以跳过此处
首先点击右下角的preferences
再点击中文(或者任意你喜欢的语言),后期教程以中文界面为主
分支尾:看的懂英语可以跳过此处
项目的创建
让我们返回到主菜单,点击"创建新项目"
点击"继续"
输入项目名称,我们这里叫:"Eutopia RenPy Journey"(名称不可以输入不再ASCII内的字符,关于ASCII,有兴趣自行搜索)
点击继续,以及后面两个都保持为默认,点击继续
稍等片刻后我们会返回到主菜单
箭头所指的便是我们新建的项目
让我们启动项目试试看
右下角是我们的游戏名称,左边是我们的游戏菜单(虽然现在很丑,但后面会美化的)
点击开始游戏试试看
点击两次后便会返回游戏主界面
Tips:接下来需要写代码了,请各位阁下做好心理准备!
Ok,相信大家都做好了准备,接下来就是愉快的代码编写时间!
先回到主界面,看到右上角一个名为script.rpy的脚本文件吗?
点击它,就可以跳转到......什么?你没跳转?那就跟着下面图片去配置吧!分支头2,可以跳转的跳过
自行选择一个你喜欢的编辑器吧!
分支尾2,可以跳转的跳过
这是文件中的代码:
# 游戏的脚本可置于此文件中。 # 声明此游戏使用的角色。颜色参数可使角色姓名着色。 define e = Character("艾琳") # 游戏在此开始。 label start: # 显示一个背景。此处默认显示占位图,但您也可以在图片目录添加一个文件 # (命名为 bg room.png 或 bg room.jpg)来显示。 scene bg room # 显示角色立绘。此处使用了占位图,但您也可以在图片目录添加命名为 # eileen happy.png 的文件来将其替换掉。 show eileen happy # 此处显示各行对话。 e "您已创建一个新的 Ren'Py 游戏。" e "当您完善了故事、图片和音乐之后,您就可以向全世界发布了!" # 此处为游戏结尾。 return
看上去复杂吗?其实就光凭这个注释就可以明白大半了
但是,我们还是一步一步来比较好-
首先,一个普通的gal需要角色
- Q:如何创建一个角色?
- A:define [随便一个字符串,用来代表你的角色,每个角色需要有一个唯一的字符串!
在下文用"e"表示
] = Character ("你的角色名")
Tips:编写代码时需要注意大小写,缩进,以及符号(必须为英文字符!) - Q:如何让角色说话?
- A:e "你想让角色说的话"
Tips:在Ren'py中游戏会从"label start:"开始,角色说话时注意缩进!最好以空格代替Tab键! - Q:我想显示我角色(laopo)的立绘,该怎么写?
- A:这个有点小麻烦,首先你需要一张图片,把它放在游戏项目的images目录,(名称最好英文全小写,根据机制,文件名在代码编写的时候会强制改为小写并剔除扩展名。譬如我有一张名为Mypic.png的图片,在写代码时需要全小写,也就是"mypic")show [文件名]
- Q:默认背景好难看,怎么更换背景?
- A:同上,只不过需要将show改为scene
代码实践
#在文本前面加"#"叫做注释,注释不会被引擎运行——所以你可以在这里夹杂私货[笑] #好吧,事实上这个是用来备忘的,一些复杂的项目的代码时间久了你有可能会记不住你写的是什么,这时注释就起到作用了
#创建一个角色Eutopia define t = Character ("Eutopia") #游戏开始的地方 label start: #这是一个背景,图片名称Utopia,别忘了小写 scene utopia #角色立绘,图片名称Eutopia show eutopia t "基本上就是这样" t "让我们运行看看" #游戏在此结束 return
左代码,右程序
图像的基本运用
- 头像设置
- 图像的移动与位置
- 头像设置
这是肥肠简单的一个办法:在image后面加一个side就行了,其余与立绘一样
image side eutopia="eutopia-h.png"
这里头像资源文件名叫eutopia-h.png,你也可以使用其他的,最好是透明png格式
2. 图像的移动与位置eutopia换装ing...
[renpy默认位置是中间,具体写法请查看前面立绘部分]
这时,如果我们想让她出现在左或者右边该怎么写呢?show eutopia at left #出现在左 show eutopia at right #出现在右
出现在左:
出现在右:
附页
Tips:文件夹结构图
images:存放图片
gui:存放游戏界面资源
audio:存放音频文件
tl:翻译文件
saves:游戏存档文件
cache:缓存文件完全不知道自己在干什么了哭死
-
-
[Linux中国合辑]使用 NFS 将 Git 提交记录显示成文件目录
2024-01-08 16:43
译自:https://jvns.ca/blog/2023/12/04/mounting-git-commits-as-folders-with-nfs/ 作者: Julia Evans 原创:LCTT https://linux.cn/article-16542-1.html 译者: guevaraya
大家好!某天,我突发奇想 —— 是否能把 Git 存储库制作成一个 FUSE 文件系统,然后把所有的提交记录做成文件夹呢?答案是肯定的!有 giblefs[1]、 GitMounter[2] 和用于 Plan 9 号的 git9[3]。
但在 Mac 上使用 FUSE 实在很烦人 —— 你需要安装一个内核扩展,但由于安全的原因,Mac OS 上安装内核扩展看起来越来越难了。此外,我还有一些想法,希望能用与这些项目不同的方式来组织文件系统。
因此,我想在 Mac OS 上尝试 FUSE 以外的挂载文件系统的方法会很有趣,因此我创建了一个名为 git-commit-folders[4] 的项目来做这个事。它可以同时使用 FUSE 和 NFS(至少在我的电脑上),WebDav 的实现起来还有点问题。
这个项目很有实验性(我不确定这究竟是一个有用的软件,还是一个思考 Git 如何工作的有趣玩具),但写起来很有趣,我自己也很喜欢在小型存储库中使用它,下面是我在写这个项目时遇到的一些问题。
目标:像文件夹一样显示提交记录我做这个事的主要目的是给大家一些启发:Git 核心是如何运行的。总结来说,Git 提交记录实际上和文件夹非常类似 —— 每个 Git 提交都包含一个目录,其中 列出了文件[5],这个目录也可以有子目录,依此类推。
只是为了节省磁盘空间,Git 提交实际上并不是以文件夹的形式实现的。
而在 git-commit-folders,所有的提交记录实际上看起来就是一个文件夹,如果你想浏览历史提交记录,你可以像浏览文件系统一样浏览它们!例如如果你像查看我的博客的初始提交记录,你可以如下操作:
$ ls commits/8d/8dc0/8dc0cb0b4b0de3c6f40674198cb2bd44aeee9b86/ README
其他之后的提交记录,如下:
$ ls /tmp/git-homepage/commits/c9/c94e/c94e6f531d02e658d96a3b6255bbf424367765e9/ _config.yml config.rb Rakefile rubypants.rb source
分支是符号链接
通过 git-commit-folders 挂载的文件系统中,提交是唯一真正的文件夹 —— 其他一切(分支、标签等)都是提交记录的符号链接。这反映了 Git 底层的工作方式。
$ ls -l branches/ lr-xr-xr-x 59 bork bazil-fuse -> ../commits/ff/ff56/ff563b089f9d952cd21ac4d68d8f13c94183dcd8 lr-xr-xr-x 59 bork follow-symlink -> ../commits/7f/7f73/7f73779a8ff79a2a1e21553c6c9cd5d195f33030 lr-xr-xr-x 59 bork go-mod-branch -> ../commits/91/912d/912da3150d9cfa74523b42fae028bbb320b6804f lr-xr-xr-x 59 bork mac-version -> ../commits/30/3008/30082dcd702b59435f71969cf453828f60753e67 lr-xr-xr-x 59 bork mac-version-debugging -> ../commits/18/18c0/18c0db074ec9b70cb7a28ad9d3f9850082129ce0 lr-xr-xr-x 59 bork main -> ../commits/04/043e/043e90debbeb0fc6b4e28cf8776e874aa5b6e673 $ ls -l tags/ lr-xr-xr-x - bork 31 Dec 1969 test-tag -> ../commits/16/16a3/16a3d776dc163aa8286fb89fde51183ed90c71d0
这个并不能完全呈现 Git 的所有工作机理(相比简单的类似文件夹的提交,还有很多复杂的细节),但是我希望大家对“每个提交如同一个文件夹,里面有你的旧版本代码”有一个直观的认识。
这么做有什么好处呢?在我深入介绍它的实现之前,我想说下为什么把 Git 提交记录变成拥有文件夹的文件系统很有用。我的很多项目最终都没有真正使用过(比如 dnspeep[6]),但我发现自己在做这个项目的时候确实使用到了一些。
目前为止我发现主要用处是:
查找已经删除的函数 - 可以用 grep someFunction branch_histories/main/*/commit.go 查找它的旧版本 快速查看其他分支的一个文件并从其拷贝一行,如 vim branches/other-branch/go.mod 在每个分支中搜索某个函数,如 grep someFunction branches/*/commit.go
所有这些操作都通过提交记录的符号链接,来替代提交记录的直接引用。
这些都不是最有效的方法(你可以用 git show 和 git log -S 或者 git grep 来完成类似操作),但是对我个人来说,我经常忘记 Git 语法,而浏览文件系统对我来说更简单。git worktree 还允许你同时签出多个分支,但对我来说,为了看一个文件而设置整个工作树感觉很奇怪。
接下来我想谈谈我遇到的一些问题。
问题 1: 用 WebDav 还是 NFS?Mac OS 原生支持的两个文件系统是 WebDav 和 NFS。我说不出那个更新容易实现,所以我就索性尝试两个都支持。
起初,WebDav 的实现看起来更容易一些,在 golang.org/x/net[7] 上有一个 WebDav 实现[8],这个很好配置。
但这个实现不支持符号链接,我想可能原因是它用的是 io/fs 接口,而 io/fs 还不支持 符号链接[9]。不过看起来正在进行中。所以我放弃了 WebDav,而决定重点放在 NFS 实现上了,用 go-nfs[10] NFSv3 的库文件来实现。
有人也提到了 Mac 上的 FileProvider[11],我还没有深入了解这个。
问题 2: 如何确保所有的实现保持一致?我已经实现了三个不同的文件系统(FUSE、NFS 和 WebDav),但对我来说还是没搞清楚如何避免大量的重复代码。
我的朋友 Dave 建议写一个核心实现,然后写一个适配器(如 fuse2nfs 和 fuse2dav)来转换成 NFS 和 WebDav 版本。这个看起来需要我着手实现三个文件系统的接口:
对应 FUSE 的 fs.FS 对应 NFS 的 billy.Filesystem 对应 WebDav 的 webdav.Filesystem
因此我把所有的核心逻辑放到 fs.FS 接口上,然后写两个函数:
func Fuse2Dav(fs fs.FS) webdav.FileSystem func Fuse2NFS(fs fs.FS) billy.Filesystem
所有的文件系统都比较类似,因此转换起来不是很难,但就是有大量的烦人的问题需要修复。
问题 3: 我不想罗列所有的提交记录怎么办一些 Git 存储库有成千上万的提交记录。我的第一个想法是如何让 commits/ 看起来是空的,这样就可以如下展示:
$ ls commits/ $ ls commits/80210c25a86f75440110e4bc280e388b2c098fbd/ fuse fuse2nfs go.mod go.sum main.go README.md
因此所有的提交记录可以直接查看,但是又不能罗列它们。这个对文件系统是一个奇怪的事情,实际上 FUSE 可以做到。但我在 NFS 上无法实现。我认为这里的原因是,如果你告诉 NFS 某个目录是空的,它就会认为该目录实际上是空的,这是合理的。
我们最终是这样处理的:
按照 .git/objects 的方式,以前两个字符组织管理提交记录(因此 ls commits 会显示 0b 03 05 06 07 09 1b 1e 3e 4a),但这样做会分为两层,这样 18d46e76d7c2eedd8577fae67e3f1d4db25018b0 则为
commits/18/18df/18d46e76d7c2eedd8577fae67e3f1d4db25018b0
开始只罗列一次所有的已经打包的提交哈希,将它们缓存在内存中,然后后面仅更新稀疏对象。主要思路是版本库中几乎所有的提交都应该打包,而且 Git 不会经常重新打包提交这个看起来在拥有百万提交记录的 Linux 内核的 Git 存储库上似乎效果不错。在我的机器上实测它初始化大概需要一分钟,之后只需快速增量更新即可。
每个提交哈希只有 20 个字节,因此缓存 1 百万个提交哈希也不是很大,大约 20MB。
我认为更聪明的做法是延迟加载提交列表 —— Git 会按提交 ID 对其打包文件进行排序,所以你可以很容易地进行二叉树搜索,找到所有以 1b 或 1b8c 开始的提交。我用的 Git 库[12] 对此并不支持,因为罗列出来 Git 存储库所有的提交记录确实一个奇怪的事情。我花了 几天时间[13] 尝试实现它,但没有达到我想要的性能,所以就放弃了。
问题 4: 不是目录我常遇到下面这个错误:
"/tmp/mnt2/commits/59/59167d7d09fd7a1d64aa1d5be73bc484f6621894/": Not a directory (os error 20)
这起初真的把我吓了一跳,但事实证明,这只是表示在列出目录时出现了错误,而 NFS 库处理该错误的方式就是显示 “Not a directory”(不是目录)。这个错误遇到了很多次,我需要每次跟踪这个错误的根源。
有很多类似错误。我也遇到 cd: system call interrupted,令人沮丧的是,但最终也只是程序中的其他错误。
我意识到终极大法是用 Wireshark 查看 NFS 发送和接受的数据包,很多问题便可迎刃而解。
问题 5: inode 编号在开始的时候我不小心将所有的文件夹的 inode 设为 0。这很糟糕,因为如果在每个目录的 inode 都为 0 的目录上运行查找,它就会抱怨文件系统循环并放弃,这个也是符合逻辑的。
我通过定义一个 inode(string) 来修复这个问题,通过散列字符串来获取 inode 编号,并使用树 ID / blob ID 作为散列字符串。
问题 6: 过期文件句柄我一直遇到这个“Stale NFS file handle”(过期文件句柄)错误。问题是,我需要获取未知的 64 字节 NFS “文件句柄”,并将其映射到正确的目录。
我使用的 NFS 库的工作方式是为每个文件生成一个文件句柄,并通过固定大小的缓存来缓存这些引用。这对小型存储库来说没问题,但是如果对于拥有海量的文件的存储库来说,由于缓存就会溢出,就会导致“stale file handle” 错误。
这仍然是个问题,我不知道如何解决。我不明白真正的 NFS 服务器是如何做到这一点的,也许它们只是有一个非常大的缓存?
NFS 文件句柄占用 64 个字节(不是比特),确实很大,所以很多时候似乎可以将整个文件路径编码到句柄中,根本不需要缓存。也许我会在某个时候尝试实现这一点。
问题 7: 分支历史branch_histories/ 目录目前仅罗列对应分支的最近 100 个提交记录。我不知道该怎么做,如果能以某种方式列出分支的全部历史就更好了。也许我可以使用 commits/ 目录中类似的子文件夹技巧。
问题 8: 子模块Git 存储库有时包含了子模块。由于目前我对子模块的理解还不深入,我先忽略它吧。因此这个算是一个问题。
问题 9: NFSv4 是否更好?我构建这个项目使用的是 NFSv3 库,因为我当时只能找到一个 NFSv3 的 Go 库文件。可当我搞完的时候才发现了一个名叫 buildbarn 的项目里有 NFSv4 服务器[14]。有没有可能用它会更好一些?
我不知道这样做有什么问题,或者用 NFSv4 有哪些优点?我还有点不确定是否要使用 buildbarn NFS 库,因为不清楚他们是否希望其他人使用它。
就这些吧之前已经解决了很多问题我都忘记了,这是我目前能回想起来的。我未来有可能解决或根本解决不了 NFS 的“过期文件句柄” 错误,或者“在 Linux 内核的存储库上启动需要 1 分钟”的问题,就这样吧。
感谢我的朋友 vasi[15],他给我了很多文件系统方面的帮助。
(题图:DA/d22b1c01-e80a-4529-b88a-419ceef74b5e)
via: https://jvns.ca/blog/2023/12/04/mounting-git-commits-as-folders-with-nfs/
作者:Julia Evans[16] 选题:lujun9972[17] 译者:guevaraya[18] 校对:wxy[19]
本文由 LCTT[20] 原创编译,Linux中国[21] 荣誉推出
[1]: https://github.com/fanzeyi/giblefs [2]: https://belkadan.com/blog/2023/11/GitMounter/ [3]: https://orib.dev/git9.html [4]: https://github.com/jvns/git-commit-folders [5]: https://jvns.ca/blog/2023/09/14/in-a-git-repository--where-do-your-files-live-/#commit-step-2-look-at-the-tree [6]: https://github.com/jvns/dnspeep [7]: http://golang.org/x/net [8]: https://pkg.go.dev/golang.org/x/net/webdav [9]: https://github.com/golang/go/issues/49580 [10]: https://github.com/willscott/go-nfs/ [11]: https://developer.apple.com/documentation/fileprovider/ [12]: https://github.com/go-git/go-git [13]: https://github.com/jvns/git-commit-folders/tree/fast-commits [14]: https://github.com/buildbarn/bb-adrs/blob/master/0009-nfsv4.md [15]: https://github.com/vasi [16]: https://jvns.ca/ [17]: https://github.com/lujun9972 [18]: https://github.com/guevaraya [19]: https://github.com/wxy [20]: https://github.com/LCTT/TranslateProject [21]: https://linux.cn/article-16542-1.html?utm_source=rss&utm_medium=rss
-
[机翻]Onscripter脚本文档目录游戏开始/重置/退出
*define 标签表示定义块的开头 *start 标签表示程序块的开始 game 结束定义块并执行游戏 reset 重置游戏 definereset 强制完全重置脚本 end 结束游戏和关闭窗口 语法标记
***** 标签的前缀 ; 注释的前缀 : 在一行上写入和执行多个命令 % 数值变量的前缀 $ 字符变量的前缀 ? 数组变量的前缀 ~ jumpf/jumpb 的目标点 ` | 允许 1 字节字符显示 | / 忽略换行符 文本窗口
setwindow 设置文本窗口和字符显示属性 setwindow2 修改文本窗口出现 textoff 隐藏文本窗口 texton 显示文本窗口 windoweffect 指定文本窗口的效果 erasetextwindow 在效果运行时切换文本显示 文本显示
defaultfont 指定默认字体 !s 指定字符显示速度 # 更改字符颜色 textclear 清除显示的文本 locate 在不更改文本窗口位置的情况下更改字符的位置 puttext 写出一些小指示(例如,在 if 语句之后) br 在显示的文本中插入回车符 textspeed 更改文本显示速度 点击等待
@ 输入单击等待状态 **** 进入回车等待状态 clickstr 点击指定字符串后进入点击等待状态 _ 忽略下一次点击 linepage 等待行尾的点击 clickvoice 单击时播放指定声音 autoclick 即使没有点击,也能继续进步 click 输入单击等待状态,而不显示单击等待光标 光标
setcursor 指定单击等待光标的图形文件 abssetcursor 锁定鼠标位置并指定用于单击等待光标的图形文件 mousecursor 为常规鼠标光标指定图形文件(目前不推荐) 图像显示
transmode 更改 Alpha Blend 透明模式 underline 设置站立图像的地线 bgalia 设置非标准背景的参数 humanz 指定精灵和站立图像的重叠优先级 windowback 在与站立图像相同的位置插入文本窗口 bg 设置背景图片 ld 设置站立图像 cl 擦除指定的站立图像 tal 修改站立图像透明度 print 显示所有图像,删除不应存在的图像 lsp 将 Sprite 加载到内存中,以便显示它 lsph 将 Sprite 加载到内存中,覆盖最后一个无效的 Sprite csp 从内存中删除 Sprite vsp 切换精灵显示(必须先通过 LSP/LSPH 加载) spstr 通过重写文本精灵来更改复杂按钮上的文本字符串 msp 更改 Sprite 位置(方法 1) amsp 更改 Sprite 位置(方法 2) cell 手动指定精灵的单元格 blt 瞬间将图像快速传输到屏幕上 ofscpy 将 BLT 绘制的图像传输到屏幕外缓冲区 repaint 重绘屏幕 图像效果
effect 指定效果 effectblank 指定效果结束后的等待时间 effectcut 在选择对话框期间切换效果运行时 quake 在屏幕上产生地震效果 quakex 在屏幕上产生水平抖动效果 quakey 在屏幕上产生垂直晃动效果 monocro 使屏幕单色 nega 使屏幕为负片 字符/数字/条形显示
% 显示数值变量的内容 $ 显示字符变量的内容 bar 创建和显示条形图 barclear 清除条形显示 prnum 初始化数字标签 prnumclear 清除数字标签 音乐/特效播放
cdfadeout 指定 CD-DA 淡出时间 mp3fadeout 指定 MP3 淡出时间 play 播放 CD-DA 或 MIDI playonce 仅播放一次指定的 CD-DA 轨道或 MIDI 文件 playstop 停止 CD-DA 或 MIDI 播放 wave 仅播放一次 WAV 文件 waveloop 循环 WAV 文件播放 wavestop 停止 WAV 文件播放 mp3 只播放一次指定的MP3文件 mp3loop 循环 MP3 文件播放 mp3save 如果游戏在 MP3 播放过程中保存,则在加载游戏时,请在该位置恢复播放 dsound 声明您正在使用 DirectSound(在最新版本中不是必需的) dwave 仅使用DirectSound播放一次WAV文件 dwaveloop 使用 DirectSound 循环 WAV 文件 dwavestop 在 DirectSound 中停止 WAV 文件播放 dwaveload 将WAV文件加载到内存中 dwaveplay 播放一次内存中已有的 WAV 文件 dwaveplayloop 循环播放内存中已有的 WAV 文件 stop 停止所有音乐播放 短片播放
avi 播放 AVI 文件 mpegplay 播放 MPEG 文件 选择
selectcolor 指定选择文本颜色 selectvoice 指定要在选择时播放的声音 select 设置选择 selgosub 设置跳转到子例程的选项 selnum 显示所选选项并将其结果添加到指定的数值变量中 跳
goto 跳转到指定标签 skip 跳过接下来的 X 行脚本 gosub 调用子例程 return 从子例程返回 jumpf 跳转到下一个 ~ 符号的位置 jumpb 跳转到最后一个 ~ 符号的位置 点击时跳转到旗帜
trap 左键跳转到指定标签 lr_trap 左键或右键跳转到指定标签 trap2 设置「跳到下一个选择」时,左键跳转到指定标签 lr_trap2 设置「跳到下一个选项」时,左键或右键跳转到指定标签 图像按钮
btndef 将按钮图形文件加载到内存中。 btn 将图像初始化为按钮(方法 1) btnwait 显示图像按钮并将其置于单击等待状态(方法 1) btnwait2 显示图像按钮并将其置于单击等待状态(方法 2) spbtn 将 Sprite 指定为图像按钮 getbtntimer 获取自我们输入 btnwait 到数值变量以来已经过去了多少时间 btntime 为图像按钮功能创建时间限制 exbtn 创建复杂(复合)按钮 exbtn_d 指定使用复杂按钮时的光标行为 等待/计时器
!d 等待指定时间 !w 等待指定时间,忽略点击 delay 导致时间延迟(方法 1) wait 导致时间延迟(方法 2) resettimer 复位内部定时器 waittimer 等到指定时间(按内部时间计算)过去 gettimer 获取内部定时器的值 spwait 等到指定的精灵编号的动画结束 变量操作/计算
stralias 创建字符串别名/文件名别名 numalias 创建数值变量别名 intlimit 设置数值变量的最大值和最小值 dim 声明数组变量 mov 将值加载到数值或字符变量中 mov3~mov10 将值加载到多个数值或字符变量中 movl 将整行加载到数组中 add 添加数字 sub 减去数字 inc 增量变量 dec 递减变量 mul 乘以数字 div 除数 mod mod(请注意,这是一个程序化的mod,而不是真正的modulo) rnd 创建随机数(方法 1) rnd2 创建随机数(方法 2) itoa 将数值变量更改为字符或字符串 atoi 将字符变量更改为数字 条件表达式/循环
if if(conditional statement) { 命令 } notif 如果 (!(条件语句)) { 命令 } cmp 比较字符变量 fchk 检查指定的镜像标签是否已读取 lchk 检查指定的标签是否已读取 for~next 循环命令 break 跳出 for 循环 右键单击功能
rmenu 初始化并在右键单击时显示菜单 menusetwindow 初始化右键菜单的窗口 savename 指定右键菜单的保存文件名 menuselectcolor 指定右键单击菜单文本的颜色 menuselectvoice 为右键单击菜单指定系统声音 rlookback 右键单击后跳转到日志模式 roff 忽略右键单击 rmode 打开和关闭右键单击的可用性 日志模式
lookbackbutton 指定图像按钮以进入日志模式 lookbackcolor 为日志模式指定文本颜色 lookbackvoice 在日志模式下向上翻页/向下翻页时播放声音 lookbackflush 清除日志模式 跳过模式
kidokuskip 打开跳过模式 mode_wave_demo 即使指定了「跳到下一个选择」,也可以播放WAVE文件 skipoff 关闭“跳过模式” 文件访问日志/全局变量
filelog 尝试创建/使用文件访问日志 globalon 允许使用全局变量 labellog 标签访问日志 保存/加载
savenumber 修改保存次数限制 savegame 将游戏保存在指定的保存文件中 loadgame 从指定的保存文件加载游戏 savefileexist 检查保存文件是否存在 saveon 进入保存对话框 saveoff 从“保存”对话框中转义 附加功能
mesbox 创建消息框 inputstr 等待玩家输入角色(方法1) input 等待玩家输入角色(方法2) clickpos 点击获取光标坐标 systemcall 执行右键单击菜单中列出的操作 模式自定义函数
automode 允许使用自动模式 automode_time 在自动模式下指定未播放声音时的字符延迟时间 defvoicevol 设置语音的默认音量(新命令) defsevol 设置 SFX 的默认音量 defmp3vol 设置 MP3 文件的默认音量 mode_saya 允许使用同人游戏“沙耶~不道德迷宫~”中的模式。 mode_ext 允许使用“Gin'iro”使用的自动模式 mode800 将屏幕尺寸设置为 800x600 插件/档案
soundpressplgin 通过插件/ dll加载压缩音频功能(现在只需使用DirectSound命令即可) spi 通过插件/DLL 加载压缩图像功能 arc 使用指定的存档 nsa 打开 NSA 存档访问权限 nsadir 指定 NSA 存档所在的文件夹 安慰
versionstr 修改版本字符串 caption 修改窗口标题 数据解析
date 获取年、月和日 time 按小时、分钟和秒获取当前时间 savetime 获取保存指定保存文件的日期 getversion 获取当前 NScripter 生成的版本字符串 getreg 从 Windows 注册表中获取值 getini 读取 INI 文件 菜单栏函数
killmenu 擦除菜单栏 defaultspeed 在菜单栏上指定可选择的文本显示速度 !sd 使用 defaultspeed 命令传递的文本显示速度 menu_full 进入全屏模式 menu_window 进入窗口模式 menu_click_def 进入默认菜单栏操作模式 menu_click_page 进入菜单随每页显示的模式 系统定制功能
*customsel 与 CSEL 命令交互的标签 textgosub 通常用于在系统自定义中的单击等待状态期间提供弹出文本 csel 在系统自定义中描述选项 cselbtn 创建带有选择文本的按钮 getcselnum 获取 CSEL Choice 分支机构的数量 cselgoto 跳转到 CSEL 创建的标签 textbtnwait 输入 CustomWait 定义的 Click Wait 状态 selectbtnwait 输入 customsel 定义的 Click Wait 状态 texec 在等待重新编辑时删除文本 getcursorpos 获取文本光标的当前位置 -
[touhou/东方/车万]最全音乐集!https://cloud.lilywhite.cc/s/4ZUW?path=%2F东方Project%2F官方音乐%2F上海アリス幻樂団 ZUN
车万人必备莉莉云下载站!(chrome内核偶尔加载不出来很正常)
-
[耳机警告/噪声音乐/实验电子/Extratone]彻底疯狂!!!!!!!!! (BPM300-1500?)
好好写?不可能~下次一定!
ahdufhafajhsdvbhvrsetgvsvertstsevrtsvrgsvrrvtvserfsv
啊啊啊啊啊啊啊啊啊啊啊啊啊,我不要点外卖!!!!!!!!!!!!!!!!!!!!!!
dshjdsjkjnkdknjkhusdfrgsgtrsghhtgrg
彻底疯狂!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -
[诗岸]纵使某一刻被世界所遗弃 - 暮色、诗岸
[00:00.0]作词: 暮色
[00:00.706]作曲: 暮色
[00:01.413]世界呀
[00:03.424]许下的 愿望
[00:05.408]从来没曾实现呢
[00:08.402]请不要 就这样 把我丢下
[00:15.414]
[00:24.671]好像被
[00:26.654]全世界 遗弃了
[00:31.168]就连时间 都停住不走
[00:36.405]
[00:36.905]好像有
[00:39.912]很多事 在心里面藏着
[00:42.661]可是没人 再愿意去听它们了
[00:47.657]
[00:47.913]纵使 好像努力抓住什么
[00:53.402]但是什么 都不肯做停留
[00:59.162]
[00:59.421]或许 世界还在忙着转动
[01:04.666]所以没空 再次照顾到我
[01:09.668]
[01:10.162]好想知道 世界 是从哪一刻 停止转动
[01:15.419]我只好 努力 自顾自地 止住伤痛
[01:20.906]所有往事 所有的人 都只是 擦肩而过
[01:26.920]毁灭之后 还有谁 记得我
[01:32.412]
[01:45.172]好像一切都变得没有道理
[01:48.158]停止用逻辑去思考事情
[01:51.165]我想时间也放弃了这里
[01:53.920]一会快 一会慢 是什么东西
[01:56.914]爱恨情仇都变得没有了意义
[02:02.162]就让它 埋葬这废墟
[02:06.908]
[02:07.162]既然如此 世界 是否能听到 我的哀求
[02:12.665]快回到 那原来 熟悉的 规律之中
[02:18.415]所有心愿 所有的事 都不过 是耳旁风
[02:24.165]我只希望 一切 自然地过
[02:29.663]
[02:30.161]好想知道 世界 是从哪一刻 停止转动
[02:35.408]我只好 努力 自顾自地 止住伤痛
[02:41.156]所有往事 所有的人 都只是 擦肩而过
[02:46.913]毁灭之后 还有谁 记得我
[02:52.663]
[02:52.908]我的努力 我的情绪 都无所谓啦
[02:58.656]世界啊 对我好一点 好吗诗岸人设:
[图片来自萌娘百科]
诗岸声源:Warma
-
[网易云]优雅永不言败~纯音乐与Artcore&J-Trance{或许其他什么东西?}(断续更新) -
[原创]Last Memoris Betas.Op1-ErrorEutopia -
[rotaeno/旋转音律]Inverted World - ARForest.mp3 -
嘘,偷偷打包的Shinnku网页应用,姐姐应该不会生气吧 [获得称号:Chrome战士]bbsLinux
bbsWindows //这个是顺手的,win什么的一点也不会,运行不了就开摆
下载站Linux
下载站Windows
一切只是为了方便
1.nw.js yyds
2.win什么的就开摆
3.获得称号:Chrome战士
4.没有代码,就一配置文件
5.没有第6条
6.信宅神,得永生
7.紫老太婆我ijfdgnsrtijg-9';]][h':KOx 9o [lejirges2024-01-07注:因为由于某些傻逼脚本小子导致的高流量以及持续不断接近9个月的ddos攻击, 姐姐不得不启用人机验证,而后我打包的nwjs App因为软件缺陷无法过验证 !(仅限下载站)
Error表示:学了一点技术就搞破坏,并不是什么好选择...... -
[Linux]AIR.Appimage && ATRI.Appimage && GINKA.Appimage && 少女领域.Appimage && 我所希翼的未来.Appimage