الوثائق
تاريخ المشروع
لقطات مشروع محلية متوافقة مع Git، والاختلافات الهيكلية، والفروع القابلة للمراجعة، ونسخ GitHub الاختياري.
مترجم تلقائيًا من الإنجليزية. عرض الأصل بالإنجليزية
نسخة العمل والتاريخ
سجلات SQLite الخاصة بالتطبيق هي نسخة عمل المشروع الحالية. @cadcamfun/vcs يخزن النقط والأشجار والالتزامات والمراجع المتوافقة مع Git من خلال الواجهة الخلفية للكائن المحقون؛ يستمر السايدكار في الحفاظ على الواجهة الخلفية في SQLite. تعمل عمليات السجل محليًا بدون حساب Git القابل للتنفيذ أو حساب GitHub.
يلتقط الالتزام لقطات للمشروع وموارد التصميم/التصنيع ذات الصلة به. تشير الفروع إلى الالتزامات، بينما يحدد HEAD الفرع المسحوب. تتواجد جداول إصدار الموارد مع هذا المحفوظات على مستوى المشروع؛ نسخة الرسم والتزام المشروع لهما نطاقات مختلفة.
الالتزام وسير العمل فرع
- يقرأ
GET /api/projects/:id/vcs/statusلرؤية الفرع الحالي، HEAD، والمسارات المتغيرة. - إنشاء فرع مع
POST /vcs/branches، ثم التحقق من ذلك معPOST /vcs/checkout. ترتبط مسارات الفروع هنا ببادئة واجهة برمجة التطبيقات (API) الخاصة بالمشروع. - تحرير موارد المشروع والالتزام بها
POST /vcs/commitورسالة غير فارغة. - فحص
GET /vcs/logوGET /vcs/diff. يدعم السجل المراجعة والحد والمسار الاختياري المتعقب. - افتح طلب سحب المشروع، وراجع تغييراته الهيكلية، ثم ادمجه بعد حل المراجعات أو التعارضات المحظورة.
إن الخروج والاستعادة والعمليات التي تحرك فرع العمل ترفض نسخة عمل قذرة عند الاقتضاء. تسجل عملية الاستعادة التزامًا جديدًا يمثل المحتوى السابق، ويقتصر اختياريًا على المسارات المحددة. إنه يحافظ على التاريخ اللاحق بدلاً من إعادة كتابته.
محتويات اللقطة
project.json
drawings/<id>.json
components/<id>.json
toolpaths/<id>.json
materials/<id>.json
tools/<id>.json
machine-configs/<id>.json
costs/<id>.json
.cadcamfun/workflows/<name>.yml يبقي ملف JSON واحد لكل كيان التغييرات غير ذات الصلة منفصلة. تتضمن اللقطة عناصر المكتبة المشار إليها بواسطة مسارات الأدوات وتقديرات تكلفة الإنتاج حتى تتمكن بيانات التصنيع المستعادة من الاحتفاظ بتبعياتها. تقتصر معرفات الكيانات المستخدمة كأسماء ملفات على الأحرف الآمنة والأرقام والشرطات السفلية والواصلات، بحد أقصى 128 من الأحرف.
يتم فرز مفاتيح JSON بشكل متكرر وتستخدم الملفات طباعة جميلة مستقرة مع سطر جديد نهائي. المصفوفات تحتفظ بترتيبها. يمكن أن تنتقل الملفات النصية الإضافية باستخدام لقطة على مستوى الحزمة؛ تقبل نقطة نهاية الالتزام العامة الملفات الإضافية فقط ضمن .cadcamfun/workflows/ باستخدام اسم ملف YAML آمن.
تستخدم الكائنات بايت تنسيق الكائن السائب الخاص بـ git للبايت، لذا تتطابق معرفات الكائنات مع تلك المحسوبة بواسطة git. إدخالات الشجرة هي إما ملفات (mode 100644) أو الدلائل (الوضع 40000). يسجل توقيع الالتزام الاسم والبريد الإلكتروني ووقت Unix بالثواني و +hhmm/-hhmm إزاحة. يتم تخزين الفروع تحت refs/heads/، والفرع الافتراضي للمشروع هو main (packages/vcs/src/object.ts, repository.ts).
فرق ودمج الدلالات
يحسب المستودع قاعدة الدمج، ويتعامل مع الجوانب غير المتغيرة مباشرة، وينفذ عمليات دمج هيكلية ثلاثية الاتجاهات لـ JSON المتغيرة. يمكن دمج تعديلات خصائص الكائن المستقلة دون تعارض. يتم الإبلاغ عن التعديلات المتزامنة غير المتوافقة على نفس العدد أو المصفوفة من خلال مؤشرات JSON؛ لا يتم دمج المصفوفات عنصرًا تلو الآخر.
تتضمن اختلافات الكيانات المسار ونوع المورد والمعرف والاسم عند توفرها وحالة الإضافة/التعديل/الحذف وتغييرات الخصائص مع القيم السابقة/اللاحقة. تستخدم الملفات غير JSON سلوك التعارض على مستوى الملف. يؤدي دمج المستودعات مع التعارضات إلى إرجاع مساراتها ومؤشراتها دون كتابة التزام مدمج.
سحب الطلبات والأذونات
طلبات سحب المشروع مباشرة على /api/projects/:id/pulls. فتح واحد يسجل العنوان والنص والرأس والقاعدة ونوع المؤلف. تتضمن الاستجابات التفصيلية طلب السحب والمراجعات والتغييرات. دعم المراجعات comment, approve، و request-changes، مع مسار اختياري ومؤشر خاصية.
يتحكم أحدث حكم بعدم التعليق لكل مراجع في كتلة تغييرات الطلب. يتم رفض الدمج أثناء تغيير أي طلب من هذا القبيل. ولا يتطلب التنفيذ موافقة إيجابية في حالة عدم وجود حكم بالمنع. تستخدم اختلافات طلب السحب المدمجة التزام الدمج المسجل بحيث لا تغير حركة الفرع اللاحقة سجل المراجعة هذا.
تتطلب قراءة السجل والالتزام والتفرع وفتح طلبات السحب والمراجعة الوصول إلى المشروع. تتطلب عمليات نقل نسخة العمل وصيانة الفرع المشترك المالك أو مسؤول/مدير المؤسسة كما يفرضه المعالج. العمليات القذرة أو المتضاربة ترجع 409؛ ترجع الإجراءات المحمية 403؛ المراجع أو الموارد المفقودة تُرجع 404؛ العمليات الأخرى غير الصالحة ترجع 400.
لا يمكن لممثل الذكاء الاصطناعي الالتزام أو الاستعادة أو الاندماج main. يستخدم المساعد فرع الاقتراح ويفتح طلب سحب ليقوم الشخص بمراجعته. تحدد سجلات التدقيق والإخطار التغييرات التي أنشأها المساعد.
مرآة جيثب اختيارية
GET و PUT /api/projects/:id/vcs/remote قراءة أو تعيين owner/repo مرآة جيثب؛ null يفصله. استخدام الدفع والسحب POST /vcs/push و /vcs/pull، مع رمز GitHub الخاص بالمستخدم x-github-token لتلك المكالمة.
يقوم Push بنقل الكائنات التي يمكن الوصول إليها وتحديث الفرع البعيد دون الكتابة فوق الالتزامات البعيدة غير المسحوبة. يؤدي السحب إلى جلب الفرع البعيد ودمجه محليًا، مع رفض نسخة العمل القذرة. تؤدي تعديلات JSON المتباينة غير المتوافقة إلى إرجاع التعارضات بدلاً من استبدال المحتوى المحلي بصمت.
يستخدم النقل السايدكار عمليات كائن/مرجع GitHub REST. يتم توفير رمز GitHub لكل طلب ولا يتم تخزينه كبيانات مشروع. طلب السحب المحلي هو سجل مراجعة التطبيق؛ إنه ليس طلب سحب GitHub تلقائيًا.
لقطات والترميم
snapshotToFiles تحويل لقطة المشروع إلى محتويات الملف الأساسي؛ filesToSnapshot يعيد بناء قوائم المجال. ProjectVcsRepo يقرأ موارد قاعدة البيانات الحالية ويطبق اللقطات المستعادة. يمكن أن تؤدي استعادة المشروع بالكامل إلى تغيير العديد من الجداول ذات الصلة، لذا راجع اختلافاتها وامسح نسخة العمل قبل تبديل السجل.
واجهات برمجة تطبيقات النقل والكائنات
تقوم حزمة VCS بتصدير تشفير الكائنات وقراءتها، Repositoryومحولات المتجر ومساعدات JSON والدمج الأساسية وتحويل اللقطة واختلافات الكيانات ومزامنة GitHub وواجهات النقل. يمكن للاختبارات إدخال واجهة خلفية لكائن في الذاكرة أو نقل مزيف بدلاً من الوصول إلى مستودع المستخدم.
مداخل التنفيذ
packages/vcs/src/repository.ts يمتلك الالتزامات والمراجع والاجتياز والاستعادة والدمج؛ json.ts تمتلك الدمج الهيكلي. snapshot.ts يحدد الموارد المتعقبة؛ diff.ts يصف تغييرات الكيان؛ github.ts و transport.ts تنفيذ النسخ المتطابق. السايدكار project-vcs.ts ويضيف سياسة الفاعل والمثابرة، في حين http/vcs.ts لوازم تصريح النقل والأحداث.
عمليات التاريخ والأتمتة
يتم إصدار تعريفات سير العمل مع المشروع ويتم تشغيلها مقابل الملفات الملتزم بها. قد يؤدي الالتزام إلى تشغيل مسارات العمل هذه بعد تسجيل السجل؛ سير العمل الفاشل لا يتراجع عن الالتزام. حافظ على تميز عمليات حفظ الموارد المحلية، وعمليات تنفيذ المشروع، ونتائج سير العمل، والمزامنة عن بعد عند تشخيص حالة المشروع.
جرب المستودع بدون بيانات التطبيق
يتيح خط تخزين الكائنات تنفيذ تمرين التكامل وتفرعه بالكامل في الذاكرة. قم بتشغيل هذا داخل مساحة العمل التي تعتمد عليها @cadcamfun/vcs، مثل apps/sidecar. لا يمس قاعدة بيانات مشروع سطح المكتب.
import { Repository, memoryBackend, canonicalJson } from "@cadcamfun/vcs"
const repo = new Repository(memoryBackend())
const author = { name: "Workshop", email: "workshop@example.invalid", time: 0, tz: "+0000" }
repo.commit({ "project.json": canonicalJson({ name: "Blank", revision: 1 }) }, {
message: "Initial blank", author
})
repo.createBranch("proposal/wider-blank")
repo.checkout("proposal/wider-blank")
repo.commit({ "project.json": canonicalJson({ name: "Blank", revision: 2 }) }, {
message: "Record revised blank", author
})
console.log(repo.currentBranch()) // proposal/wider-blank
console.log(repo.log().length) // 2 Repository.commit يتلقى شجرة الملفات الكاملة لهذا الالتزام، وليس التصحيح. يقوم السايدكار ببناء هذه الشجرة من سجلات قاعدة البيانات العاملة والملفات النصية المحمولة. يجب أن يحافظ التكامل على مستوى الحزمة على الملفات التي ينوي الاحتفاظ بها. لا يطبق المثال الموجود في الذاكرة الملكية السايدكار أو سياسة ممثل الذكاء الاصطناعي؛ يتم فرضها بواسطة خدمة المشروع وطبقة HTTP.
مصدر: packages/vcs/src/store.ts, repository.ts، و apps/sidecar/src/services/project-vcs.ts.
المراجعة والاستعادة والمزامنة بشكل متعمد
تسجيل تغييرات نسخة العمل قبل تبديل الفروع. يتطلب التفرع الجديد التزام مصدر قابل للحل، لذا قم بتهيئة مشروع غير ملتزم بالتزامه الأول قبل التفرع. إنشاء فرع يؤدي فقط إلى إنشاء مرجع؛ الخروج عبارة عن عملية منفصلة تطبق لقطةها على قاعدة البيانات العاملة.
بالنسبة لطلب السحب، قارن الرأس بقاعدة الدمج الخاصة به وقم بمراجعة الاختلافات على مستوى الخاصية. لا يؤدي التعليق اللاحق إلى مسح حكم تغييرات الطلب السابق: يجب على المراجع إرسال حكم الموافقة اللاحق. يمكن للعلاقات العامة المدمجة التقديم السريع أو إنشاء التزام دمج وفقًا لأصل المستودع؛ افحص التزام الدمج المسجل بدلاً من افتراض عدد ثابت من الوالدين.
عند الدمج في القاعدة المسحوبة، تتطلب الخدمة نسخة عمل نظيفة وتطبق اللقطة الأساسية الجديدة. عند سحب فرع آخر، يقوم دمج التحديثات الأساسية للعلاقات العامة بتحديث مرجع هذا الفرع دون استبدال قاعدة البيانات العاملة الحالية. يقوم السحب اللاحق بتحميل تلك القاعدة المحدثة.
يعمل الدفع والسحب على مزامنة التاريخ الملتزم. لا يعد محتوى واجهة المستخدم غير المحفوظ وحالة قاعدة البيانات غير الملتزم بها لقطات عن بعد. الرفض عن بعد هو طلب جلب/دمج أولاً؛ إنها ليست تعليمات بالكتابة فوق الفرع البعيد.
مصدر: packages/vcs/src/repository.ts, github.ts، و apps/sidecar/src/services/project-vcs.ts.
التعافي من إخفاقات التاريخ
| فشل | الإجراء التالي |
|---|---|
NothingToCommit | قارن ملفات عمل قاعدة البيانات مع HEAD. لا يؤدي حفظ نفس قيم الموارد مرة أخرى إلى إنشاء شجرة مختلفة. |
| فرع غير صالح أو موجود | اختر اسم مرجع آمن جديد. لا يمكن أن تحتوي الأسماء على خطوط مائلة مزدوجة أو اجتياز أو أجزاء من تعبير ref أو لاحقة شرطة مائلة/.lock زائدة. |
| تغييرات غير ملتزم بها | الالتزام بالموارد المقصودة أو استعادتها/تجاهلها عمدًا قبل الخروج أو السحب أو عملية نسخة عمل محمية. |
| دمج الصراع مع المسار/المؤشرات | قم بفحص هذه الخصائص في محفوظات القاعدة/الرئيس، وقم بإنشاء حل تمت مراجعته، ثم أعد المحاولة. لم يؤدي دمج المستودع الفاشل إلى إنشاء التزام دمج جزئي. |
| طلب أحد المراجعين إجراء تغييرات | قم بحل الملاحظات واحصل على حكم محدث بعدم التعليق من ذلك المراجع. |
| لا يمكن للجهات الفاعلة في مجال الذكاء الاصطناعي التصرف بشكل رئيسي | استخدم فرع اقتراح الذكاء الاصطناعي وطلب سحب يراجعه الإنسان. لا يؤدي تغيير علامة التأكيد إلى إزالة قيود الممثل. |
مصدر: packages/vcs/src/repository.ts, apps/sidecar/src/services/project-vcs.ts، و http/vcs.ts. ال مرجع واجهة برمجة التطبيقات يسرد مخططات الطلب والاستجابة الفعلية.
تخطيط المستودع
يتم تخزين المشروع في المستودع كملف JSON واحد لكل كيان. وبالتالي فإن تحرير الرسم لا يمس أبدًا ملف مسار الأدوات، ويتم قراءة التخطيط بشكل طبيعي على GitHub. snapshotToFiles يكتب هذا التخطيط من أ ProjectSnapshot، و filesToSnapshot يقرأها مرة أخرى.
| قائمة لقطة | دليل | محتوى |
|---|---|---|
project | project.json | البيانات الوصفية للمشروع. |
drawings, components, toolpaths | نفس الأسماء | كيانات التصميم والتصنيع. |
materials, tools, machineConfigs | materials/, tools/, machine-configs/ | عناصر المكتبة هي مرجع مسارات الأدوات، التي تم إصدارها مع المشروع، لذا فإن مسار الأدوات المستعاد لا يزال يعثر عليها. |
costs | costs/ | تقديرات تكلفة الإنتاج لمسارات الأدوات. |
extra | أي طريق | الملفات النصية المخزنة حرفيًا: سير العمل، README، رمز G الذي تم إنشاؤه. |
الالتزام والتفرع والفرق والدمج في الكود
ال Repository يعمل الفصل على أي واجهة تخزين خلفية. يدعمها السايدكار باستخدام SQLite (الجداول GitObject و GitRef); memoryBackend() يستخدم للاختبارات والتجارب. المثال التالي كامل وتظهر نتائجه في التعليقات.
import { Repository, memoryBackend, snapshotToFiles, describeDiff } from "@cadcamfun/vcs"
const repo = new Repository(memoryBackend())
const me = { name: "Ada", email: "ada@example.com", time: 1767225600, tz: "+0100" }
const files = (width: number, height: number) => snapshotToFiles({
project: { id: "p1", name: "Bracket" },
drawings: [{ id: "d1", name: "Plate", width, height }],
components: [], toolpaths: [],
})
const base = repo.commit(files(40, 25), { message: "base", author: me })
repo.currentBranch() // "main"
repo.createBranch("a"); repo.createBranch("b")
repo.checkout("a"); const a = repo.commit(files(50, 25), { message: "a: width 50", author: me })
repo.checkout("b"); repo.commit(files(40, 30), { message: "b: height 30", author: me })
describeDiff(repo, base, a)
// [{ path: "drawings/d1.json", kind: "drawings", id: "d1", name: "Plate",
// status: "modified", changes: [{ pointer: "/width", before: 40, after: 50 }] }]
repo.mergeInto("a", "b", me) // { kind: "merge", oid: "46e7…" }
// different properties of the same entity merge cleanly
repo.checkout("b"); repo.commit(files(60, 30), { message: "b: width 60", author: me })
repo.mergeInto("a", "b", me)
// { kind: "conflict", conflicts: [{ path: "drawings/d1.json", pointers: ["/width"] }] }
repo.createBranch("bad..name") // throws: Invalid branch name bad..name
repo.commit(sameFilesAsHead, { message: "x", author: me })
// throws: No changes since the last commit (unless allowEmpty: true) تكون عمليات الدمج ثلاثية على مستوى خصائص JSON. عندما يقوم كلا الجانبين بتغيير خصائص مختلفة لكيان واحد، ينجح الدمج. عندما يقوم كلاهما بتغيير نفس الخاصية إلى قيم مختلفة، تكون النتيجة أ conflict يسرد مؤشرات RFC 6901 داخل كل ملف. تتم مقارنة المصفوفات ذات الطول المتساوي لكل فهرس، لذلك تظهر القمة المنقولة كتغيير واحد؛ تتم مقارنة صفائف ذات أطوال مختلفة ككل.
| دمج النتيجة | معنى |
|---|---|
up-to-date | لا شيء للدمج. إرجاع الالتزام الحالي. |
fast-forward | تحرك مؤشر الفرع للأمام؛ لم يتم إنشاء التزام الدمج. |
merge | تم إنشاء التزام الدمج. |
conflict | لا التزام. conflicts يسرد المسارات والمؤشرات لحلها. |
| طريقة المستودع | غاية |
|---|---|
commit(files, { message, author, allowEmpty? }) | اكتب شجرة كاملة كالتزام جديد على الفرع الحالي. |
log(rev = "HEAD", limit?) / fileLog(path, rev?, limit?) | تاريخ الفرع / ملف واحد . |
createBranch(name, from = "HEAD"), deleteBranch, checkout | إدارة الفروع. يجب ألا تحتوي الأسماء .. أو //، تنتهي في / أو .lock، أو تحتوي @{. |
tag(name, rev = "HEAD"), tags() | علامات خفيفة الوزن تحت refs/tags/. |
diff(from, to) | التغييرات على مستوى الملف: تمت إضافتها وتعديلها وحذفها بمعرفات blob. |
restorePaths(rev, paths, author, message?) | التزام جديد باستعادة الملفات المحددة من مراجعة قديمة. |
revertTo(rev, author, message?) | الالتزام الجديد الذي تعادل شجرته مراجعة أقدم؛ التاريخ لا تتم إعادة كتابته. |
merge(theirs, author) / mergeInto(into, theirs, author) | دمج ثلاثي في الفرع الحالي/فرع مسمى. |
isAncestor, mergeBase | استعلامات الرسم البياني. |
القواعد التي يفرضها التطبيق
تضيف خدمة محفوظات المشروع الخاصة بالسايدكار قواعد أعلى المستودع:
| رمز الفشل | متى |
|---|---|
blocked | يحاول ممثل الذكاء الاصطناعي الالتزام أو الاندماج main (تقول الرسالة لاستخدام ai/* فرع وفتح طلب سحب)، أو يتم دمج طلب السحب أثناء وجود آخر حكم للمراجع request-changes. |
dirty | تحتوي نسخة العمل على تغييرات غير ملتزم بها وستقوم العملية بالكتابة فوقها: "التغييرات غير الملتزم بها في ملف (ملفات) N؛ قم بتنفيذها أو تجاهلها أولاً". |
conflict | أدى الدمج إلى صراعات. الفشل يحمل قائمة الصراع. |
nothing-to-commit | لم تتغير الشجرة منذ الالتزام الأخير. |
not-found | فرع أو التزام أو كائن أو طلب سحب غير معروف. |
remote | فشلت مزامنة جيثب. |
invalid | مدخلات أخرى غير صالحة، على سبيل المثال مراجعة أو دمج طلب سحب غير مفتوح. |
يتم احتساب فقط أحدث حكم بعدم التعليق لكل مراجع. المراجع الذي طلب التغييرات ووافق عليها لاحقًا لم يعد يحظر الدمج. يتم نشر عمليات التنفيذ وسحب الأحداث والمراجعات كأحداث مباشرة، وبالتالي يتم تحديث سطح المكتب والإصدار المصاحب دون الاقتراع.
بايت متوافق مع بوابة
يتم حساب معرفات الكائنات تمامًا كما يحسبها git. يؤدي الدفع إلى GitHub من خلال واجهة برمجة تطبيقات Git Data إلى إبقاء كل معرف التزام متطابقًا على كلا الجانبين، كما يؤدي الضغط على GitHub إلى الاحتفاظ بمعرف الالتزام متطابقًا على كلا الجانبين git clone تعرض المرآة نفس سجل التطبيق. يقبل GitHub فقط تحديثات المرجع سريعة التقديم؛ قم بالسحب والدمج محليًا أولاً عند تحرك جهاز التحكم عن بعد.
كائن التزام حقيقي
{
"oid": "44d2d03d23b27fbbc4b388e32e15dfb0f39fff87",
"parents": [],
"message": "First version\n",
"author": { "name": "Local user", "email": "local@cadcamfun.local", "time": 1792037121 }
} oidهو معرف سداسي عشري مكون من 40 حرف لكائن الالتزام المخزن فيهGitObject.- الالتزام الأول ليس له أهل؛ التزام الدمج له اثنان.
- يتم تخزين الرسالة بسطر جديد لاحق، كما يفعل Git.
- بدون
x-session-token، المؤلف هو ملف التعريف المحلي للتثبيت.timeفي ثواني يونكس.
| طريق | جسم | مطلوب |
|---|---|---|
POST …/vcs/commit | message, authorKind, files | message |
POST …/vcs/branches | name, from | name |
POST …/vcs/checkout | branch | branch |
POST …/vcs/restore | rev, paths | rev |
POST …/pulls | title, body, head, base, authorKind | title, head |