Google Documents List Data API 共有編

Googleドキュメント上のファイルの共有は,以下のように行います。

本当は「リンクを知っている全員」への共有を行いたかったのですが,あれこれ設定を変えて試しても,「ウェブ上で一般公開」の共有にしかできませんでした。

    GDataCredentials^ c = gcnew GDataCredentials(email, password);
    RequestSettings^ r = gcnew RequestSettings(appname, c);
    DocumentsRequest^ dr = gcnew DocumentsRequest(r);
    Document^ doc = SortTable[sel]->GetDoc();
    DocumentEntry^ entry = doc->DocumentEntry;
    AclQuery^ query = gcnew AclQuery(entry->AccessControlList);
    AclFeed^ aclFeed = dr->Service->Query(query);
    AclEntry^ aclentry = gcnew AclEntry();
    aclentry->Role = gcnew AclRole("reader");
    AclScope^ scope = gcnew AclScope();
    scope->Type = AclScope::SCOPE_DEFAULT;
    scope->Value = "";
    aclentry->Scope = scope;
    aclFeed->Insert(aclentry);
    dr->Service->Query(query);
カテゴリー: 技術メモ | コメントをどうぞ

Gerritを約1年運用してみて

Gerritを利用して拙作のLhazをオープンソース化してから,1年が過ぎようとしています。ここで,Gerritの良い点,悪い点をまとめます。GitHubやSourceForgeを使用した経験はないので,他の開発プラットフォームと比較した結果ではありません。運用中のレビューサイトはこちらになります。

良い点

gitが身についた

Gerritはgitベースですので,gitの使い方が身につきました。add, commitなどの基本的なコマンドはgitのみの運用でも身につくかと思いますが,Gerritではpushやコンフリクトの解決にrebaseが必要だったりして,やや進んだ使い方が身につきます。また,Lhazの開発では,zlib等の外部ライブラリを使用しており,mergeも使ったりしました。

ブランチがGerrit上で可視化されるのも良いと思います。具体的には,zlib等をmasterブランチ,lhazブランチと分けて,開発元の更新はmaster,自分で手を加えた部分はlhaz,でトラッキングしていますが,このような感じで流れが分かります。

コラボレーション

Gerritでは複数人で開発を進めていきますが,コードレビューしたりされたりで,人の書いたコードをじっくり見ることができ,たいへん参考になります。2ペインで左に更新前,右に更新後,と差分が見やすいのも気に入っています。自分のレビュースタイルは,動いてるならいいんじゃない?,といったあっさりしたものですが,1ライン単位でレビューコメントを記載できるので,ネチネチ派?の方も使い出があるのではと思います。

Lhaz開発メンバーから文字列クラスのリノベーションをご提案頂き,1プロジェクトとしてインテグレートさせて頂いたのですが,自分には馴染みの少ないテンプレートが駆使されているC++らしいコードで,とても勉強になりました。

仕事(Androidスマートフォン開発)でもGerritを使用していますが,コミットのアップロードやマージがあった際にメールで通知を受けることができるので,相当広い範囲に目を配ることができます。

モチベーション

Gerritにpushして,レビューして,+1 Verified,+2 Looks good to me, approved,のスコアがついた後,「Submit Patch Set」というボタンを押して,変更がブランチにマージされます。この瞬間,小さな達成感があり,気持ちよいです。早く次の変更を入れたくなるので,開発が継続していきます。

そして,過去のコミットを振り返ると,開発の歴史そのものですので,「よくがんばったな」「続けていこう」という気になれます。この辺りは特にGerrit固有ということはないですが。

悪い点

とっつきにくい?

こちらのWikiにてLhazの開発参加方法を説明していますが,自分で見ても始めるのが面倒くさそうです(実際はそうでもないと思いますが…)。Lhazでこれまでコミット頂けたのもまだ4名の方で,あまり気軽にトライできないのかな,と思われます。

また,GitHubのように自分で試せる公開Gerritサーバといったものはないので,自分でサーバを用意してGerritをインストールしていくのも,ひと手間いります。 review.chitora.com でホスティングすることも可能ですので,使ってみたい方はご連絡ください。

 コードレビュー専用

