Planet Linux of Taiwan

09月28日

shelandy's face
shelandy


縮小 展開

Mageia 5 WPA2 Enterprise setting [solved]!

If your you need to connect to a WPA2 Enterprise wireless  server similar to this setting in Ubuntu's network manager
    Wireless security: WPA & WPA2 Enterprise
    Authentication: Protected EAP (PEAP)
    Anonymous Identity: NetID
    CA certificate: None
    PEAP version: Automatic
    Inner Authentication: MSCHAPv2
    Username: NetID
    Password: password

This is the Ubuntu's WPA2 for setting above using network manager in wpa_supplicant.conf
network={
    pairwise=CCMP
    proto=RSN
    ssid="YOURWPA2_AP_SSID"
    password="MYPASSWD"
    eap=PEAP
    key_mgmt=WPA-EAP
    phase2="auth=MSCHAPV2"
    identity="MYNETID"
    auth_alg=OPEN
     phase1="peaplabel=auto peapver=0"
    eapol_flag s=0                  
    disbaled=1                    
}

This is the setting of  the default Mageia 5 WPA2 Enterprise setting using network manager.   in /etc/wpa_supplicant.conf.  This will not work.
network={
    pairwise=TKIP
    proto=WPA
    identity="MYNETID"
    ssid="YOURWPA2_AP_SSID"
    password="MYPASSWD"
    scan_ssid=1
    group=TKIP
    mode=0
    eap=PEAP
    key_mgmt=WPA-EAP
    phase2="auth=MSCHAPV2"
}

This is the Mageia's  working WPA2 Enterprise  setting equivalent to the one in Ubuntu .  It works!
network={
    pairwise=CCMP
    proto=RSN
    identity="MYNETID"
    ssid="YOURWPA2_AP_SSID"
    password="MYPASSWD"
    scan_ssid=1
    group=CCMP TKIP
    mode=0
    eap=PEAP
    key_mgmt=WPA-EAP
    phase2="auth=MSCHAPV2"
}

the difference between Ubuntu and Mageia's default  WPA2 enterprise setting
+ scan_ssid=1        // mageia default
+ group=TKIP        // mageia old use TKIP
+ mode=0              //  mageia default
- auth_alg=OPEN // Ubuntu's, not needed in
- phase1="peaplabel=auto peapver=0"   // Ubuntu      
- eapol_flags=0    // Ubuntu                           
-  disbaled=1        // Ubuntu

