2008年9月7日 星期日

linux-指令-awk

awk是可以用來分析文件的工具~本來我以為是一個小工具~
經過這一次之後,我才發現awk可以做的事情實在是太多了~可以由我上一篇寫的文章(svn update script)內的程式碼就知道了~

基本上呢,鳥哥寫的很清楚了,可以先看一下這裡~

那我在這裡寫的就是我有用到,但是,鳥哥沒有寫的~

如何把shell的變數傳給awk,這裡要注意的是,傳送去的變數,在使用的時候,不需要加$

[root@host ~]# awk -v var=$shell_var '條件類型1{動作1} 條件類型2{動作2} ...'file


如何在awk中,使用shell的指令,把command的output傳給awk下的var變數,而我的輸入部分就是透過command來完成的,可以參考我的上一篇的程式碼

command | getline var


另外,在awk的{動作1},其實可以放很大的程式碼,可以參考我上一篇文章的程式或是man awk

還有另一個很好用的指令system("指令")。就是可以在awk中,要求執行一個shell中的指令
例:

awk -F: '/正規表示法/
{
  cmd="命令字串";
  print cmd;
  system(cmd)
}' file


參考資料:
好用的 awk 命令
AWK 中如何利用系統資源
AWK Tutorial Guide(英文)
臥龍小三 Shell 設計入門 8.正規表示式 awk
study-area Scripts大集合: awk
通用線程:Awk 實例,第一部份(簡體中文)
通用線程:Awk 實例,第二部份(簡體中文)
通用線程:Awk 實例,第三部份(簡體中文)

svn update script

因為最近在使用svn,
每次有新的進度之後,就要開始看哪一些需要更新,
有時候編譯出來的檔案實在有夠多~

不可能一個指令一個指令下去打,很浪費時間~
但是,又要更新,這是一定要做的,所以,今天就研究了一下,
看能不能寫一個script來幫助我update這一些資料

所以,研究了awk這一個小工具,真的很好用,可以用來分析文件中的資料~
研究了六個小時左右終於寫出來了~這一個東西以後真的可以幫我省六個小時回來嗎?
[2008/11/20補充]
在這幾個月用下來,我覺得真的還不錯用~


以下是我寫出來的script,要放在svn的目錄下才可以使用
update.sh

#!/bin/bash

#把svn status 的結果送到temp檔
svn status > temp

#抓行數
total_line=`awk '{print NR}' temp|tail -n1`

#迴圈
for ((current_line=1;current_line<=$total_line;current_line=current_line+1))
do
  awk -v current=$current_line -v total=$total_line '{
    if ($1=="?" && current==NR && $2!="temp")
    {
      printf("========================================\n");
      printf("%s\n",$0);
      printf("Do you want to add(a) or delete(d):");
      "read yn && echo $yn" | getline yn;
      if (yn == "a")
      {
        cmd = "svn add "$2;
        print(cmd); // debug用
        system(cmd);
      }
      else if (yn == "d")
      {
        cmd = "svn delete --force "$2;
        print(cmd); // debug用
        system(cmd);
      }
    }
    else if ($1=="!" && current==NR && $2!="temp")
    {
      printf("========================================\n");
      printf("%s\n",$0);
      printf("Do you want to revert(r) or delete(d):");
      "read yn && echo $yn" | getline yn;
      if (yn == "r")
      {
        cmd = "svn revert "$2;
        print(cmd); // debug用
        system(cmd);
      }
      else if (yn == "d")
      {
        cmd = "svn delete "$2;
        print(cmd); // debug用
        system(cmd);
      }
    }
  }' temp
done
#刪除暫存檔temp
echo "========================================"
rm -rfv temp

NR是表示目前是第幾行,current和current_line記錄目前是第幾行;total和total_line是記錄temp一共有幾行。