Gerritは純粋なコードレビューツールですので,設計に使用することは難しいです(全てテキストファイルで設計すれば可能かもしれませんが)。また,タスク管理やプロジェクト管理,バグ管理もできません。この辺りは,SourceForge等の方が強いと思います。Lhaz開発では,別途Redmineを使用して,それらの管理を行っています。逆に,コードレビュー専用だけに,セットアップさえ済めば,運用上はボタンを押すだけのシンプルさ,とも言えるかもしれません。

カテゴリー: 技術メモ | コメントをどうぞ

歌集・句集

吟醸の 香に添い調ぶ 蟋蟀の 歌に酔うらん 長き月夜に
多摩川の 小川に見えし エジプトの ナイルを眺め 帰り来たれば
満開の 桜のもとに 笑う君 心配するな 尽くせ全力
命とる 物のほどかは 靖国の 桜となりし 学徒思へば

カテゴリー: 文系 | コメントをどうぞ

開発をつぶやく

Gerritのmergeフックを利用して,ソースの変化をTwitterにつぶやく方法です。

Gerritにソースをpushして,レビューアにapproveされて,Submitボタンを押して変更がマージされると,下記スクリプトが実行されます(「review_site」はGerritのインストール先です)。

review_site/hooks/change-merged

実行される際のパラメータは,以下のようになります。

change-merged --change <change id> --change-url <change url> --project <project name> --branch <branch> --submitter <submitter> --commit <sha1>
  • change id: Gerrit上のURLの連番
  • change url: GerritのURL
  • project name: gitのリポジトリ名
  • branch: マージされたリモートブランチ名
  • submitter: 変更をpushした人
  • sha1: コミットのhash

ツイート内容として,

[プロジェクト] コミットコメントのサブジェクト GerritレビューURL

例) [lhaz] Clean up of sort kind/reverse http://review.chitora.com/#change,497

とつぶやきたい場合,change-mergedスクリプトの内容を以下のようにします。

#!/bin/sh
URL=$4
PROJECT=$6
SHA1=$12
cd ../git/$6.git
TITLE=`git show -s --format="%s" $SHA1`
twt "[$PROJECT] $TITLE $URL"

それぞれ引数を変数に引き取り,

cd ../git/$6.git

にてgitリポジトリのディレクトリに移動します。hooksから見た相対位置になります。

TITLE=`git show -s --format="%s" $SHA1`

はコミットのサブジェクトを取り出すgitコマンドになります。
twtは自作のコマンドラインでツイートするツールですが,類似のものが使用できると思います。

カテゴリー: 技術メモ | コメントをどうぞ

Windows Update で無線LANのドライバが消える

HP Pavilion Desktop PC s5750jp CTにオプションの 802.11b/g/n 対応ワイヤレスMini card LAN を装着していますが,最近の Windows Update でデバイスドライバが消える,という現象が起きました。OSは,Windows7 64bitを使用しています。

Ralinkのドライバを更新 (3.1.9.0→3.2.1.0)して一時は解決できたかに見えたのですが,日を開けてPCを起動すると,問題が再発していました。

このため,現時点では「システムの復元」でPCの状態を少し前に戻して無線LANで接続しています。

解決しました。ワイアレスマウスの電池が少なくなっていたのが真の原因でした。有線マウスに換えたところ,Windows Update最新の状態で問題なく無線LANが使えるようになりました。お騒がせしました。

有線マウスでも再現してしまいました。無線LANのHW故障が疑われます。面倒なので外付けのメディアコンバーターを購入します。

カテゴリー: 技術メモ | コメントをどうぞ

Google Documents List Data API アップロード編

無変換で Google Document にファイルをアップロードするためには, ResumableUploader を使います。 file はファイルへのフルパスになります。