diff wpa_supplicant.conf wpa_supplicant.conf.old (the later the is Mageia's non-working default setting)
<    pairwise=CCMP
<    proto=RSN
<    group=CCMP TKIP
>    pairwise=TKIP
>    proto=WPA
>    group=TKIP

This is the 2/20 of my 開放改變20 initiative in this year.

09月27日

coldnew's blog's face
coldnew's blog


縮小 展開

Unknown perls from the Clojure standard library 筆記

看完 ClojuTRE 2015Unknown pearls from the Clojure standard library - Renzo Borgatti 演講後,來紀錄個筆記。

這場演講介紹了一些在 clojure.core 裡面的函式,這些函式平常可能不太有機會用到,但是可以協助我們除錯程式的問題。

投影片: 下載連結

destructure

destructure (解構) 在 Clojure 裡面是個非常實用的功能,可以方便我們對資料直接指派變數去代替它,如下:

No destructuring

(let [data [1 2 3]
      a (nth data 0)
      b (nth data 1)
      c (nth data 2)]
  (println "a:" a "b:" b "c:" c))
;; => a: 1 b: 2 c: 3

With destructuring

 (let [[a b c] [1 2 3]]
   (println "a:" a "b:" b "c:" c))
 ;; => a: 1 b: 2 c: 3
 
 
 

我們可以透過 destructure 去觀察一個東西是如何被解構的,這邊是投影片給的範例:

(destructure '[[x y & others] v])

;; => [v2 v
;;     x (nth v2 0 nil)
;;     y (nth v2 1 nil)
;;     others (nthnext v2 2)]

當然投影片給的是整理後的結果,實際上我執行得到的結果是這樣的

[vec__23596
 v
 seq__23597
 (clojure.core/seq vec__23596)
 first__23598
 (clojure.core/first seq__23597)
 seq__23597
 (clojure.core/next seq__23597)
 x
 first__23598
 first__23598
 (clojure.core/first seq__23597)
 seq__23597
 (clojure.core/next seq__23597)
 y
 first__23598
 others
 seq__23597]

reductions

我們在 Clojure 中很常用 reduce 去將一個函數作用到list 上的每兩個元素上,然後返回最後的結果,最常見的簡單函數就是一個 list 的元素全部相加

(reduce + (range 10))
;; => 45

reduce 的運作過程,則可以透過 reductions 來協助我們進行查看,可以看到這邊最後得到的 45 就是我們想要的結果。

(reductions + (range 10))
;; =>  (0 1 3 6 10 15 21 28 36 45)

test

在 Clojure 中,我們可以在 metadata 中設定好對一個函數的測試方式,然後呼叫 test 對該函數進行測試,這項功能很適合用在小函式的一些 assertion 測試上。

(defn add+
  {:test #(do
            (assert (= (add+ 2 3) 5))
            (assert (= (add+ 4 4) 8)))}
  [x y] (+ x y))

(test #'add+) ;; <= trigger
;; => :ok

你也可以透過 meta 去查看你這個函式的 metadata 或是測試用的函式資訊

(meta #'addd+)

;; =>
{:arglists ([x y]),
 :test #function[hello.core/fn--23678],
 :line 350,
 :column 4,
 :file "/home/coldnew/Workspace/hello/src/hello/cpre.clj",
 :name add+,
 :ns #namespace[hello.core]}

clojure.pprint/cl-format

clojure.pprint/cl-format 是 Clojure 移植 Common Lisp 的 format 函式,對於同時寫 Clojure 和 ClojureScript 的開發者而言, cl-format 可以同時用於 Clojure 和 ClojureScript 上,方便了不少。

(註: CLJS-324 ISSUE 尚未被解決前,Clojure 的 format 是無法用於 ClojureScript 上的)

如果要更多關於 cl-format 的使用,可以看看 Praticle Common Lisp 一書,我在 clojure/clojurescript 與 left-pad 一文亦有提到如何透過 cl-format 實作 Clojure/ClojureScript 皆可以用的 leftpad 函式。

投影片上給的範例則是這樣:

(clojure.pprint/cl-format nil "~:r" 1234)
;; => one thousand, two hundred thirty-fourth

(clojure.pprint/cl-format nil "~@r" 1234)
;; => MCCXXXIV

clojure.java.browse/browse-url

clojure.java.browse/browse-url 會呼叫系統預設的瀏覽器,開啟你所指定的網頁。

(clojure.java.browse/browse-url "http://localhost:3000")

clojure.java.javadoc/javadoc

Clojure 畢竟是 JVM 上的語言,有時候我們需要查看一些 javadoc,或是查看 Clojure 內部的 Java 實現,可以透過 clojure.java.javadoc/javadoc 來查看

(clojure.java.javadoc/javadoc (list* 1 []))
;; => open clojure.lang.Cons Javadoc

clojure.reflect/reflect

老實說我看了還是不知道這是什麼,也許是和 Java 的 reflection 有關,不過我們還是可以在 clojure.reflect/reflect 的文檔中看出一些東西

(require '[clojure.reflect :refer [reflect]])
(require '[clojure.pprint :refer [print-table]])

;; Here we have a simple function that prints the
;; important bits of the class definition in a table.
(->> String
     reflect
     :members
     print-table)

;; =>
;; |                    :name |           :return-type | :declaring-class |                                       :parameter-types |                       :exception-types |                        :flags |
;; |--------------------------+------------------------+------------------+--------------------------------------------------------+----------------------------------------+-------------------------------|
;; |               replaceAll |       java.lang.String | java.lang.String |                    [java.lang.String java.lang.String] |                                     [] |                    #{:public} |
;; |   CASE_INSENSITIVE_ORDER |                        | java.lang.String |                                                        |                                        |     #{:public :static :final} |
;; |                  indexOf |                    int | java.lang.String |                    [char<> int int char<> int int int] |                                     [] |                    #{:static} |
;; |           codePointCount |                    int | java.lang.String |                                              [int int] |                                     [] |                    #{:public} |
;; |                 getChars |                   void | java.lang.String |                                   [int int char<> int] |                                     [] |                    #{:public} |
;; |            regionMatches |                boolean | java.lang.String |                         [int java.lang.String int int] |                                     [] |                    #{:public} |
;; |                  isEmpty |                boolean | java.lang.String |                                                     [] |                                     [] |                    #{:public} |
;; |              codePointAt |                    int | java.lang.String |                                                  [int] |                                     [] |                    #{:public} |
;; |              lastIndexOf |                    int | java.lang.String |                                     [java.lang.String] |                                     [] |                    #{:public} |
;; |               startsWith |                boolean | java.lang.String |                                 [java.lang.String int] |                                     [] |                    #{:public} |
;; ...etc

講者在投影片中給的範例則是這個: (注意到結果是節錄呦~)

(require '[clojure.reflect :refer [reflect]])
(println (with-out-str (clojure.pprint/write (reflect :a))))

;; extract from a typical output:
{:name invoke,
 :return-type java.lang.Object,
 :declaring-class clojure.lang.Keyword,
 :parameter-types [java.lang.Object java.lang.Object],
 :exception-types [],
 :flags #{:public :final}}

clojure.inspector/inspect-tree

我們在處理一些樹狀資料時(ex: JSON 格式),有個圖示化的工具可以方便瀏覽所有資訊,這邊可以透過 clojure.inspector/inspect-tree 來查看

(require '[clojure.inspector :as i])

(def m {:a "a"
        :b {:c "c"
            :d [1 2 3]
            :e {:f "f"
                :g "g"
                :h "h"}}
        :i [1 2 3]
        :l {:m "m"
            :n "n"}
        :o [{:p "p" :q "q"}]})

(i/inspect-tree m)

這樣呼叫,會得到如下的視窗

clojure.lang.PersistentQueue

clojure.lang.persistentQueue 是 Clojure 下並未寫在 doc 上面的 Queue 實現 (java) ,我們可以用它來實作我們需要的 queue (佇列) 功能

基本上,你有以下幾種方法可以對你的 PersistentQueue 進行處理

  • peek

    取得 queue 最頂端的資料(head)

  • pop

    回傳不包含最頂端資料(head)的一個新的 PersistentQueue

  • conj

    將資料加入到 queue 的尾巴

  • empty?

    檢測 queue 是否為空的

  • seq

    將 queue 的資料變成序列 (sequence)

投影片上,講者是舉這範例:

(def e (clojure.lang.PersistentQueue/EMPTY))
(def buf (reduce conj e (range 10)))

(peek buf)
;; => 0

(peek (pop buf))
;; => 1

(peek (pop (pop buf)))
;; => 2

StackOverflow 則是有人舉出了如何透過 clojure.lang.persistentQueue 實現自己的 queue 函式

(defn queue
  ([] clojure.lang.PersistentQueue/EMPTY)
  ([coll] (reduce conj clojure.lang.PersistentQueue/EMPTY coll)))

(defmethod print-method clojure.lang.PersistentQueue
  [q ^java.io.Writer w]
  (.write w "#queue ")
  (print-method (sequence q) w))

(comment
  (let [*data-readers* {'queue #'queue}]
    (read-string (pr-str (queue [1 2 3])))))

fnil

我們在用 Clojure 處理東西的時候,有時候可能是資料本身就是 nil 的情況,這種狀況下對 nil 進行處理可能就會導致 Exception 的狀況發生

在傳統的 LISP 中,常以 or 作為一個保護,一旦遇到 nil 的情況,則回傳預設值

(or nil 10)
;; => 10

fnil 則是用來替你的函式多加一層保護,讓函式遇到 nil 的狀況可以避免一些 Exception 的發生

講者在投影片上提供的範例是這樣的:

(def m {:host "127.0.0.1" :port nil})
(update m :port (fnil #(Integer/parseInt %) "80"))
;; => {:host "127.0.0.1", :port 80}

(def m {:host "127.0.0.1" :port "8008"})
(update m :port (fnil #(Integer/parseInt %) "80"))

;; => {:host "127.0.0.1", :port 8008}

不過我們也可以將其拆開來看,這樣會更好理解

(Integer/parseInt "10")
;; => 10

(Integer/parseInt nil)
;; =>  Unhandled java.lang.NumberFormatException

((fnil #(Integer/parseInt %) 80) "1000")
;; => 1000

counted?

counted? 是 O(1) 的操作,用來查看目標是否具有實作 count 函式

(counted? [:a :b :c])
;; => true

(counted? '(:a :b :c))
;; => true

(counted? {:a 1 :b 2 :c 3})
;; => true

(counted? #{:a :b :c})
;; => true

(counted? "asdf")
;; => false

(counted? (into-array Integer/TYPE [1 2 3]))
;; => false

reversible?

reversible? 也是 O(1) 的操作,用來查看目標是否有實作 reversible 函式

(reversible? [])
;; =>  true

(reversible? (sorted-map))
;; =>  true

(reversible? (sorted-set))
;; =>  true

(reversible? '())
;; =>  false

(reversible? {})
;; =>  false

(reversible? #{})
;; =>  false

vector-of

vector-of 會根據你提供的類型 (permitive type) 來將參數轉換成相對應型別的向量 (vector)

可以使用的類型有 :int , :long , :float , :double , :byte , :short , :char , :boolean

(conj (vector-of :int) 1 2 3)
;; => [1 2 3]  ; <-- note, these are unboxed internally

(vector-of :int 1 2 3)
;; => [1 2 3]  ; same here

(vector-of :float 1 2 3)
;; => [1.0 2.0 3.0]

(type (conj (vector-of :int) 1 2 3))
;; => clojure.core.Vec

(type (conj (vector-of :float) 1 2 3))
;; => clojure.core.Vec

clojure.set/rename-keys

clojure.set/rename-keys 可以用來改變目前現有的 hash-map 的關鍵字 (keyword) 名稱

(require 'clojure.set)

(clojure.set/rename-keys {:a 1, :b 2} {:a :new-a, :b :new-b})
;; => {:new-a 1, :new-b 2}

(cloure.set/rename-keys {:a 1} {:b :new-b})
;; => {:a 1}

;; You need to be careful about key collisions.  You probably shouldn't
;; depend on the exact behavior.
(clojure.set/rename-keys {:a 1 :b 2} {:a :b})
;; => {:b 1}

(clojure.set/rename-keys  {:a 1 :b 2}  {:a :b :b :a})
;; => {:a 1}

clojure.data/diff

clojure.data/diff 用來對兩個序列(sequence)進行比較,並回傳比較的結果

(require 'clojure.data)

(clojure.data/diff {:a 1 :b 2} {:a 3 :b 2 :c 3})
;; => ({:a 1} {:a 3, :c 3} {:b 2})

(clojure.data/diff [1 2 3] [5 9 3 2 3 7])
;; => [[1 2] [5 9 nil 2 3 7] [nil nil 3]]

(clojure.data/diff (set [1 2 3]) (set [5 9 3 2 3 7]))
;; => [#{1}  #{7 9 5}        #{3 2}]

munge

munge 這個函式並未有文檔,因此只能實際看看用途了

(defn foo [] (println "foo"))
;; =>  #'user/foo

foo
;; => #<user$foo user$foo@a0dc71>

(munge foo)
;; => "user_DOLLARSIGN_foo_CIRCA_a0dc71"


(doseq [c (remove #(Character/isLetterOrDigit %) (map char (range 32 127)))]
  (println c "->" (munge c)))
;; Prints:
;;   ->
;; ! -> _BANG_
;; " -> _DOUBLEQUOTE_
;; # -> _SHARP_
;; $ -> $
;; % -> _PERCENT_
;; & -> _AMPERSAND_
;; ' -> _SINGLEQUOTE_
;; ( -> (
;; ) -> )
;; * -> _STAR_
;; + -> _PLUS_
;; , -> ,
;; - -> _
;; . -> .
;; / -> _SLASH_
;; : -> _COLON_
;; ; -> ;
;; < -> _LT_
;; = -> _EQ_
;; > -> _GT_
;; ? -> _QMARK_
;; @ -> _CIRCA_
;; [ -> _LBRACK_
;; \ -> _BSLASH_
;; ] -> _RBRACK_
;; ^ -> _CARET_
;; _ -> _
;; ` -> `
;; { -> _LBRACE_
;; | -> _BAR_
;; } -> _RBRACE_
;; ~ -> _TILDE_

gensym

gensym 會產生不衝突名稱的 symbol,這個應該是在 macro 實現時,Clojure 所使用到的函式

(gensym "foo")
;; => foo2020

(gensym "foo")
;; => foo2027

seque

seque 是一種 阻塞隊列(Linked Blocking Queue, LBQ) 的實作,這種實現是線程安全(thread safe)的,可以確保資料先進先出(first in first out, FIFO) 的狀況。

(let [start (System/nanoTime)
      q (seque
         (iterate
          #(do (Thread/sleep 400) (inc %))
          0))]
  (println "sleep five seconds...")
  (Thread/sleep 5000)
  (doseq [i (take 20 q)]
    (println (int (/ (- (System/nanoTime) start) 1e7))
             ":" i)))


;; The iterate form returns a lazy seq that delays nearly a half-second
;; before returning each subsequent item.  Here seque starts a thread
;; generating the lazy seq.

;; The body of the let allows the seque thread to get ahead by five seconds
;; before it begins consuming the seq using doseq.  The doseq prints a
;; timestamp and the value from the seq when it becomes available.  The
;; first 11 or so are available almost instantly, until the consuming
;; doseq catches up with the producing iterate, at which point the consumer
;; blocks for 400ms before each item can be printed.

;;sleep five seconds...
500 : 0
500 : 1
500 : 2
500 : 3
500 : 4
500 : 5
500 : 6
500 : 7
500 : 8
500 : 9
500 : 10
500 : 11
520 : 12
;; ......

clojure.zip/zippers

clojure.zip 是用來處理樹狀結構用函式庫,這篇文章有很好的解釋: (λx.Liu)Blog=Hacking: Understand clojure.zip with picture

clojure.zip/zipper 則是用來將資料包裝起來,這樣我們就可以透過 clojure.zip 來處理這些樹狀資料

(def zp (clojure.zip/zipper vector? seq (fn [_ c] c)
                            [[1 2 3] [:a :b] 2 3 [40 50 60]]))
;; => [[[1 2 3] [:a :b] 2 3 [40 50 60]] nil]


(clojure.zip/down zp)
;; =>
[[1 2 3]
 {:l [],
  :pnodes [[[1 2 3] [:a :b] 2 3 [40 50 60]]],
  :ppath nil,
  :r ([:a :b] 2 3 [40 50 60])}]


(-> zp
    clojure.zip/down
    first)
;; =>
[1 2 3]


(-> zp
    clojure.zip/down
    clojure.zip/right)
;; =>
[[:a :b]
 {:l [[1 2 3]],
  :pnodes [[[1 2 3] [:a :b] 2 3 [40 50 60]]],
  :ppath nil,
  :r (2 3 [40 50 60])}]

09月24日

sakananote's face
sakananote


縮小 展開

Open Build Service 實作練習 Workshop 101 小記

Open Build Service 實作練習 Workshop 101

OS: openSUSE Leap 42.1

預先準備

首先設定 API 的 URL
# osc    -A   https://api.opensuse.org

Your user account / password are not configured yet.
You will be asked for them below, and they will be stored in
/root/.oscrc for future use.

Creating osc configuration file /root/.oscrc ...
Username: 輸入帳號
Password: 輸入密碼

建立完之後家目錄會產生  .oscrc  以及 .osc_cookiejar
  • ~/.oscrc 為相關apiurl 以及帳號資訊, 檔案權限為 600, 後續可以用 ring 來處理


使用 osc 指令進行 check out 專案  osc  co   home:使用者帳號
# osc  co  home:sakana

觀察目錄就會出現專案的資料夾
# ls
.bash_history  .dbus        inst-sys        .oscrc    .Xauthority bin            .gnupg       .local          .rnd
.config        home:sakana  .osc_cookiejar  .viminfo

切換到專案目錄
# cd   home\:sakana/

使用 osc mkpac 指令建立 package, 這次workshop 使用的是  ctris
# osc  mkpac   ctris
A    ctris

再次觀察
# ls
ctris  gmchess  Helloworld-test  jUploadr  .osc  owncloud
進入 套件工作目錄
# cd   ctris/

修改 .spec 檔案, 可以參考講師提供的  http://paste.opensuse.org/8035d628
# vi  ctris.spec

Name:           ctris
Summary:        Console based Tetris clone
URL:            http://www.hackl.dhs.org/ctris/
License:        GPL-2.0
Group:          Amusements/Games/Action/Arcade
Version:        0.42
Release:        1
Source:         %{name}-%{version}.tar.bz2
BuildRoot:      %{_tmppath}/%{name}-%{version}-build
BuildRequires:  ncurses-devel
Requires:       ncurses

%description
An ASCII version of the well known game Tetris

%prep
%setup -q

%build
make

%install
%make_install
%debug_package

%clean
rm -rf $RPM_BUILD_ROOT;

%files
%defattr(-,root,root)
%doc AUTHORS COPYING README TODO
%doc %{_mandir}/man6/ctris.6.gz
/usr/games/ctris

%changelog

Notes
  • 在 openSUSE 環境內 #vi  xxxx.spec 會自動套入 .spec 格式
  • BuildRequires 為編譯過程中需要的套件
  • Requires 則為執行需要的套件

抓取套件  source code
# wget  http://goo.gl/zWJXyd -O ctris-0.42.tar.bz2

觀察目錄
# ls
ctris-0.42.tar.bz2  ctris.spec  .osc

觀察.osc 目錄
# ls   .osc/
_apiurl  _files  _osclib_version  _package  _project

使用 osc   vc 指令填寫 chang log
# osc  vc

填入 change log
-------------------------------------------------------------------
Sat Sep 24 07:11:09 UTC 2016 -

- OBS workshop

# ls
ctris-0.42.tar.bz2  ctris.changes  ctris.spec  .osc

觀察目錄
# ls .osc/
_apiurl  _files  _osclib_version  _package  _project

標記要新增或是移除的檔案
# osc   addremove
A    ctris.spec
A    ctris.changes
A    ctris-0.42.tar.bz2

觀察目錄, 多了 _to_be_added
# ls .osc/
_apiurl  _files  _osclib_version  _package  _project  _to_be_added

# cat  .osc/_to_be_added
ctris.spec
ctris.changes
ctris-0.42.tar.bz2

到目前為止都是在 local

接下來進行 commit ( -ci ) 以及上傳到 build.opensuse.org
# osc   ci    -m  "Ya! I am a packager"
Sending meta data...
Done.
Sending    ctris
Sending    ctris/ctris.spec
Sending    ctris/ctris.changes
Sending    ctris/ctris-0.42.tar.bz2
Transmitting file data ..
Committed revision 1.
觀察目錄
# ls .osc/
_apiurl  ctris-0.42.tar.bz2  ctris.changes  ctris.spec  _files  _meta  _osclib_version  _package  _project

接下來要設定套件要編譯的 Repositories ( OS )

到 Web UI
點選  Repositories
點選  Add repositories

螢幕快照 2016-09-24 下午3.18.41.png


針對要加入的 repo 勾選
勾選完之後就會自動 build

螢幕快照 2016-09-24 下午3.24.30.png


到此, 就可以在 OBS 上面享受用一個原始碼編譯出不同平台的便利性
也可以到 http://software.opensuse.org/search 搜尋一下自己的套件觀察 :)
2016-09-24 22-16-56 的螢幕擷圖.png


剛剛是在  build.opensuse.org 上面編譯
那如果要在本機編譯呢?

本地端 編譯  ( 要配合自己有裝的 repo )
可以使用 osc  build 指令 後面加上 repo 以及架構 還有 .spec 檔案
# osc  build  openSUSE_Leap_42.1   x86_64   ctris.spec
Building ctris.spec for openSUSE_Leap_42.1/x86_64
Getting buildinfo from server and store to /root/home:sakana/ctris/.osc/_buildinfo-openSUSE_Leap_42.1-x86_64.xml
Getting buildconfig from server and store to /root/home:sakana/ctris/.osc/_buildconfig-openSUSE_Leap_42.1-x86_64
Updating cache of required packages

The build root needs packages from project 'openSUSE:Leap:42.1'.
Note that malicious packages can compromise the build result or even your system.
Would you like to ...
0 - quit (default)
1 - always trust packages from 'openSUSE:Leap:42.1'
2 - trust packages just this time
? 1
adding 'openSUSE:Leap:42.1' to ~/.oscrc: ['https://api.opensuse.org']['trusted_prj']
100.0% cache miss. 0/100 dependencies cached.

[   34s] RPMLINT report:
[   34s] ===============
[   35s] ctris.x86_64: W: incorrect-fsf-address /usr/share/doc/packages/ctris/COPYING
[   35s] The Free Software Foundation address in this file seems to be outdated or
[   35s] misspelled.  Ask upstream to update the address, or if this is a license file,
[   35s] possibly the entire file with a new copy available from the FSF.
[   35s]
[   35s] ctris.x86_64: W: file-contains-current-date /usr/games/ctris
[   35s] Your file contains the current date, this may cause the package to rebuild in
[   35s] excess.
[   35s]
[   35s] 2 packages and 0 specfiles checked; 0 errors, 2 warnings.
[   35s]
[   35s]
[   35s] template finished "build ctris.spec" at Sat Sep 24 07:38:00 UTC 2016.
[   35s]

/var/tmp/build-root/openSUSE_Leap_42.1-x86_64/home/abuild/rpmbuild/SRPMS/ctris-0.42-1.src.rpm

/var/tmp/build-root/openSUSE_Leap_42.1-x86_64/home/abuild/rpmbuild/RPMS/x86_64/ctris-0.42-1.x86_64.rpm
/var/tmp/build-root/openSUSE_Leap_42.1-x86_64/home/abuild/rpmbuild/RPMS/x86_64/ctris-debuginfo-0.42-1.x86_64.rpm

這邊會看到, 編譯完成之後會放到 /var/tmp 下面的目錄


Lab: 共同協作

那如果想要跟其他人共同維護套件呢?

範例 使用現有的套件

使用 osc  branch 指令建立分支, 這邊是使用講師的 套件
# osc   branch   home:gary_lin   ctris

# cd

切換到工作目錄
# osc   co   home:sakana:branches:home:gary_lin/ctris
A    home:sakana:branches:home:gary_lin
A    home:sakana:branches:home:gary_lin/ctris
A    home:sakana:branches:home:gary_lin/ctris/ctris-0.42.tar.bz2
A    home:sakana:branches:home:gary_lin/ctris/ctris.changes
A    home:sakana:branches:home:gary_lin/ctris/ctris.spec
At revision e1fa18eaa16d59e32af37e7b02af3130.

觀察目錄
# ls
.bash_history  bin  .config  .dbus  .gnupg  home:sakana  home:sakana:branches:home:gary_lin  inst-sys  .local  .osc_cookiejar  .oscrc  .rnd  .viminfo

由於只是 workshop 所以先切換到該套件的工作目錄
# cd   home\:sakana\:branches\:home\:gary_lin/ctris/

測試改動 .spec 內容 ( 這邊我改了 release 版本 )
# vim  ctris.spec

填入 change log
# osc   vc

標記新增或是移除檔案
# osc  addremove

進行 build 動作
$ osc  build  openSUSE_Leap_42.1   x86_64

進行  commit, 此時都是在自己的 home project 上面
$ osc   ci   -m   “another change”

可以到 Subprojects 查詢
螢幕快照 2016-09-24 下午4.23.20.png


透過  osc  submitreq 送出更動請求 ( 像是git 的 pull request )
# osc   submitreq
created request id 429914

這樣就可以完成 協同工作

今天的  workshop 真是收穫良多
謝謝 Gary

~ enjoy it