這裡要說明一下,我的effort。
一開始我是打算全部都用awk來完成我的目標,awk是可以分析檔案的內容作適當的動作。
但是呢?在svn的顯示要更新的列表我目前只有兩項要注意的「!」、「?」
「?」:就是表示server沒有檔案,client有檔案。在這一個情況下我有兩個可能的動作要做;
一、這一個資料是我剛剛新增的,所以,我應該要打svn add path指令
二、這一個資料是Makefile幫我建出來了,我不想要它,我要打svn delete --force path的指令
「!」:這一個表示server有檔案,但是,client端確沒有檔案。在這一個情況下我有兩個可能的動作;
一、這一個本來就是我想要刪掉,或是我打Makefile打令把它刪掉的,要打svn delete --force path指令
二、這一個就是不小心被我刪掉了資料,我必需要還原它,要打svn revert path指令還原它

這裡遇到一些問題,
一、awk沒有提供function讓使用著在程式執行時輸入資料,這樣就不能跟使用者互動了,還好,awk有提供一個指令command | getline var透過shell的command傳值給var變數。因此,input的部分我必需透過shell的read指令來幫助我~
二、非常意外的,在同一個awk中,command | getline var竟然只能執行一次,而之後若要重覆執行,就會讀取之前輸入的資料,因此,我必需透過shell script讓每分析新的一行,我必需重新執行awk,而每一次執行awk,我必需只讀取我要分析的那一行,不然,又是由第一行開始,那第一行就會執行command | getline var,那我就前功盡棄啦~
三、我必需要知道這一個文件有幾行~不然,我怎麼去設定迴圈哩~
四、shell的變數與awk裡面的變數是不相同的,我必需透過-v參數把total_line與current_line的值傳送進去~
五、等我分析完之後,我還必在awk中透過shell打上我要打的svn指令,還好,awk提供了system(command)的這一個function,可以透過它傳送給shell指令


如何在awk使用傳送要給shell的指令
例:

awk -F: '/正規表示法/
{
  cmd="命令字串";
  print cmd;
  system(cmd)
}' file


取得文件行數
總結了一下有五種方法:
現在有一個a文件,共有55行
第一種:

[root@host ~]# awk '{print NR}' a|tail -n1


第二種:

[root@host ~]# awk 'END{print NR}' a


第三種:

[root@host ~]# grep -n "" a|awk -F: '{print '}|tail -n1

第四種:

[root@host ~]# sed -n '$=' a

第五種:

[root@host ~]# wc -l a|awk '{print }'

第六種:

[root@host ~]# cat a |wc -l


[2009.06.14 補充]
若要一次新增許多資料的話,而且分散在各各不同的資料夾,則有三個方法,第一個是一個一個加,第二個是使用上面的script,第三個是使用下面的指令
$ svn status | awk '{print $2}' | xargs svn add
而以上的指令使用條件是必需要是所有svn state所出來的檔案都是要新增的

參考資料:
好用的 awk 命令
AWK 中如何利用系統資源
怎樣取得文件行數

2008年9月6日 星期六

C++標準函式庫—STL(Standard Template Library)

何謂抽象指標(Iterator)

透過指標我們可以間接地讀取或寫入指標所指變數的內含值,指標的另一個用處是用來接受new運算子動態分配得到記憶體時所傳回的Address(然後我們再利用此指標間接操作此一動態記憶體-亦即此一記憶體沒有變數名稱「不具名物件」,所以一定要透過指標來間接操作它)。一般而言,對容器類別而言,為了達到像內建指標一樣方便的設施,我們並不是定義一個像vector<int> *pvec;這樣的指標來間接操作pvec所指到的向量,而是,我們另外定義了一個更形上更抽像的指標-叫做Iterator,此Iterator就是容器類別的指標,有了Iterator,我們可以對容器內的每一個元素做間接的讀取或寫入,更進一步來說,有了Iterator,會讓泛型演算法更加地一般化(這也是為什麼sort或copy演算法可以放諸四海皆準地用在各種容器上的原因)。每一個容器類別都有二個公開的成員函式,分別是begin()和end(),它們分別會傳回容器的第一個元素的指標(Iterator)和最後一個元素的下一個位置的指標(Iterator),如:

