Initialize dart-lang/tuple with the tuple package at v1.0.1.

---
Update README.google.

Merge tag 'v1.0.1' of ../tuple-orig

Merge pull request #2 from nex3/strong

Fix all strong-mode warnings and errors
Fix all strong-mode warnings and errors.

Setup Travis CI.

Update CHANGELOG.md and bump the version to 1.0.0.

Remove _hash function and use hash functions provided by quiver_hashcode.

Merge pull request #1 from srawlins/complete-changelog

Complete changelog
Complete changelog

Bump the version to 0.4.0.

Add CHANGELOG.md.

Add fromList factory constructor.

Add me to AUTHROS.

Add Tuple6 and Tuple7 classes.

Bump the version to 0.3.0.

Add toList() to tuple classes.

Add .pub and doc to .gitignore.

Add API documentation to tuple classes.

Bump the version to 0.2.0.

Redesign the tuple API.

* Rename PersistentTuple to Tuple and remove mutable tuple classes.
* Rename iN to itemN.
* Rename setIN to withItemN.

Bump the version to 0.1.2.

* Add me as an author.
* Change homepage to https://github.com/kseo/tuple.

Add test cases for tuple.

Fix a bug in == operator of PersistentTuple classes.

Check if o is of PersistentTuple type, not Tuple.

0.1.1

Merge pull request #3 from kseo/mapkey

Override operator == and hashCode.
Merge pull request #2 from kseo/addoverride

Add @override annotation to toString().
Merge pull request #1 from kseo/gitignore

Add .packages file to .gitignore.
Add @override annotation to toString().

Add .packages file to .gitignore.

As of 1.12, the .packages file exists after running pub get. Don’t check it
into source control.

Override operator == and hashCode.

This makes it possible to use tuples as keys in maps.

Initial commit

BUG=
R=devoncarew@google.com, whesse@google.com

Review-Url: https://codereview.chromium.org/2939773003 .
diff --git a/.analysis_options b/.analysis_options
new file mode 100644
index 0000000..a10d4c5
--- /dev/null
+++ b/.analysis_options
@@ -0,0 +1,2 @@
+analyzer:
+  strong-mode: true
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c944841
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,28 @@
+# https://www.dartlang.org/tools/private-files.html
+
+pubspec.lock
+
+build/
+.packages
+packages
+
+.pub
+doc
+
+.buildlog
+*.js_
+*.js.deps
+*.js.map
+*.dart.js
+
+# Eclipse
+.project
+
+# IntelliJ
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# Mac
+.DS_Store
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..a4a70c4
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,8 @@
+language: dart
+sudo: false
+dart:
+  - stable
+  - dev
+script: ./tool/travis.sh
+env:
+  - DARTANALYZER_FLAGS=--fatal-warnings
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..d653058
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,8 @@
+# Below is a list of people and organizations that have contributed
+# to the tuple project. Names should be added to the list like
+# so:
+#
+#   Name/Organization <email address>
+
+Boris Kaul <localvoid@gmail.com>
+Kwang Yul Seo <kwangyul.seo@gmail.com>
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..77d2a47
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,27 @@
+#### 1.0.1
+   * Fix all strong-mode warnings and errors.
+
+#### 1.0.0
+   * Remove _hash function and use quiver_hashcode package instead.
+
+#### 0.4.0
+   * Add fromList factory constructor.
+   * Add Tuple6 and Tuple7 classes.
+
+#### 0.3.0
+   * Add toList method.
+
+#### 0.2.0
+   * Rename PersistentTuple classes to Tuple; remove Tuple classes.
+   * Rename each iN item to itemN.
+   * Rename setIN to withItemN.
+
+#### 0.1.2
+   * Fix a bug in == operator of PersistentTuple classes.
+
+#### 0.1.1
+   * Add operator == and hashCode to classes, so that tuples may be used as
+     keys in hashes.
+
+#### 0.1.0
+   * Initial release.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..c024562
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2014, the tuple project authors.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/README.google b/README.google
index 70d0e9a..89f8df3 100644
--- a/README.google
+++ b/README.google
@@ -6,6 +6,7 @@
 License: BSD 2-clause "Simplified" License
 
 Description:
-This directory contains the tuple package as downloaded from
-https://github.com/kseo/tuple/archive/v1.0.1.tar.gz on June
-13, 2017.
+This directory contains the tuple package as checked
+out from git@github.com:kseo/tuple.git at tag v1.0.1
+on June 13, 2017.
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..61c0db1
--- /dev/null
+++ b/README.md
@@ -0,0 +1,21 @@
+# Tuple data structure
+
+- [Tuple2], [Tuple3]...
+
+[![Build Status](https://travis-ci.org/kseo/tuple.svg)](https://travis-ci.org/kseo/tuple)
+[![Coverage Status](https://coveralls.io/repos/kseo/tuple/badge.svg?branch=master&service=github)](https://coveralls.io/github/kseo/tuple?branch=master)
+
+## Usage example
+
+```dart
+const t = const Tuple2<String, int>('a', 10);
+
+print(t.item1); // prints 'a'
+print(t.item2); // prints '10'
+```
+
+```dart
+final t1 = const Tuple2<String, int>('a', 10);
+final t2 = t1.withItem1('c');
+// t2 is a new [Tuple2] object with item1 is 'c' and item2 is 10.
+```
diff --git a/lib/src/tuple.dart b/lib/src/tuple.dart
new file mode 100644
index 0000000..2dace3f
--- /dev/null
+++ b/lib/src/tuple.dart
@@ -0,0 +1,481 @@
+// Copyright (c) 2014, the tuple project authors. Please see the AUTHORS
+// file for details. All rights reserved. Use of this source code is governed
+// by a BSD-style license that can be found in the LICENSE file.
+
+part of tuple;
+
+/// Represents a 2-tuple, or pair.
+class Tuple2<T1, T2> {
+  /// Returns the first item of the tuple
+  final T1 item1;
+
+  /// Returns the second item of the tuple
+  final T2 item2;
+
+  /// Creates a new tuple value with the specified items.
+  const Tuple2(this.item1, this.item2);
+
+  /// Create a new tuple value with the specified list [items].
+  factory Tuple2.fromList(List items) {
+    if (items.length != 2) {
+      throw new ArgumentError('items must have length 2');
+    }
+
+    return new Tuple2<T1, T2>(items[0] as T1, items[1] as T2);
+  }
+
+  /// Returns a tuple with the first item set to the specified value.
+  Tuple2<T1, T2> withItem1(T1 v) {
+    return new Tuple2<T1, T2>(v, item2);
+  }
+
+  /// Returns a tuple with the second item set to the specified value.
+  Tuple2<T1, T2> withItem2(T2 v) {
+    return new Tuple2<T1, T2>(item1, v);
+  }
+
+  /// Creates a [List] containing the items of this [Tuple2].
+  ///
+  /// The elements are in item order. The list is variable-length
+  /// if [growable] is true.
+  List toList({bool growable: false}) =>
+      new List.from([item1, item2], growable: growable);
+
+  @override
+  String toString() => '[$item1, $item2]';
+
+  @override
+  bool operator ==(o) => o is Tuple2 && o.item1 == item1 && o.item2 == item2;
+
+  @override
+  int get hashCode => hash2(item1.hashCode, item2.hashCode);
+}
+
+/// Represents a 3-tuple, or triple.
+class Tuple3<T1, T2, T3> {
+  /// Returns the first item of the tuple
+  final T1 item1;
+
+  /// Returns the second item of the tuple
+  final T2 item2;
+
+  /// Returns the third item of the tuple
+  final T3 item3;
+
+  /// Creates a new tuple value with the specified items.
+  const Tuple3(this.item1, this.item2, this.item3);
+
+  /// Create a new tuple value with the specified list [items].
+  factory Tuple3.fromList(List items) {
+    if (items.length != 3) {
+      throw new ArgumentError('items must have length 3');
+    }
+
+    return new Tuple3<T1, T2, T3>(
+        items[0] as T1, items[1] as T2, items[2] as T3);
+  }
+
+  /// Returns a tuple with the first item set to the specified value.
+  Tuple3<T1, T2, T3> withItem1(T1 v) {
+    return new Tuple3<T1, T2, T3>(v, item2, item3);
+  }
+
+  /// Returns a tuple with the second item set to the specified value.
+  Tuple3<T1, T2, T3> withItem2(T2 v) {
+    return new Tuple3<T1, T2, T3>(item1, v, item3);
+  }
+
+  /// Returns a tuple with the third item set to the specified value.
+  Tuple3<T1, T2, T3> withItem3(T3 v) {
+    return new Tuple3<T1, T2, T3>(item1, item2, v);
+  }
+
+  /// Creates a [List] containing the items of this [Tuple3].
+  ///
+  /// The elements are in item order. The list is variable-length
+  /// if [growable] is true.
+  List toList({bool growable: false}) =>
+      new List.from([item1, item2, item3], growable: growable);
+
+  @override
+  String toString() => '[$item1, $item2, $item3]';
+
+  @override
+  bool operator ==(o) =>
+      o is Tuple3 && o.item1 == item1 && o.item2 == item2 && o.item3 == item3;
+
+  @override
+  int get hashCode => hash3(item1.hashCode, item2.hashCode, item3.hashCode);
+}
+
+/// Represents a 4-tuple, or quadruple.
+class Tuple4<T1, T2, T3, T4> {
+  /// Returns the first item of the tuple
+  final T1 item1;
+
+  /// Returns the second item of the tuple
+  final T2 item2;
+
+  /// Returns the third item of the tuple
+  final T3 item3;
+
+  /// Returns the fourth item of the tuple
+  final T4 item4;
+
+  /// Creates a new tuple value with the specified items.
+  const Tuple4(this.item1, this.item2, this.item3, this.item4);
+
+  /// Create a new tuple value with the specified list [items].
+  factory Tuple4.fromList(List items) {
+    if (items.length != 4) {
+      throw new ArgumentError('items must have length 4');
+    }
+
+    return new Tuple4<T1, T2, T3, T4>(
+        items[0] as T1, items[1] as T2, items[2] as T3, items[3] as T4);
+  }
+
+  /// Returns a tuple with the first item set to the specified value.
+  Tuple4<T1, T2, T3, T4> withItem1(T1 v) {
+    return new Tuple4<T1, T2, T3, T4>(v, item2, item3, item4);
+  }
+
+  /// Returns a tuple with the second item set to the specified value.
+  Tuple4<T1, T2, T3, T4> withItem2(T2 v) {
+    return new Tuple4<T1, T2, T3, T4>(item1, v, item3, item4);
+  }
+
+  /// Returns a tuple with the third item set to the specified value.
+  Tuple4<T1, T2, T3, T4> withItem3(T3 v) {
+    return new Tuple4<T1, T2, T3, T4>(item1, item2, v, item4);
+  }
+
+  /// Returns a tuple with the fourth item set to the specified value.
+  Tuple4<T1, T2, T3, T4> withItem4(T4 v) {
+    return new Tuple4<T1, T2, T3, T4>(item1, item2, item3, v);
+  }
+
+  /// Creates a [List] containing the items of this [Tuple4].
+  ///
+  /// The elements are in item order. The list is variable-length
+  /// if [growable] is true.
+  List toList({bool growable: false}) =>
+      new List.from([item1, item2, item3, item4], growable: growable);
+
+  @override
+  String toString() => '[$item1, $item2, $item3, $item4]';
+
+  @override
+  bool operator ==(o) => o is Tuple4 &&
+      o.item1 == item1 &&
+      o.item2 == item2 &&
+      o.item3 == item3 &&
+      o.item4 == item4;
+
+  @override
+  int get hashCode =>
+      hash4(item1.hashCode, item2.hashCode, item3.hashCode, item4.hashCode);
+}
+
+/// Represents a 5-tuple, or quintuple.
+class Tuple5<T1, T2, T3, T4, T5> {
+  /// Returns the first item of the tuple
+  final T1 item1;
+
+  /// Returns the second item of the tuple
+  final T2 item2;
+
+  /// Returns the third item of the tuple
+  final T3 item3;
+
+  /// Returns the fourth item of the tuple
+  final T4 item4;
+
+  /// Returns the fifth item of the tuple
+  final T5 item5;
+
+  /// Creates a new tuple value with the specified items.
+  const Tuple5(this.item1, this.item2, this.item3, this.item4, this.item5);
+
+  /// Create a new tuple value with the specified list [items].
+  factory Tuple5.fromList(List items) {
+    if (items.length != 5) {
+      throw new ArgumentError('items must have length 5');
+    }
+
+    return new Tuple5<T1, T2, T3, T4, T5>(items[0] as T1, items[1] as T2,
+        items[2] as T3, items[3] as T4, items[4] as T5);
+  }
+
+  /// Returns a tuple with the first item set to the specified value.
+  Tuple5<T1, T2, T3, T4, T5> withItem1(T1 v) {
+    return new Tuple5<T1, T2, T3, T4, T5>(v, item2, item3, item4, item5);
+  }
+
+  /// Returns a tuple with the second item set to the specified value.
+  Tuple5<T1, T2, T3, T4, T5> withItem2(T2 v) {
+    return new Tuple5<T1, T2, T3, T4, T5>(item1, v, item3, item4, item5);
+  }
+
+  /// Returns a tuple with the third item set to the specified value.
+  Tuple5<T1, T2, T3, T4, T5> withItem3(T3 v) {
+    return new Tuple5<T1, T2, T3, T4, T5>(item1, item2, v, item4, item5);
+  }
+
+  /// Returns a tuple with the fourth item set to the specified value.
+  Tuple5<T1, T2, T3, T4, T5> withItem4(T4 v) {
+    return new Tuple5<T1, T2, T3, T4, T5>(item1, item2, item3, v, item5);
+  }
+
+  /// Returns a tuple with the fifth item set to the specified value.
+  Tuple5<T1, T2, T3, T4, T5> withItem5(T5 v) {
+    return new Tuple5<T1, T2, T3, T4, T5>(item1, item2, item3, item4, v);
+  }
+
+  /// Creates a [List] containing the items of this [Tuple5].
+  ///
+  /// The elements are in item order. The list is variable-length
+  /// if [growable] is true.
+  List toList({bool growable: false}) =>
+      new List.from([item1, item2, item3, item4, item5], growable: growable);
+
+  @override
+  String toString() => '[$item1, $item2, $item3, $item4, $item5]';
+
+  @override
+  bool operator ==(o) => o is Tuple5 &&
+      o.item1 == item1 &&
+      o.item2 == item2 &&
+      o.item3 == item3 &&
+      o.item4 == item4 &&
+      o.item5 == item5;
+
+  @override
+  int get hashCode => hashObjects([
+        item1.hashCode,
+        item2.hashCode,
+        item3.hashCode,
+        item4.hashCode,
+        item5.hashCode
+      ]);
+}
+
+/// Represents a 6-tuple, or sextuple.
+class Tuple6<T1, T2, T3, T4, T5, T6> {
+  /// Returns the first item of the tuple
+  final T1 item1;
+
+  /// Returns the second item of the tuple
+  final T2 item2;
+
+  /// Returns the third item of the tuple
+  final T3 item3;
+
+  /// Returns the fourth item of the tuple
+  final T4 item4;
+
+  /// Returns the fifth item of the tuple
+  final T5 item5;
+
+  /// Returns the sixth item of the tuple
+  final T6 item6;
+
+  /// Creates a new tuple value with the specified items.
+  const Tuple6(
+      this.item1, this.item2, this.item3, this.item4, this.item5, this.item6);
+
+  /// Create a new tuple value with the specified list [items].
+  factory Tuple6.fromList(List items) {
+    if (items.length != 6) {
+      throw new ArgumentError('items must have length 6');
+    }
+
+    return new Tuple6<T1, T2, T3, T4, T5, T6>(items[0] as T1, items[1] as T2,
+        items[2] as T3, items[3] as T4, items[4] as T5, items[5] as T6);
+  }
+
+  /// Returns a tuple with the first item set to the specified value.
+  Tuple6<T1, T2, T3, T4, T5, T6> withItem1(T1 v) {
+    return new Tuple6<T1, T2, T3, T4, T5, T6>(
+        v, item2, item3, item4, item5, item6);
+  }
+
+  /// Returns a tuple with the second item set to the specified value.
+  Tuple6<T1, T2, T3, T4, T5, T6> withItem2(T2 v) {
+    return new Tuple6<T1, T2, T3, T4, T5, T6>(
+        item1, v, item3, item4, item5, item6);
+  }
+
+  /// Returns a tuple with the third item set to the specified value.
+  Tuple6<T1, T2, T3, T4, T5, T6> withItem3(T3 v) {
+    return new Tuple6<T1, T2, T3, T4, T5, T6>(
+        item1, item2, v, item4, item5, item6);
+  }
+
+  /// Returns a tuple with the fourth item set to the specified value.
+  Tuple6<T1, T2, T3, T4, T5, T6> withItem4(T4 v) {
+    return new Tuple6<T1, T2, T3, T4, T5, T6>(
+        item1, item2, item3, v, item5, item6);
+  }
+
+  /// Returns a tuple with the fifth item set to the specified value.
+  Tuple6<T1, T2, T3, T4, T5, T6> withItem5(T5 v) {
+    return new Tuple6<T1, T2, T3, T4, T5, T6>(
+        item1, item2, item3, item4, v, item6);
+  }
+
+  /// Returns a tuple with the sixth item set to the specified value.
+  Tuple6<T1, T2, T3, T4, T5, T6> withItem6(T6 v) {
+    return new Tuple6<T1, T2, T3, T4, T5, T6>(
+        item1, item2, item3, item4, item5, v);
+  }
+
+  /// Creates a [List] containing the items of this [Tuple5].
+  ///
+  /// The elements are in item order. The list is variable-length
+  /// if [growable] is true.
+  List toList({bool growable: false}) =>
+      new List.from([item1, item2, item3, item4, item5, item6],
+          growable: growable);
+
+  @override
+  String toString() => '[$item1, $item2, $item3, $item4, $item5, $item6]';
+
+  @override
+  bool operator ==(o) => o is Tuple6 &&
+      o.item1 == item1 &&
+      o.item2 == item2 &&
+      o.item3 == item3 &&
+      o.item4 == item4 &&
+      o.item5 == item5 &&
+      o.item6 == item6;
+
+  @override
+  int get hashCode => hashObjects([
+        item1.hashCode,
+        item2.hashCode,
+        item3.hashCode,
+        item4.hashCode,
+        item5.hashCode,
+        item6.hashCode
+      ]);
+}
+
+/// Represents a 7-tuple, or septuple.
+class Tuple7<T1, T2, T3, T4, T5, T6, T7> {
+  /// Returns the first item of the tuple
+  final T1 item1;
+
+  /// Returns the second item of the tuple
+  final T2 item2;
+
+  /// Returns the third item of the tuple
+  final T3 item3;
+
+  /// Returns the fourth item of the tuple
+  final T4 item4;
+
+  /// Returns the fifth item of the tuple
+  final T5 item5;
+
+  /// Returns the sixth item of the tuple
+  final T6 item6;
+
+  /// Returns the seventh item of the tuple
+  final T7 item7;
+
+  /// Creates a new tuple value with the specified items.
+  const Tuple7(this.item1, this.item2, this.item3, this.item4, this.item5,
+      this.item6, this.item7);
+
+  /// Create a new tuple value with the specified list [items].
+  factory Tuple7.fromList(List items) {
+    if (items.length != 7) {
+      throw new ArgumentError('items must have length 7');
+    }
+
+    return new Tuple7<T1, T2, T3, T4, T5, T6, T7>(
+        items[0] as T1,
+        items[1] as T2,
+        items[2] as T3,
+        items[3] as T4,
+        items[4] as T5,
+        items[5] as T6,
+        items[6] as T7);
+  }
+
+  /// Returns a tuple with the first item set to the specified value.
+  Tuple7<T1, T2, T3, T4, T5, T6, T7> withItem1(T1 v) {
+    return new Tuple7<T1, T2, T3, T4, T5, T6, T7>(
+        v, item2, item3, item4, item5, item6, item7);
+  }
+
+  /// Returns a tuple with the second item set to the specified value.
+  Tuple7<T1, T2, T3, T4, T5, T6, T7> withItem2(T2 v) {
+    return new Tuple7<T1, T2, T3, T4, T5, T6, T7>(
+        item1, v, item3, item4, item5, item6, item7);
+  }
+
+  /// Returns a tuple with the third item set to the specified value.
+  Tuple7<T1, T2, T3, T4, T5, T6, T7> withItem3(T3 v) {
+    return new Tuple7<T1, T2, T3, T4, T5, T6, T7>(
+        item1, item2, v, item4, item5, item6, item7);
+  }
+
+  /// Returns a tuple with the fourth item set to the specified value.
+  Tuple7<T1, T2, T3, T4, T5, T6, T7> withItem4(T4 v) {
+    return new Tuple7<T1, T2, T3, T4, T5, T6, T7>(
+        item1, item2, item3, v, item5, item6, item7);
+  }
+
+  /// Returns a tuple with the fifth item set to the specified value.
+  Tuple7<T1, T2, T3, T4, T5, T6, T7> withItem5(T5 v) {
+    return new Tuple7<T1, T2, T3, T4, T5, T6, T7>(
+        item1, item2, item3, item4, v, item6, item7);
+  }
+
+  /// Returns a tuple with the sixth item set to the specified value.
+  Tuple7<T1, T2, T3, T4, T5, T6, T7> withItem6(T6 v) {
+    return new Tuple7<T1, T2, T3, T4, T5, T6, T7>(
+        item1, item2, item3, item4, item5, v, item7);
+  }
+
+  /// Returns a tuple with the seventh item set to the specified value.
+  Tuple7<T1, T2, T3, T4, T5, T6, T7> withItem7(T7 v) {
+    return new Tuple7<T1, T2, T3, T4, T5, T6, T7>(
+        item1, item2, item3, item4, item5, item6, v);
+  }
+
+  /// Creates a [List] containing the items of this [Tuple5].
+  ///
+  /// The elements are in item order. The list is variable-length
+  /// if [growable] is true.
+  List toList({bool growable: false}) =>
+      new List.from([item1, item2, item3, item4, item5, item6, item7],
+          growable: growable);
+
+  @override
+  String toString() =>
+      '[$item1, $item2, $item3, $item4, $item5, $item6, $item7]';
+
+  @override
+  bool operator ==(o) => o is Tuple7 &&
+      o.item1 == item1 &&
+      o.item2 == item2 &&
+      o.item3 == item3 &&
+      o.item4 == item4 &&
+      o.item5 == item5 &&
+      o.item5 == item6 &&
+      o.item6 == item7;
+
+  @override
+  int get hashCode => hashObjects([
+        item1.hashCode,
+        item2.hashCode,
+        item3.hashCode,
+        item4.hashCode,
+        item5.hashCode,
+        item6.hashCode,
+        item7.hashCode
+      ]);
+}
diff --git a/lib/tuple.dart b/lib/tuple.dart
new file mode 100644
index 0000000..149fd7c
--- /dev/null
+++ b/lib/tuple.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2014, the tuple project authors. Please see the AUTHORS
+// file for details. All rights reserved. Use of this source code is governed
+// by a BSD-style license that can be found in the LICENSE file.
+
+/// # Tuple data structure
+///
+/// - [Tuple2], [Tuple3]...
+///
+/// ## Usage example
+///
+/// ```dart
+/// const t = const Tuple2<String, int>('a', 10);
+///
+/// print(t.item1); // prints 'a'
+/// print(t.item2); // prints '10'
+/// ```
+///
+/// ```dart
+/// const t1 = const Tuple2<String, int>('a', 10);
+/// final t2 = t1.withItem1('c');
+/// // t2 is a new [Tuple2] object with item1 is 'c' and item2 is 10.
+/// ```
+library tuple;
+
+import 'package:quiver_hashcode/hashcode.dart';
+
+part 'package:tuple/src/tuple.dart';
diff --git a/pubspec.yaml b/pubspec.yaml
new file mode 100644
index 0000000..48bc8c3
--- /dev/null
+++ b/pubspec.yaml
@@ -0,0 +1,13 @@
+name: tuple
+version: 1.0.1
+authors:
+- Boris Kaul <localvoid@gmail.com>
+- Kwang Yul Seo <kwangyul.seo@gmail.com>
+description: Tuple data structure
+homepage: https://github.com/kseo/tuple
+environment:
+  sdk: '>=1.6.0'
+dependencies:
+  quiver_hashcode: '>=1.0.0-dev.1 <1.1.0'
+dev_dependencies:
+  test: any
diff --git a/test/all_tests.dart b/test/all_tests.dart
new file mode 100644
index 0000000..6cf9e29
--- /dev/null
+++ b/test/all_tests.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2015, the tuple project authors. Please see the AUTHORS
+// file for details. All rights reserved. Use of this source code is governed
+// by a BSD-style license that can be found in the LICENSE file.
+
+library tuple.test;
+
+import 'tuple_test.dart' as tuple_test;
+
+main() {
+  tuple_test.main();
+}
diff --git a/test/tuple_test.dart b/test/tuple_test.dart
new file mode 100644
index 0000000..4bbe0cf
--- /dev/null
+++ b/test/tuple_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2015, the tuple project authors. Please see the AUTHORS
+// file for details. All rights reserved. Use of this source code is governed
+// by a BSD-style license that can be found in the LICENSE file.
+
+library tuple.test;
+
+import 'package:test/test.dart';
+import 'package:tuple/tuple.dart';
+
+main() {
+  group("Tuple tests", () {
+    final t = new Tuple2<int, bool>(1, true);
+
+    test('items', () {
+      expect(t.item1, equals(1));
+      expect(t.item2, equals(true));
+    });
+
+    test('withItems', () {
+      expect(t.withItem1(2), equals(new Tuple2<int, bool>(2, true)));
+      expect(t.withItem2(false), equals(new Tuple2<int, bool>(1, false)));
+    });
+
+    test('create a tuple from a list of items', () {
+      final t1 = new Tuple2.fromList([1, true]);
+      expect(t1.item1, equals(1));
+      expect(t1.item2, equals(true));
+
+      expect(() => new Tuple2.fromList([1]), throwsA(new isInstanceOf<ArgumentError>()));
+      expect(() => new Tuple2.fromList([1, true, 'a']), throwsA(new isInstanceOf<ArgumentError>()));
+    });
+
+    test('equality', () {
+      final otherT = new Tuple2<int, bool>(1, true);
+      expect(t, equals(otherT));
+    });
+
+    test('nested equality', () {
+      final t1 = new Tuple2<Tuple2<int, String>, bool>(
+          new Tuple2<int, String>(3, 'a'), false);
+      final t2 = new Tuple2<Tuple2<int, String>, bool>(
+          new Tuple2<int, String>(3, 'a'), false);
+      expect(t1, equals(t2));
+    });
+
+    test('can be used as keys in maps', () {
+      final map = {t: 'a'};
+      final key = new Tuple2<int, bool>(1, true);
+      expect(map[key], equals('a'));
+    });
+
+    test('toList() should return a listing containing the items of the tuple',
+        () {
+      expect(t.toList(), orderedEquals([1, true]));
+    });
+
+    test('toList() should return a fixed list by default', () {
+      expect(() => t.toList().add(3),
+          throwsA(new isInstanceOf<UnsupportedError>()));
+    });
+
+    test('toList(growable: true) should return a growable list', () {
+      expect(t.toList(growable: true)..add('a'), orderedEquals([1, true, 'a']));
+    });
+  });
+}
diff --git a/tool/travis.sh b/tool/travis.sh
new file mode 100755
index 0000000..61c101b
--- /dev/null
+++ b/tool/travis.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# Copyright (c) 2015, Google Inc. Please see the AUTHORS file for details.
+# All rights reserved. Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# Fast fail the script on failures.
+set -e
+
+# Verify that the libraries are error and warning-free.
+echo "Running dartanalyzer..."
+libs=$(find lib -maxdepth 1 -type f -name '*.dart')
+dartanalyzer $DARTANALYZER_FLAGS $libs test/all_tests.dart
+
+# Run the tests.
+echo "Running tests..."
+pub run test:test
+
+# Gather and send coverage data.
+if [ "$REPO_TOKEN" ] && [ "$TRAVIS_DART_VERSION" = "stable" ]; then
+  echo "Collecting coverage..."
+  pub global activate dart_coveralls
+  pub global run dart_coveralls report \
+    --token $REPO_TOKEN \
+    --retry 2 \
+    --exclude-test-files \
+    test/all_tests.dart
+fi