npm، Cargo، Composer اور pip سب ایک ہی semver shorthand کا مختلف طریقے سے مطلب نکالتے ہیں، اور میرے آزمائے گئے تیرہ range expressions میں سے صرف دو ہی ان چاروں میں ایک جیسا عمل کرتے ہیں۔
میں نے ہر manager کے لیے الگ الگ parsers لکھے، ان کے آفیشل specs پر عمل کیا، اور پھر ہر range کو انیس ورژن نمبرز کے میٹرکس (matrix) کے خلاف چلا کر دیکھا۔ 13 × 19 کے گرڈ (247 cells) نے ایک بکھری ہوئی تصویر پیش کی: صرف 17 cells نے ہر ٹول سے ایک ہی "yes" یا "no" جواب دیا، اور ان 17 میں سے زیادہ تر متفقہ طور پر مسترد (rejections) تھے۔ مختصراً یہ کہ، ٹولز "yes" کے مقابلے میں "no" پر کہیں زیادہ متفق ہوتے ہیں۔
ٹولز میں فرق کیوں ہے
چاروں managers کا دعویٰ ہے کہ وہ Semantic Versioning پر عمل کرتے ہیں، پھر بھی ہر ایک کے اپنے shorthand قواعد ہیں۔
- Caret (^) اور dot-x – npm caret کو سپورٹ کرتا ہے؛ pip caret اور dot-x دونوں کو نظر انداز کر دیتا ہے۔ صرف یہی بات npm اور pip کے درمیان 49 cells کا اختلاف پیدا کرتی ہے۔
- Bare versions – Cargo ایک سادہ
1.2.3کو caret range کے طور پر لیتا ہے، جس کا مطلب ہے "1.x کے ساتھ مطابقت رکھنے والا"۔ npm اور Composer اسی اسٹرنگ کو ایک بالکل درست میچ (exact match) کے طور پر پڑھتے ہیں، اور صرف1.2.3کو قبول کرتے ہیں۔ - Tilde (~) – Cargo کا tilde minor ورژن کو فکس کرتا ہے (
~1.2کا مطلب1.2.*ہے لیکن1.3.0نہیں)۔ Composer کا tilde major ورژن کو فکس کرتا ہے (~1.2کا مطلب1.*ہے)۔ یہ دونوں تشریحات کسی بھی ایسے ورژن پر مختلف ہو جاتی ہیں جو minor component کو تبدیل کرتا ہو۔
Pre-release کی ہینڈلنگ ایک اور حیرت کا باعث بنتی ہے۔ ^1.2.3 جیسی range میں 2.0.0-rc.1 شامل نہیں ہوتا، اگرچہ اس کا عددی حصہ upper bound سے کم ہے۔ قاعدہ یہ ہے: pre-releases کو اس وقت تک خارج رکھا جاتا ہے جب تک کہ range میں واضح طور پر کسی pre-release identifier کا ذکر نہ ہو۔
ٹولز کے درمیان واحد محفوظ سنٹیکس (syntax)
تجربہ ظاہر کرتا ہے کہ واضح inequality ranges—مثلاً >=1.2.0 <2.0.0—npm، Cargo، Composer اور pip میں ایک ہی طرح کام کرتی ہیں۔ ہر manager ان دو حدود (boundaries) کو لفظی طور پر عددی حدود (numeric limits) کے طور پر لیتا ہے، جس میں کوئی پوشیدہ caret یا tilde semantics نہیں ہوتے۔
اگر آپ کو "کوئی بھی 1.x ورژن جو کم از کم 1.2 ہو" ظاہر کرنا ہے، تو اسے مکمل طور پر لکھیں۔ اس میں چند اضافی حروف لگتے ہیں، لیکن یہ اس بات کی ضمانت دیتا ہے کہ جہاں بھی کوڈ چلے گا، اس کا resolution قابلِ پیش گوئی ہوگا۔
جب shorthand اب بھی معنی رکھتی ہو
سنگل لینگویج (single-language) پروجیکٹس کے لیے shorthand اب بھی پرکشش ہے۔ خالص npm ecosystem کے اندر، ^1.2.3 مختصراً "مستقبل کے minor اور patch releases کے ساتھ مطابقت" کو بیان کرتا ہے۔ یہی بات Cargo کے caret یا Composer کے tilde کے لیے بھی درست ہے جب آپ کو معلوم ہو کہ استعمال کرنے والا ٹول تبدیل نہیں ہوگا۔ خطرہ تب پیدا ہوتا ہے جب ایک ہی manifest کو مختلف زبانوں کی حدود کے درمیان دوبارہ استعمال کیا جائے، یا جب کوئی CI job متعدد ecosystems سے dependencies حاصل کرے۔
خلاصہ
کراس لینگویج مطابقت (cross-language compatibility) کے لیے semver shorthand پر بھروسہ کرنا ایک جوا ہے۔ اس بات کی ضمانت دینے کا واحد قابلِ اعتماد طریقہ کہ ورژن کی پابندی (version constraint) کا ہر جگہ ایک ہی مطلب ہو، واضح inequalities لکھنا ہے۔ جب آپ کو اختصار کی ضرورت ہو، تو ایک ہی ecosystem تک محدود رہیں؛ جب آپ کو تسلسل (consistency) کی ضرورت ہو، تو وضاحت کے لیے shorthand کا استعمال چھوڑ دیں۔