vector<int> ivec(10); //定義一個整數向量,內含10個元素

vector<int>::iterator iter = ivec.begin() //定義一個ivec向量的指標,它指向ivec的第一個元素

vector<int>::iterator iter_end = ivec.end() //定義一個ivec向量的指標,它指向ivec的最後元素的下一個元素

然後我們就可以利用提領(Dereference)運算子 * ,來間接地讀取或寫入第一個元素的值,如:

int ia = *iter; // 將第一個元素的內含值存入ia物件中

還有可以用遞增運算子 ++ ,將指標移到下一個或之後的其他元素當中,如:

iter++; // iter變成指向第二個元素

綜上所述,所有對內建指標可以做的提領或遞增和遞減的動作,一樣通通適用於Iterators,是不是很方便呢?

C++教學講義 Part7

2008年9月5日 星期五

qt - 透過滑鼠移動在canvas上的物件

參考資料:參考文檔的canvas example


void FigureEditor::contentsMousePressEvent(QMouseEvent* e)
{
  QPoint p = inverseWorldMatrix().map(e->pos()); // 可以改成p = inverseWorldMatrix()*(e->pos());
  QCanvasItemList l=canvas()->collisions(p);
  for (QCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it) { // Iterator請參考這裡
    moving = *it;
    moving_start = p;
    return;
  }
  moving = 0;
}

QCanvasItem* moving; // 用來記錄要移動的qcanvasitem的指標
QPoint moving_start; // 用來記錄要移動的qcanvasitem的起始座標位址

這裡說明一下,it是指標性值的變數,是指到QCanvasItemList內的item的位置,所以,(*it)指的就是放在QCanvasItemList的東西,而我們這裡放的東西就是ImageItem,而ImageItem是由CanvasItem繼承過來的~ImageItem *item= (ImageItem*)(*it);,就是把基底類別(CanvasItem)的指標轉換成衍生類別(ImageItem)的指標

用到的function解釋

const QWMatrix & QCanvasView::inverseWorldMatrix () const
Returns a reference to the inverse of the canvasview's current transformation matrix.
回傳目前canvasview的反座標轉換物件的參照(reference)

QPoint QWMatrix::map ( const QPoint & p ) const
This function is obsolete. It is provided to keep old source working. We strongly advise against using it in new code.
這一個函式作廢了,請用下面運算代替
Does the same as operator *( const QPoint &)

const QPoint & QMouseEvent::pos () const
Returns the position of the mouse pointer relative to the widget that received the event.
傳回滑鼠的相對於目前widget的指標位置

QCanvasItemList QCanvas::collisions ( const QPoint & p ) const
Returns a list of canvas items that intersect with the point p. The list is ordered by z coordinates, from highest z coordinate (front-most item) to lowest z coordinate (rear-most item).
傳回所有與p點有交集的所有canvas item,且這一個list內的canvas item是由z大排到z小

QCanvas * QCanvasView::canvas () const
Returns a pointer to the canvas which the QCanvasView is currently showing.
目前qcanvasview所顯示的是某canvas,把此canvas的指標傳回



用到的類別解釋
The QCanvasItemList class is a list of QCanvasItems
QCanvasItemList is a QValueList of pointers to QCanvasItems. This class is used by some methods in QCanvas that need to return a list of canvas items.
QCanvasItemList是一連串QCanvasItem的pointer的集合,這一個class是被某一些canvas的function用來回傳一連串的QCanvasItem的pointer

延伸閱讀:
QValueList類是一個提供雙向鏈表(double-link)的基於值的模板類,也就是說是一個雙向鏈表,但是,裡面放什麼東西,還沒有定義,而QCanvasItemList就是繼承QValueList<QCanvasItem * >,也就是說雙向鏈表裡面放的是QCanvasItem的指標啦~


