۱۳۸۹ تیر ۱۳, یکشنبه

ترفند 2 » جابجا کردن فایل در SVN به شیوه صحیح

تعریف مساله

اگر نمی‌دانید SVN چیست بی‌خیال این پست بشوید و در عوض اینجا یا اینجا را بخوانید.

اگر تا به حال برای مدیریت فایل‌های پروژه از نرم‌افزار SVN (SubVersioN) استفاده کرده باشید، احتمالا به این موضوع برخورد داشته‌اید که یک فایل را جابجا کرده‌اید یا نامش را تغییر داده‌اید و سپس هنگامیکه می‌خواستید تغییرات را ارسال (commit) کنید، متوجه شده‌اید که به جای اینکه از دستورات svn برای جابجا کردن فایل استفاده کنید، از دستورات سیستم فایل استفاده کرده‌اید.

در این حالت SVN به مشکل برمی‌خورد: SVN نمی‌تواند بفهمد که شما فایل را جابجا کرده‌اید، بنابراین این جابجایی را به صورت دو تغییر می‌بیند: اولا فایل اصلی گم‌شده است. دوما فایل جدیدی اضافه شده است که تحت مدیریت نسخ قرار ندارد.

شما می‌توانید این تغییرات را ارسال کنید که معادل یک حذف/اضافه شدن یک فایل جدید به مخزن (Repository) است. اما این وضعیت با یک جابجایی(move) متفاوت است، چرا که در جابجایی سابقه تغییرات فایل حفظ می‌شود ولی در یک حذف/اضافه دو فایل به همدیگر هیچ ارتباطی ندارند و سابقه آنها از همدیگر مستقل است.

راه‌حل ویندوزی

این وضعیت به کمک TortoiseSVN در ویندوز به سادگی قابل حل است:
کافیست در پنجره ارسال، دو فایل قدیم و جدید را انتخاب کنید و از منوی کلیک راست، گزینه Repair Move را انتخاب کنید. شرح بیشتر

راه‌حل لینوکسی

در لینوکس اما وضعیت اندکی متفاوت است. حقیقتش من هیچ رابط کاربری دلچسبی برای SVN در لینوکس سراغ ندارم. با اینکه در حال حاضر SVN جزء لاینفک برنامه‌نویسی متن‌باز است و خودش نیز زاده این فرهنگ است و طبیعتا انتظار می‌رود برنامه‌های مناسبی برای آن در لینوکس موجود باشد؛ و با اینکه برنامه‌های بیشماری در این رابطه برای لینوکس نوشته شده‌اند، به نظر من هیچ یک کارایی TortoiseSVN را ندارند. برنامه‌هایی مثل: RabbitVCS, RapidSVN, SmartSVN, Subclipse و …

از طرف دیگر معلوم نیست امکان Repair Move در کدامیک از این برنامه‌ها وجود دارد یا خیر. نتیجه اینکه تصمیم گرفتم برای حل این مشکل دست به کار شوم و یک اسکریپت ساده بنویسم. حاصل کار اسکریپت svnfixmove است که از طریق خط فرمان قابل استفاده است.

فراخوانی اسکریپت بسیار شبیه استفاده از دستور svn move است. مثلا اگر اسکریپت را در فولدر خانه (home) خود قرار دهید:

~/svnfixmove oldfile newfile

اول بررسی می‌کند که فایل oldfile در وضعیت Missing باشد و فایل newfile نیز در وضعیت Unversioned قرار داشته باشد و فقط در این صورت، وضعیت فایل را «تصحیح» می‌کند.

برای استفاده از اسکریپت کافیست متن آن را از کادر زیر کپی کنید و در یک فایل ذخیره کنید. سپس فایل را به عنوان فایل قابل اجرا علامت بزنید:

#!/bin/sh
#
# By: Sajjad Naficy (2010/Jul/4)
#
# This work is in public domain. You may use/modify/redistribute 
# it anyway you want. However a mention of the original creator 
# is appreciated.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#

(svn st $1|grep "^\!") >/dev/null
if [ $? -ne 0 ]; then
  echo "$1 must be missing." 
  exit 1
