Sunday, May 27, 2012

Beginning Pub Packaging in Dart

‹prev | My Chain | next›

I have been pleasantly surprised at how well my old Dart code has held up. I am also glad that my grasp of the language has not deteriorated during my SPDY break. I am left in the somewhat unexpected state of not needing to do as much as I had planned to keep things fresh as I refresh some of the chapters in Dart for Hipsters. Still, I want to keep focused on Dart for a little while longer, so I will take some time tonight to look at something that definitely popped up while I was on sabbatical: the pub packaging tool.

I am grateful to Allan MacDonald for pointing me to a mailing list discussion on this very topic in which Bob Nystrom describes how to use pub in the dart sdk, which I conveniently have.

So I return to my Dart-powered, client-side comic book application. It turns out that I am in dire need of some help here working with the Hipster MVC library. As I make changes to the application itself, I invariably need to make a change to Hipster MVC. And I wind up in a state something like:
➜  dart-comics git:(modal-dialog) ✗ git status
# On branch modal-dialog
# Changes to be committed:
#   (use "git reset HEAD ..." to unstage)
#
# new file:   public/scripts/HipsterCollection.dart
# new file:   public/scripts/HipsterHistory.dart
# new file:   public/scripts/HipsterModel.dart
# new file:   public/scripts/HipsterRouter.dart
# new file:   public/scripts/HipsterSync.dart
# new file:   public/scripts/HipsterView.dart
#
# Changes not staged for commit:
#   (use "git add ..." to update what will be committed)
#   (use "git checkout -- ..." to discard changes in working directory)
#
# modified:   public/scripts/Collections.Comics.dart
# modified:   public/scripts/HipsterCollection.dart
# modified:   public/scripts/HipsterHistory.dart
# modified:   public/scripts/HipsterModel.dart
# modified:   public/scripts/HipsterRouter.dart
# modified:   public/scripts/HipsterSync.dart
# modified:   public/scripts/HipsterView.dart
# modified:   public/scripts/ModalDialog.dart
# modified:   public/scripts/Models.ComicBook.dart
# modified:   public/scripts/Views.AddComic.dart
# modified:   public/scripts/Views.AddComicForm.dart
# modified:   public/scripts/Views.Comics.dart
# modified:   public/scripts/main.dart
#
# Untracked files:
#   (use "git add ..." to include in what will be committed)
#
# public/scripts/ComicBook.dart
# public/scripts/ComicBook.tmpl
A lot of that is actual changes to dart comics, but there is also much noise added by removing local copies and replacing them with symbolic links to my local Hipster MVC repository:
➜  dart-comics git:(modal-dialog) ✗ ls -l public/scripts/Hipster*
lrwxrwxrwx 1 chris chris 43 May 24 22:26 public/scripts/HipsterCollection.dart -> ../../../hipster-mvc/HipsterCollection.dart
lrwxrwxrwx 1 chris chris 40 May 24 22:26 public/scripts/HipsterHistory.dart -> ../../../hipster-mvc/HipsterHistory.dart
lrwxrwxrwx 1 chris chris 38 May 24 22:26 public/scripts/HipsterModel.dart -> ../../../hipster-mvc/HipsterModel.dart
lrwxrwxrwx 1 chris chris 39 May 24 22:26 public/scripts/HipsterRouter.dart -> ../../../hipster-mvc/HipsterRouter.dart
lrwxrwxrwx 1 chris chris 37 May 24 22:26 public/scripts/HipsterSync.dart -> ../../../hipster-mvc/HipsterSync.dart
lrwxrwxrwx 1 chris chris 37 May 24 22:26 public/scripts/HipsterView.dart -> ../../../hipster-mvc/HipsterView.dart
Anyhow, hopefully pub can help somewhat—even in its infancy.