void FigureEditor::contentsMouseMoveEvent(QMouseEvent* e)
{
  if ( moving ) {
    QPoint p = inverseWorldMatrix().map(e->pos());
    moving->moveBy(p.x() - moving_start.x(),p.y() - moving_start.y());
    moving_start = p;
    canvas()->update();
  }
}



void QCanvasItem::moveBy ( double dx, double dy ) [virtual]
Moves the canvas item relative to its current position by (dx, dy).
移動canvas item對於目前的位置的相對偏移(dx,dy)
動作解析:滑鼠先移動到目的地,算出滑鼠與目前的座標差,而這個座標差就是相對於原位置的偏移~再根據這一個偏移值移動這一個canvas item

====================================================
總算完成透過滑鼠移動canvas item的程式了,
這裡要另外一說的就是,inverseWorldMatrix()只有當在設定完WorldMatrix之後,才會有效果,基本上,若沒有設定過,就不需要使用這一個function

2008年9月4日 星期四

程式設計的版本控制 - SVN - 指令大全

path:表示本機路徑
url:表示是server上的目錄
file:是本機檔案

0. 一開始要把之前完成的程式上傳到空的svn server

[root@host ~]# svn import path url


1. 將文件checkout到本機端,其中path是你要新增的資料夾是用來放置下載下來檔案;url是網路上server的位置,xxx是使用者名稱

[root@host ~]# svn checkout path url --username xxx


如果我現在有9個版本,我要取得第二個的話就打以下指令,下載第二個版本到本機目錄path下

[root@host ~]# svn checkout -r 2 url path


2. 往檔案庫中添加新的檔案或資料夾

[root@host ~]# svn add file(or path)


3. 將修改過的文件提交到檔案庫

[root@host ~]# svn commit


4. 鎖定工作複本路徑或是檔案庫的 URL, 這樣就沒有其它使用者可以對它們送交任何更動.

[root@host ~]# svn lock path


5. 解除工作複本路徑或 URL 的鎖定

[root@host ~]# svn unlock path


6. 更新到某個版本(若沒有填,則更新到最新版本);svn update如果後面沒有目錄,默認將當前目錄以及子目錄下的所有文件都更新到最新版本。

將版本庫中的文件test.php還原到版本200

[root@host ~]# svn update -r200 test.php

更新到最新版本(如果在提交的時候提示過期的話,是因為衝突,需要先update,修改文件,然後清除svn resolved,最後再提交commit)

[root@host ~]# svn update test.php


6. 查看文件或者目錄狀態(包含子目錄),只列出與server有差異的部分

[root@host ~]# svn status path


顯示文件和子目錄狀態(包含與server沒有差異的部分也全部列出來)

[root@host ~]# svn status -v path

A file_or_dir:目錄或檔案 file_or_dir 已預定要被新增至檔案庫.
M file:檔案 file 的內容已被修改.
D file_or_dir:目錄或檔案 file_or_dir 已預定要自檔案庫刪除.
X dir:目前 dir 未納入版本控制, 但是關聯到一個 Subversion 的外部定義. 欲了解更多外部定義, 請參考 the section called “外部定義”.
? file_or_dir:目錄或檔案你可以藉由 svn status 命令的 --quite (-q) 選項, 或是對父目錄設定其 svn:ignore 性質, 就不會顯示問號代碼. 想知道有哪些檔案會被忽略, 請參照 the section called “svn:ignore”.
! file_or_dir:目錄或檔案 file_or_dir 已納入版本控制之中, 但是它不是消失, 就是不完整. 如果這個檔案或目錄被非 Subversion 的命令所刪除, 就會被判定為消失. 如果是目錄的話, 如果你在取出或是更新時中斷, 那麼它就會變成不完整. 只要執行 svn update, 就可以從檔案庫重新取得目錄或檔案, 或者以 svn revert file_or_dir, 回存消失的檔案.
~ file_or_dir:目錄或檔案 file_or_dir 在檔案庫裡是一種物件, 但是實際在工作複本中又是另一種. 舉個例子, Subversion 可能在檔案庫裡有一個檔案, 但是你刪除了這個檔案, 而以原名稱建立了一個目錄, 但是都沒有使用 svn delete 或 svn add 命令來處理.
C file:file_or_dir 處於衝突的狀態. 也就是說, 在更新時, 來自伺服器的更新與工作複本中的本地更動, 有重疊的部份. 在送交更動回檔案庫之前, 你必須先解決這個這個衝突.

