support git lfs fetch
diff --git a/manifest_xml.py b/manifest_xml.py
index a7fe8dd..abab35e 100644
--- a/manifest_xml.py
+++ b/manifest_xml.py
@@ -799,6 +799,11 @@
       if node.getAttribute('force-path').lower() in ("yes", "true", "1"):
         gitdir = os.path.join(self.topdir, '%s.git' % path)
 
+    lfs_fetch = node.getAttribute('lfs-fetch')
+    if not lfs_fetch:
+      lfe_fetch = False
+    else:
+      lfs_fetch = lfs_fetch.lower() in ("yes", "true", "1")
     project = Project(manifest = self,
                       name = name,
                       remote = remote.ToRemoteSpec(name),
@@ -816,6 +821,7 @@
                       upstream = upstream,
                       parent = parent,
                       dest_branch = dest_branch,
+                      lfs_fetch = lfs_fetch,
                       **extra_proj_attrs)
 
     for n in node.childNodes:
diff --git a/project.py b/project.py
index 5d8f61e..12be924 100644
--- a/project.py
+++ b/project.py
@@ -549,7 +549,7 @@
 class Project(object):
   # These objects can be shared between several working trees.
   shareable_files = ['description', 'info']
-  shareable_dirs = ['hooks', 'objects', 'rr-cache', 'svn']
+  shareable_dirs = ['hooks', 'objects', 'rr-cache', 'svn', 'lfs']
   # These objects can only be used by a single working tree.
   working_tree_files = ['config', 'packed-refs', 'shallow']
   working_tree_dirs = ['logs', 'refs']
@@ -573,7 +573,8 @@
                is_derived=False,
                dest_branch=None,
                optimized_fetch=False,
-               old_revision=None):
+               old_revision=None,
+	       lfs_fetch=False):
     """Init a Project object.
 
     Args:
@@ -598,6 +599,7 @@
       optimized_fetch: If True, when a project is set to a sha1 revision, only
                        fetch from the remote if the sha1 is not present locally.
       old_revision: saved git commit id for open GITC projects.
+      lfs_fetch: git lfs fetch
     """
     self.manifest = manifest
     self.name = name
@@ -650,6 +652,7 @@
     # This will be filled in if a project is later identified to be the
     # project containing repo hooks.
     self.enabled_repo_hooks = []
+    self.lfs_fetch = lfs_fetch
 
   @property
   def Derived(self):
@@ -1086,6 +1089,17 @@
 
 
 ## Sync ##
+  def __FetchLfsObjects(self, name, refs):
+    if 'refs/heads/*' in refs:
+      refs = []
+      for ref in GitRefs(self.objdir).all:
+        if ref.startswith(R_HEADS):
+          refs.append(ref)
+    cmd = ['lfs', 'fetch']
+    cmd.append(name)
+    cmd.extend(refs)
+    gitcmd = GitCommand(self, cmd, bare=True)
+    ret = gitcmd.Wait()
 
   def _ExtractArchive(self, tarpath, path=None):
     """Extract the given tar on its current location
@@ -1908,20 +1922,23 @@
     else:
       cmd.append('--tags')
 
+    refs = []
     spec = []
     if not current_branch_only:
       # Fetch whole repo
       spec.append(str((u'+refs/heads/*:') + remote.ToLocal('refs/heads/*')))
+      if self.manifest.IsMirror: refs.append('refs/heads/*')
     elif tag_name is not None:
       spec.append('tag')
       spec.append(tag_name)
+      refs.append(tag_name)
 
     if not self.manifest.IsMirror:
       branch = self.revisionExpr
       if is_sha1 and depth and git_require((1, 8, 3)):
         # Shallow checkout of a specific commit, fetch from that commit and not
         # the heads only as the commit might be deeper in the history.
-        spec.append(branch)
+        spec.append(branch)        
       else:
         if is_sha1:
           branch = self.upstream
@@ -1929,6 +1946,7 @@
           if not branch.startswith('refs/'):
             branch = R_HEADS + branch
           spec.append(str((u'+%s:' % branch) + remote.ToLocal(branch)))
+          refs.append(remote.ToLocal(branch))
     cmd.extend(spec)
 
     ok = False
@@ -1980,7 +1998,8 @@
           self.clone_depth = None
           return self._RemoteFetch(name=name, current_branch_only=current_branch_only,
                                    initial=False, quiet=quiet, alt_dir=alt_dir)
-
+    if self.lfs_fetch:
+      self.__FetchLfsObjects(name, refs)
     return ok
 
   def _ApplyCloneBundle(self, initial=False, quiet=False):
@@ -2203,6 +2222,12 @@
           self.config.SetString('core.bare', 'true')
         else:
           self.config.SetString('core.bare', None)
+
+        if self.lfs_fetch:
+          self.config.SetString('filter.lfs.clean', 'git-lfs clean %f')
+          self.config.SetString('filter.lfs.smudge', 'git-lfs smudge %f')  
+          self.config.SetString('filter.lfs.required', 'true')
+
     except Exception:
       if init_obj_dir and os.path.exists(self.objdir):
         shutil.rmtree(self.objdir)