ClientLoginAuthenticator^ cla = gcnew ClientLoginAuthenticator(
    "App",
    ServiceNames::Documents,
    email,
    password
);
ResumableUploader^ ru = gcnew ResumableUploader();
Document^ entry = gcnew Document();
entry->Title = "タイトル";
entry->MediaSource = gcnew MediaFileSource(file, "application/octet-stream");
Uri^ createUploadUrl = gcnew Uri("https://docs.google.com/feeds/upload/create-session/default/private/full/?convert=false");
AtomLink^ link = gcnew AtomLink(createUploadUrl->AbsoluteUri);
link->Rel = ResumableUploader::CreateMediaRelation;
entry->DocumentEntry->Links->Add(link);
ru->InsertAsync(cla, entry->DocumentEntry, gcnew Object);
カテゴリー: 技術メモ | コメントをどうぞ

Google Documents List Data API ダウンロード編

ファイルのダウンロードには, DocumentsRequest.Download を使用します。以下のサンプルでは,再度リストを取得しています。これは, Document^ の寿命が分かっていないためです。初めのリスト取得で doc->Id が保存してあり, UI でダウンロード対象が m_id として指定されます。今回のリスト取得で比較を行い,一致した場合はダウンロードします。

また,ネイティブクラスのメンバにマネージドクラスへのポインタ(この場合, Document^ )を持たせる方法もよく分かっていないため,上記方法をとっています。

Stream からバッファに一気に読み込む処理がありそうなのですが, .NET がよく分かっていないので1KBずつ読み出しています。