第一列就是顯示上面的狀態,第二列顯示工作版本號,第三和第四列顯示最後一次修改的版本號和修改人。

7. 刪除檔案或資料夾

[root@host ~]# svn delete file(or path)


8. 查看日誌,顯示這個文件的所有修改記錄,及其版本號的變化

[root@host ~]# svn log file


9. 查看文件(資料夾)詳細信息

[root@host ~]# svn info file(or path)

這一個指令也可以查詢目前本地端的版本。

10. 比較差異
將修改的文件與基礎版本比較

[root@host ~]# svn diff file(or path)


對版本m和版本n比較差異

[root@host ~]# svn diff -r m:n file(or path)


11. 將兩個版本之間的差異合併到當前文件(但是一般都會產生衝突,需要處理一下)

[root@host ~]# svn merge -r m:n path


12. SVN 幫助

[root@host ~]# svn help
[root@host ~]# svn help ci


13.顯示path目錄下的所有屬於版本庫的文件和目錄

[root@host ~]# svn listpath


14. 創建納入版本控制下的新目錄
創建納入版本控制下的新目錄(每一個以工作副本 PATH 指定的目錄,都會創建在本地端,並且加入新增調度,以待下一次的提交。)

[root@host ~]# svn mkdir path


創建版本控制的目錄(每個以URL指定的目錄,都會透過立即提交於倉庫中創建)

[root@host ~]# svn mkdir url


在這兩個情況下,所有的中間目錄都必須事先存在。

15. 恢複本地修改(恢復原始未改變的工作副本文件)(注意: 本子命令不會存取網絡,並且會解除衝突的狀況。但是它不會恢復被刪除的目錄)

[root@host ~]# svn revert path


16. svn switch (sw):更新工作副本至不同的URL。
更新你的工作副本,映射到一個新的URL,其行為跟「svn update」很像,也會將服務器上文件與本地文件合併。這是將工作副本對應到同一倉庫中某個分支或者標記的方法。url是同一個資料庫中新的資料夾

[root@host ~]# switch url [path]

改寫工作副本的URL元數據,以反映單純的URL上的改變。當倉庫的根URL變動(比如方案名或是主機名稱變動),但是工作副本仍舊對映到同一倉庫的同一目錄時使用這個命令更新工作副本與倉庫的對應關係。

[root@host ~]# switch --relocate FROM TO [path…]


17. 解決衝突(svn resolved:移除工作副本的目錄或文件的「衝突」狀態)

[root@host ~]# resolved path

注意: 本子命令不會依語法來解決衝突或是移除衝突標記;它只是移除衝突的相關文件,然後讓 PATH 可以再次提交。

18. 看別人寫的commet
使用者在svn update前應該先查出自已目前的版本號,查目前版本號的方法如下,最大的號碼即為你目前的版本號

[root@host ~]# svn status -N -v


然後在svn update後,把原本版本號到最新版本號之間的送交註解看一下。例如:原本你的工作複本版本號為13,當你修改過後要送交之前得作一次svn update,版本號跳為17,那你這時候應該要作一次看comment的指令:

[root@host ~]# svn log -r 13:17 -v


先看看別人之前改了什麼,然後你自已評估與目前你所修改的程式流程有沒有衝突,例如:別人在16版的時候把$content[_msg]變數改為 $content[_lang]變數,那麼如果你有使用$content[_msg]的話,你就應該先改好手邊的工作複本,再作svn commit。

如果你覺得看comment不夠清楚,那麼直接比較一下程式碼到底有那裡是不同

[root@host ~]# svn diff -r 16