I remove those local copies of Hipster MVC and am left with just the local changes, of which there are many. With the clutter out of the way, I have a look at those changes to see that many of them are replacing references to the raw GitHub resources with local references:
diff --git a/public/scripts/main.dart b/public/scripts/main.dart
index da0067b..21c0bd8 100644
--- a/public/scripts/main.dart
+++ b/public/scripts/main.dart
@@ -5,7 +5,7 @@
 #import('dart:html');
 #import('dart:json');
 
-#import('https://raw.github.com/eee-c/hipster-mvc/master/HipsterSync.dart');
+#import('HipsterSync.dart');
 
 main() {
   // HipsterSync.sync = localSync;
Hrm... I don't think that pub is going to help much when I need to edit local copies instead of use the remote resources—at least not yet. Hopefully at some point, pub will get something like npm's link, which allows developers to override package management installs with local copies. I won't worry about that too much since pub is little more than preview release.

One of the first things that my dart comics application does is load in my comics collection from the backend:
main() {
  var my_comics_collection = new Collections.Comics()
    , comics_view = new Views.Comics(
        el:'#comics-list',
        collection: my_comics_collection
      );

  my_comics_collection.fetch();
  // ...
}
I think that Collections.Comics may be ripe for pub-ification:
#library('Collection class to describe my comic book collection');

#import('https://raw.github.com/eee-c/hipster-mvc/master/HipsterCollection.dart');

#import('Models.ComicBook.dart');

class Comics extends HipsterCollection {
  get url() => '/comics';
  modelMaker(_) => new ComicBook();
}
Specifically, that #import() from raw.github.com would be much cleaner as a package line:
#library('Collection class to describe my comic book collection');

#import('package:hipster-mvc/HipsterCollection.dart');

#import('Models.ComicBook.dart');

class Comics extends HipsterCollection {
  get url() => '/comics';
  modelMaker(_) => new ComicBook();
}
If I try to load the app with the package line, I get the following in the Dart console:
Failed to load resource: the server responded with a status of 404 (Not Found)
   http://localhost:3000/scripts/packages/hipster-mvc/HipsterCollection.dart
Nice! It seems that my Dartium is, in fact, pub-aware since the filed URL was in scripts/packages.

In my scripts directory, I create a pubspec file that describes dart-comics' dependencies:
dependencies:
  hipster-mvc:
    git: git://github.com/eee-c/hipster-mvc.git
With that, I am ready to pub-install my Hipster MVC dependency:
➜  scripts git:(modal-dialog) ✗ pub install
Cloning into '/home/chris/repos/dart-comics/public/scripts/packages/hipster-mvc'...
remote: Counting objects: 859, done.
remote: Compressing objects: 100% (174/174), done.
remote: Total 859 (delta 755), reused 780 (delta 676)
Receiving objects: 100% (859/859), 434.36 KiB | 127 KiB/s, done.
Resolving deltas: 100% (755/755), done.
Dependencies installed!
And indeed, I do have a packages directory:
➜  scripts git:(pub-packages) ✗ gst
# On branch pub-packages
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   Collections.Comics.dart
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       packages/
#       pubspec
no changes added to commit (use "git add" and/or "git commit -a")
And Hipster MVC is in there:
➜  scripts git:(pub-packages) ✗ find packages | grep -v \\.git
packages
packages/hipster-mvc
packages/hipster-mvc/HipsterHistory.dart
packages/hipster-mvc/HipsterModel.dart
packages/hipster-mvc/HipsterSync.dart
packages/hipster-mvc/HipsterRouter.dart
packages/hipster-mvc/README.asciidoc
packages/hipster-mvc/HipsterView.dart
packages/hipster-mvc/HipsterCollection.dart
packages/hipster-mvc/main.dart
Most importantly, my dart comics application is back in business:


Last up tonight, I add the packages to the list of files ignored by git:
➜  scripts git:(pub-packages) ✗ echo packages >> .gitignore
There is no reason that I would ever want that directory checked into my git repository—especially since the packages directory is made up of git repositories.

That was a pretty nice first experience with pub packaging. I think I will continue playing with it tomorrow.


Day #399

No comments:

Post a Comment