fi
(svn st $2|grep "^\?") >/dev/null
if [ $? -ne 0 ]; then
  echo "$2 must be unversioned." 
  exit 2
fi

mv $2 $1
svn move $1 $2
کلمات کلیدی: Linux, script, subversion, svn, svn move, TortoiseSVN, Windows, اسکریپت, ترفند, لینوکس, ویندوز

۷ نظر:

  1. به به سجاد! یه بوقی چیزی میزدی ;) به سلامتی مبارکه :)

    پاسخحذف
  2. ممنون. منتظر دریافت نظراتت هستم. :)

    پاسخحذف
  3. اتفاقا من همين ديروز svn رو راه انداختم تو شركت با كمك يكي از همكارا.
    من مشكل اين پست رو راستش نفهميدم :(
    ولي مشكل ما اين بود كه كل پرو»ه را ميخواستيم تو يه درايو ديگه كپي كنيم و اصلا يك repository جديد بسازيم..بعد عين كنه اين svn فايل ها چسبيده بود كنده نميشد ازش...
    آخرش show hidden files كرديم و دستي تمام .svn ها رو پاك كرديم تا پروژه پاك شد از هرچه اين علامت ها كه به فايل ها چسبيده بود..بعد هم با صلوات فرستاديمش رو سرور...
    حالا ميخواستيم commit كنيم نميشد ...بگو مشكل چي بود!!!! بايد antivirus macafee رو disable ميكرديم... تا كل soloution را بتونيم commit كنيم ...
    حالا گفتم كه اگه گير كردين هر جائي اين antivirus هارو مواظب باشين..

    زياد حرفيدم..

    پاسخحذف
  4. باید یه فرم «از چه طریقی با وبلاگ ما آشنا شدید» بذارم :)
    از حوصله‌تون ممنون.

    1) اتفاقا پاک کردن دایرکتوری‌های svn اینقدر مبتلا به همه بوده است که برای آن ابزار مناسب در svn پیش‌بینی شده: به این کار export کردن گفته می‌شه. در TortoiseSVN سرراست‌ترین روش دسترسی بهش اینه که روی فولدر کلیک راست کنید و همین گزینه را انتخاب کنید.

    2) اندکی توضیح بیشتر درباره این موضوع پست:
    مساله move دادن یا rename کردن فایل‌ها از خارج svn - که در این پست مطرح شده است - خیلی مشکل حادی محسوب نمی‌شود: svn می‌تواند تاریخچه یک فایل را (یعنی کل آنچه از گذشته فایل می‌داند) همراه با آن move دهد. اما این در صورتی اتفاق می‌افتد که شما برای انتقال، از دستورات خود svn استفاده کنید. اگر خودتان راسا فایل را move بدهید (و زمان ارسال نیز آن را تصحیح نکنید) اتفاق خاصی نمی‌افتد، فقط svn ارتباط فایل قدیم با جدید را نخواهد فهمید و با آنها به عنوان دو فایل با دو تاریخچه مجزا برخورد می‌کند. و این بدین معنی‌است که مثلا دیگر نمی‌توان روی فایل جدید کلیک کرد و تغییراتی که در طول زمان با اسم قدیمی در آن داده شده بود را دید، بلکه باید فایل قدیم را در log پیدا کنید و تغییرات آن را ببینید.

    امیدوارم مساله روشن‌تر شده باشد. در هر صورت جای نگرانی ندارد، اگر روزی هم با آن برخورد کردید مشکلی ایجاد نخواهد شد. :)

    پاسخحذف
  5. متاسفم انگار خيلي فضول بودم ..من از طريق گونيا(آرمان) اينجا اومدم...

    پاسخحذف
  6. فضول؟ من وبلاگ رو درست کردم که همه دنیا بهش سر بزنن! :)
    فقط کنجکاو بودم ببینم چطوری افراد - بخصوص آشنایان - پیداش می کنن، همین.
    خیلی خوش آمدید. امیدوارم وبلاگ مفید باشه و به دنبال کردنش راغب باشید. :)

    پاسخحذف
  7. توی rapidsvn هم اگه دو تا فایل رو انتخاب کنی و commit کنی می شناسه و خودش revision رو درست می کنه.

    پاسخحذف