上面的指令會比較第16版與你手邊已修改但還未送交的版本作比較,如果你只想比較單一檔案的話,指令是:

[root@host ~]# svn diff -r 16 iLovePerl.php


有時候你個人的commit周期太慢了(可能因為一個bug一直抓不出來),那你還是要在未上傳檔案庫前,經常地(至少是一天一次)觀看遠端檔案庫的版本情況,像是你的工作複本到遠端檔案庫之間的送交註解,其指令如下:

[root@host ~]# svn log -r BASE:HEAD

這樣才不會與其他人的距離差太遠,否則等你要commit時,才來調整你的程式碼,這又太慢了。

有時候,在svn所控制的專案中,你有不想作版本控制的檔案,那該這麼作呢!

像是資料庫的設定檔,這個東西,每個程設師在開發狀態時,可能用的都是臨時性的資料庫,一個人一種設定,如果每一次commit或update後都把別人用的或是自己用的給重設了,那是件很麻煩的事,所以呢,我們使用svn:ignore性質來解救我們,方法如下,後來的Config代表的是一個資料夾,是你所想忽略的檔案所在的那一個資料夾,如果你想忽略的檔案是在現在的目錄中,那就把 Config 換成 .

[root@host ~]# svn propedit svn:ignore Config

然後它會進入stdin的模式,你直接打檔名進去即可,像是

[root@host ~]# svn propedit svn:ignore Config DB.config

然後按下 Ctrl+D即可。請記住DB.config是在Config資料夾中的檔案喔,而且DB.config檔不應該送進svn add中喔

[問題]
19. 像我的話,會由之前某一個檔案copy到另一個檔案,然後,要add的時候會出現「此資料夾以在控管內」,這是因為每一個資料夾內都會有一個.svn的隱藏資料夾,而在由其它資料夾copy過來時,同時也把這一個資料夾也copy過來,這個時候只要把.svn資料刪掉就可以了~

20. 當產品要release出去時,如何把每一個資料夾下的.svn刪掉哩?
其實不是刪掉,而是透過export不會產生.svn資料夾

[root@host ~]# svn export url path (跟 checkout 參數類同)


[2014.05.13 補充]
在commit時,同時加入描述。
% svn commit --message "Corrected number of cheese slices."

[2014.05.29 補充]
方法1
用\n來當作換行
% svn ci -m "This is the first line\nThis is the second line"

方法2
直接 svn commit,然后在vim中编辑log(需要bash中提前设置$SVN_EDITOR=vim)

方法3
提交指定文件中的log
-F [--file] ARG : read log message from file ARG

[2014.06.05 補充]
Log: 如果沒輸入參數, 預設會把所有 commit log 都列出來
svn log
svn log -l 10 # 顯示 10 筆(最新 10筆 Log)
svn log -c 100 # 顯示 revision 100 的 Log
svn log -v -c 100 # 顯示 revision 100 的詳細 Log

參考資料:
svn命令
版本控制系統:svn(subversion)
Version Control with Subversion
SVN命令(linux下)
Version Control with Subversion
目前用不到資料:
研究生必備SVN版本控管
在Linux上裝SVN + Backup Script
Linux(Ubuntu)下Apache + Svn的安装初步完成
svn commit的log中输入换行符
SVN 基本指令教學

程式設計的版本控制 - SVN - 完整例子說明

今天花了一整天,總算把SVN弄的差不多了~雖然今天花很多時間,但是,我知道這個系統會替我以後寫程寫省很多時間(我猜的)~
那我們就用一個完整的簡單例子來說明吧~

環境:Linux文字模式、Google的Project Hosting

申請跟測式的步驟在程式設計的版本控制 - SVN說明的應該很清楚了~這裡我們直接用例子來說明吧~

建立一個新的project吧~我這裡的示範project是goodmorn,那當然啦~我的帳號是superporter2001

這裡先假設已經看過前一篇文章,在google的Project Hosting建立一個新的Project叫做goodmorn