GDataCredentials^ c = gcnew GDataCredentials(email, pass);
RequestSettings^ r = gcnew RequestSettings("App", c);
DocumentsRequest^ dr = gcnew DocumentsRequest(r);
Feed^ feed = dr->GetEverything();
for each (Document^ doc in feed->Entries) {
    marshal_context^ context = gcnew marshal_context();
    MYSTR id = context->marshal_as(doc->Id);
    delete context;
    if (id == m_id) {
        Stream^ s = dr->Download(doc, "");
        MYBUF buf;
        array^ bytes = gcnew array(1024);
        pin_ptr p = &bytes[0];
        for (;;) {
            int n = s->Read(bytes, 0, 1024);
            if (n == 0)
                break;
            buf.Add(n, p);
        }
カテゴリー: 技術メモ | コメントをどうぞ

Google Documents List Data API リスト編

Retrieving a list of documents では, DocumentsService を使用してファイル一覧を取得していますが,後でファイルをダウンロードするときに使う DocumentsRequest.Download に Document を渡す必要があるため, DocumentsRequest を使用してフィードを取得します。

サンプルソースは以下のようになります。

GDataCredentials^ c = gcnew GDataCredentials(email, password);
RequestSettings^ r = gcnew RequestSettings("App", c);
DocumentsRequest^ dr = gcnew DocumentsRequest(r);
Feed^ feed = dr->GetEverything();
for each (Document^ doc in feed->Entries) {
    DocumentEntry^ entry = doc->DocumentEntry;
    entry->Title->Text; // タイトル
    entry->Updated;     // 更新時刻
}
カテゴリー: 技術メモ | コメントをどうぞ

Google Documents List Data API

Google Documents List Data API が気になってきた。

C++からだと.NET Client Libraryが呼び出せる模様。(自分はC/C++しか使えないので)。

まずライブラリをダウンロードする。http://code.google.com/p/google-gdata/downloads/list から Google_Data_API_Setup_1.8.0.0.msi をインストールする。

以下,呼び側アプリのプロジェクトに移る。

[全般の共通言語ランタイムサポート]の値を「共通言語ランタイムサポート (/clr)」に設定する。

Cソースが含まれる場合は,[C/C++]-[詳細設定]-[コンパイル言語の選択]-[C++コードとしてコンパイル(/TP)]に設定する。

[C/C++]-[全般]-[#using参照の解決]に C:\Program Files\Google\Google Data API SDK\Redist を指定する。

C++/CLIのコーディングは,http://www.atmarkit.co.jp/fdotnet/special/cppcli/cppcli_03.html が参考になる。

GData APIの呼び出しは,

#using <Google.GData.Documents.dll>
#using <Google.GData.Client.dll>
#using <Google.GData.Extensions.dll>

using namespace Google;
using namespace Google::GData;
using namespace Google::GData::Documents;

DocumentsService ^myService = gcnew DocumentsService("exampleCo-exampleApp-1");
myService->setUserCredentials("jo@gmail.com", "mypassword");

このような感じでいけそう。少なくともコンパイルは出来た。Cソース部分でC++としてコンパイルすることからのエラーが出ていて,まだリンクは完了してない。よって動作は未確認。

リンク完了後,動作確認予定。Google Docsも使用開始しておこう。

カテゴリー: 技術メモ | コメントをどうぞ

XSDでCOLLADA

COLLADAのとっかりはこちら。COLLADA DOMを使った3Dモデルデータの読み込み

XSDはこちら。CodeSynthesis XSD

おおまかな流れとしては,

  • XSDをVisual Studioに導入する
  • COLLADA 1.4.1 Schema (includes OpenGL ES Profile)をローカルに保存する。
  • 保存したSchemaをソリューションに追加して,XSDでC++パーサにコンパイルする。
  • コンパイルオプションはこちらにあるように–parts 3等で分割指定が必須。
  • コンパイルしたC++パーサをソリューションに追加する。
  • COLLADAの読み込み部分を作成する。1行で読み込めるが初めから高速化に対応した方がよい。
  • OpenGLの表示処理を作成する。パース結果の利用方法(triangleのみ描画)は下記。
using namespace COLLADASchema;
const COLLADA::library_geometries_sequence& g = bhc->m_dae_preview->library_geometries();
for (COLLADA::library_geometries_const_iterator i = g.begin(); i != g.end(); i++) {
  const library_geometries::geometry_sequence& h = (*i).geometry();
  for (library_geometries::geometry_const_iterator j = h.begin(); j != h.end(); j++) {
    const mesh::triangles_sequence& t = (*j).mesh()->triangles();
    for (mesh::triangles_const_iterator k = t.begin(); k != t.end(); k++) {
      unsigned int numberOfInputs = (*k).input().size();
      unsigned int numberOfTriangles = (*k).p()->size() / numberOfInputs;
      unsigned int offset = 0;
      int texoffset = -255;
      int noroffset = -255;
      for (triangles::input_const_iterator l = (*k).input().begin(); l != (*k).input().end(); l++) {
        if ((*l).semantic() == "VERTEX")
          offset = (*l).offset();
        if ((*l).semantic() == "TEXCOORD")
          texoffset = (*l).offset();
        if ((*l).semantic() == "NORMAL")
          noroffset = (*l).offset();
      }
      for (int ii = 0; ii < numberOfTriangles; ii++) {
        int index = (*k).p()->at(ii * numberOfInputs + offset);
        if (noroffset == -255) {
          glNormal3f(
            (*j).mesh()->source().at(1).float_array()->at(index * 3),
            (*j).mesh()->source().at(1).float_array()->at(index * 3 + 1),
            (*j).mesh()->source().at(1).float_array()->at(index * 3 + 2)
          );
        } else {
          int norindex = (*k).p()->at(ii * numberOfInputs + noroffset);
          glNormal3f(
            (*j).mesh()->source().at(1).float_array()->at(norindex * 3),
            (*j).mesh()->source().at(1).float_array()->at(norindex * 3 + 1),
            (*j).mesh()->source().at(1).float_array()->at(norindex * 3 + 2)
          );
        }
        if (texoffset != -255) {
          int texindex = (*k).p()->at(ii * numberOfInputs + texoffset);
          glTexCoord2f(
            (*j).mesh()->source().at(2).float_array()->at(texindex * 2),
            (*j).mesh()->source().at(2).float_array()->at(texindex * 2 + 1)
          );
        }
        glVertex3f(
          (*j).mesh()->source().at(0).float_array()->at(index * 3),
          (*j).mesh()->source().at(0).float_array()->at(index * 3 + 1),
          (*j).mesh()->source().at(0).float_array()->at(index * 3 + 2)
        );
      }
    }
  }
}

m_dae_previewは,

std::auto_ptr<COLLADASchema::COLLADA>   m_dae_preview;

というデータメンバで,COLLADAをロードした結果を保持している。

COLLADA DOMより少し速度が遅いし,分かりやすさもないので,COLLADAをパースしてみたい人は素直にCOLLADA DOMを使った方がよいかも。

カテゴリー: BH | コメントをどうぞ