Merge pull request #576 from mcuadros/clone-tags

Repository.Clone added Tags option, and set by default AllTags 
diff --git a/options.go b/options.go
index 26002e4..9f10aae 100644
--- a/options.go
+++ b/options.go
@@ -50,6 +50,9 @@
 	// stored, if nil nothing is stored and the capability (if supported)
 	// no-progress, is sent to the server to avoid send this information.
 	Progress sideband.Progress
+	// Tags describe how the tags will be fetched from the remote repository,
+	// by default is AllTags.
+	Tags TagMode
 }
 
 // Validate validates the fields and sets the default values.
@@ -66,6 +69,10 @@
 		o.ReferenceName = plumbing.HEAD
 	}
 
+	if o.Tags == InvalidTagMode {
+		o.Tags = AllTags
+	}
+
 	return nil
 }
 
@@ -103,18 +110,19 @@
 	return nil
 }
 
-type TagFetchMode int
+type TagMode int
 
-var (
+const (
+	InvalidTagMode TagMode = iota
 	// TagFollowing any tag that points into the histories being fetched is also
 	// fetched. TagFollowing requires a server with `include-tag` capability
 	// in order to fetch the annotated tags objects.
-	TagFollowing TagFetchMode = 0
+	TagFollowing
 	// AllTags fetch all tags from the remote (i.e., fetch remote tags
 	// refs/tags/* into local tags with the same name)
-	AllTags TagFetchMode = 1
+	AllTags
 	//NoTags fetch no tags from the remote at all
-	NoTags TagFetchMode = 2
+	NoTags
 )
 
 // FetchOptions describes how a fetch should be performed
@@ -133,7 +141,7 @@
 	Progress sideband.Progress
 	// Tags describe how the tags will be fetched from the remote repository,
 	// by default is TagFollowing.
-	Tags TagFetchMode
+	Tags TagMode
 }
 
 // Validate validates the fields and sets the default values.
@@ -142,6 +150,10 @@
 		o.RemoteName = DefaultRemoteName
 	}
 
+	if o.Tags == InvalidTagMode {
+		o.Tags = TagFollowing
+	}
+
 	for _, r := range o.RefSpecs {
 		if err := r.Validate(); err != nil {
 			return err
diff --git a/remote.go b/remote.go
index 1c9d1cd..3e24763 100644
--- a/remote.go
+++ b/remote.go
@@ -279,7 +279,7 @@
 		}
 	}
 
-	updated, err := r.updateLocalReferenceStorage(o.RefSpecs, refs, remoteRefs)
+	updated, err := r.updateLocalReferenceStorage(o.RefSpecs, refs, remoteRefs, o.Tags)
 	if err != nil {
 		return nil, err
 	}
@@ -481,10 +481,17 @@
 	return result, nil
 }
 
-func calculateRefs(spec []config.RefSpec,
+const refspecTag = "+refs/tags/*:refs/tags/*"
+
+func calculateRefs(
+	spec []config.RefSpec,
 	remoteRefs storer.ReferenceStorer,
-	tags TagFetchMode,
+	tagMode TagMode,
 ) (memory.ReferenceStorage, error) {
+	if tagMode == AllTags {
+		spec = append(spec, refspecTag)
+	}
+
 	iter, err := remoteRefs.IterReferences()
 	if err != nil {
 		return nil, err
@@ -493,9 +500,7 @@
 	refs := make(memory.ReferenceStorage, 0)
 	return refs, iter.ForEach(func(ref *plumbing.Reference) error {
 		if !config.MatchAny(spec, ref.Name()) {
-			if !ref.Name().IsTag() || tags != AllTags {
-				return nil
-			}
+			return nil
 		}
 
 		if ref.Type() == plumbing.SymbolicReference {
@@ -645,6 +650,7 @@
 func (r *Remote) updateLocalReferenceStorage(
 	specs []config.RefSpec,
 	fetchedRefs, remoteRefs memory.ReferenceStorage,
+	tagMode TagMode,
 ) (updated bool, err error) {
 	isWildcard := true
 	for _, spec := range specs {
@@ -674,6 +680,10 @@
 		}
 	}
 
+	if tagMode == NoTags {
+		return updated, nil
+	}
+
 	tags := fetchedRefs
 	if isWildcard {
 		tags = remoteRefs
diff --git a/remote_test.go b/remote_test.go
index 51180ce..10f6708 100644
--- a/remote_test.go
+++ b/remote_test.go
@@ -143,7 +143,7 @@
 	s.testFetch(c, r, &FetchOptions{
 		Tags: NoTags,
 		RefSpecs: []config.RefSpec{
-			config.RefSpec("+refs/heads/master:refs/remotes/origin/master"),
+			config.RefSpec("+refs/heads/*:refs/remotes/origin/*"),
 		},
 	}, []*plumbing.Reference{
 		plumbing.NewReferenceFromStrings("refs/remotes/origin/master", "f7b877701fbf855b44c0a9e86f3fdce2c298b07f"),
diff --git a/repository.go b/repository.go
index fbc7871..b86054f 100644
--- a/repository.go
+++ b/repository.go
@@ -440,6 +440,7 @@
 		Depth:    o.Depth,
 		Auth:     o.Auth,
 		Progress: o.Progress,
+		Tags:     o.Tags,
 	}, o.ReferenceName)
 	if err != nil {
 		return err
diff --git a/repository_test.go b/repository_test.go
index 6184949..4480484 100644
--- a/repository_test.go
+++ b/repository_test.go
@@ -177,6 +177,27 @@
 	c.Assert(err, NotNil)
 }
 
+func (s *RepositorySuite) TestCloneWithTags(c *C) {
+	url := s.GetLocalRepositoryURL(
+		fixtures.ByURL("https://github.com/git-fixtures/tags.git").One(),
+	)
+
+	r, err := Clone(memory.NewStorage(), nil, &CloneOptions{URL: url, Tags: NoTags})
+	c.Assert(err, IsNil)
+
+	remotes, err := r.Remotes()
+	c.Assert(err, IsNil)
+	c.Assert(remotes, HasLen, 1)
+
+	i, err := r.References()
+	c.Assert(err, IsNil)
+
+	var count int
+	i.ForEach(func(r *plumbing.Reference) error { count++; return nil })
+
+	c.Assert(count, Equals, 3)
+}
+
 func (s *RepositorySuite) TestCreateRemoteAndRemote(c *C) {
 	r, _ := Init(memory.NewStorage(), nil)
 	remote, err := r.CreateRemote(&config.RemoteConfig{