我們在建立一個~/svn資料夾,並且進入這一個資料夾

[root@host ~]# mkdir svn
[root@host ~]# cd svn


將資料 checkout 回來,也就是說把google Project Hosting的goodmorn Project下載到目前目錄下的goodmorn

[root@host ~/svn]# svn checkout https://goodmorn.googlecode.com/svn/trunk/ goodmorn --username superporter2001

系統會多一個~/svn/goodmorn的資料夾

在我們寫完一個main.cpp檔案完之後,這一個檔案的目錄在~/svn/goodmorn下,我們將此檔案(目錄)新增進 svn中

[root@host ~/svn]# svn add goodmorn/main.cpp


然後,我們上傳到svn中

[root@host ~/svn]# svn commit goodmorn


耶~那這個時候大家可能會說~那我一個檔案要add一次~那我很多檔案不就要add很多次?其實不用,假設在~/svn/goodmorn/testfile/下有3個檔案a.jpg、b.jpg、c.jpg,我們只要打以下指令

[root @host ~/svn]# svn add goodmorn/testfile/

它就會把testfile下的檔案都加進去啦~

這裡有一個例子要大家注意~若我新增一個testfile2,那我要如何更新到svn server呢?有兩個方法
方法1

[root@host ~/svn/goodmorn]# mkdir testfile2
[root@host ~/svn/goodmorn]# svn add testfile2

方法2

[root@host ~/svn/goodmorn]@ svn mkdir testfile2

這裡要跟各位說的是,若有要move、copy、mkdir的話,就用svn內建的指令吧~可求助svn help
注意,當專案納入subversion的控管後,若要對專案內的檔案作刪減增加,必須都用client軟體內的對應功能來操作,否則可能會有問題。另外就是專案下的每個目錄中皆有.svn的隱藏目錄,這是subversion用來控管的目錄,請不要刪除或修改裡面的內容。

同時,我發現一個情況~我本來在其它資料夾放置我之前寫好的程式碼,我把它copy到~/svn/goodmorn,但是,確發生問題~
svn: warning: 'car-sim_1.00' is already under version control
耶~它說早就在控管中~但是,commit它確沒有上傳~找到一個強制的方法~

[root@host ~/svn]# svn import car-sim_1.00 https://goodmorn.googlecode.com/svn/trunk/

硬是把它上傳上去,等一下再checkout下來~就正常了~
會照成上面的原因是因為在要上傳的資料夾中,有.svn的檔案存在,所要上傳時,系統才會說因為資料夾已在控管中,決解方法是把隱藏檔.svn刪除~

[root@host ~]# find ./ -name .svn -exec rm -rfv {} \;

就可以把目前目錄下(包含子目錄)的.svn檔案全部刪除~

與svn server比較檔案差異也很好用喔~

[root@host ~/svn/goodmorn]# svn status

SVN 檔案狀態資訊:

  • ?: 此檔案不存在 SVN 裡面
  • A: 此次新增的檔案
  • C: 此檔案已經有人改過, 合併不成功, 需要人工介入
  • D: 此次移除的檔案
  • M: 此檔案有修改過
  • U: 此檔案有被更新過

程式設計的版本控制 - SVN

[2009.02.17] 更新
產來在判斷是否有新增資料或是修改資料時,會自動略過*.o的檔案,不過,執行檔就不會了略過

[2009.02.05]更新
google code容量變大了很多,由原來的100mb增至2048mb,單個文件也由20mb增至40mb。好high啊!!

當程式越寫越大時,這個時候就需要一個系統來控制你寫的版本~
尤其是當多個人同時在寫一個系統的時候,這個版本控制就顯得格外的重要~
概念可以參考這裡版本控制系統的基礎觀念

今天也不知道為什麼就想到版本控制的東西,這個應該就是李文雄老師說的蘊釀吧~
不過,應該會對我寫程式有很大的幫助~
所以,今天就先來研究如何使用版本控制的系統吧~

1. 先到Google的Project Hosting註冊吧~
2. 並且依用 Subversion 跟 Google Code 作版本控制 (一)建立一個新的project吧~我這裡的示範project是goodmorn,那當然啦~我的帳號是superporter2001,在這一個網址
http://code.google.com/p/XXX/source/checkout
其中XXX的部分就是專案的名稱,目前這一個例子的專案名稱是goodmorn
可以了解google提供的url
3. 在client端安裝svn client吧

[root@host ~]# apt-get install subversion subversion-tools

4. 第一次把server上的目錄下載下來,google在Source-Checkout有提示指令(這裡要注意的是,它要你輸入的密碼不是你google的密碼,而是要去左上角的Setting裡面有一組密碼哩~)

[root@host ~]# svn checkout https://goodmorn.googlecode.com/svn/trunk/ goodmorn --username superporter2001

5. 這一個時候會在目前的目錄下新增一個檔案goodmorn,然後,我們試著在goodmorn下新增一個檔案testfile.txt,並把它加入準備要上傳的schedule中

[root@host ~]# touch goodmorn/testfile.txt
[root@host ~]# svn add goodmorn/testfile.txt

6. 然後,我們準備上傳我們修改好的檔案

[root@host ~]# svn commit goodmorn

7. 噹噹~進入server後,會出現剛剛修改的檔案哩~
8. 今天再繼續研究其它參數吧~反正,有問題就打以下指令

[root@host ~]# svn help

若要查比較詳細的資料可以打以下指令,例如要查svn add

[root@host ~]# svn help add


如果我現在有9個版本,我要取得第二個的話就打以下指令

[root@host ~]# svn checkout -r 2 https://goodmorn.googlecode.com/svn/trunk/ goodmorn --username superporter2001


svn指令索引

SVN 基本功能:

Import: 將整個 project_directory 的資料 import 進 svn 裡面

  • svn import project_directory http://DOMAIN/svn_project
  • svn import project_directory file:///SVN_PATH/svn_project

Checkout: (checkout 可簡寫成 co), 將資料 checkout 回來

  • svn co http://SVN_PATH/svn_project
  • svn co file:///SVN_PATH/svn_project
  • svn co -r 12 file:///var/lib/svn/dev/projects # 出第12版的 projcets code

List: (list 可簡寫成 ls), 看上面有哪些檔案/資料

  • svn ls http://SVN_PATH/svn_project
  • svn ls file:///SVN_PATH/svn_project

Update: (update 可簡寫成 up), 將目前資訊更新成 SVN 線上最新版本.

  • SVN_CHECKOUT_DIR$ svn up
Commit: (commit 可簡寫成 ci), 將目前所做的修改 commit 回 svn
  • SVN_CHECKOUT_DIR$ svn ci
Status: (status 可簡寫成 st), 看目前檔案/結構 跟 SVN 線上的版本有哪些不同
  • SVN_CHECKOUT_DIR$ svn st
Add: 將此 檔案/目錄 新增進 svn
  • SVN_CHECKOUT_DIR$ svn add filename 或 svn add directory
MV: 改檔名, 並且此檔案之前紀錄還要繼續留下
  • SVN_CHECKOUT_DIR$ svn mv filename new_filename
Revert: 還原這次的修改, 回到前一版的檔案狀態(未 commit 前可用)
  • SVN_CHECKOUT_DIR$ svn revert [file | directory]

SVN 檔案狀態資訊:

  • ?: 此檔案不存在 SVN 裡面
  • A: 此次新增的檔案
  • C: 此檔案已經有人改過, 合併不成功, 需要人工介入
  • D: 此次移除的檔案
  • M: 此檔案有修改過
  • U: 此檔案有被更新過


參考資料:
用 Subversion 跟 Google Code 作版本控制 (一)
用 Subversion 跟 Google Code 作版本控制 (二)
維基百科 - 版本控制
O'Reilly - 版本控制
版本控制系統的基礎觀念
版本控制系統(svn) - client版本
SVN基本指令教學
SVN教學