Repository: iterative/dvc

Issue:
Exeption when importing binary file on python 3
Traceback (most recent call last):                                                        
  File "/storage/git/dvc/dvc/main.py", line 21, in main                                   
    ret = instance.run()                                                                  
  File "/storage/git/dvc/dvc/command/import_file.py", line 51, in run                     
    self.import_files(targets, self.parsed_args.lock, self.parsed_args.jobs)              
  File "/storage/git/dvc/dvc/command/import_file.py", line 120, in import_files           
    self.create_state_files(imported_targets, lock)                                       
  File "/storage/git/dvc/dvc/command/import_file.py", line 145, in create_state_files     
    state_file.save()                                                                     
  File "/storage/git/dvc/dvc/state_file.py", line 209, in save                            
    self.update_target_metrics()                                                          
  File "/storage/git/dvc/dvc/state_file.py", line 110, in update_target_metrics           
    target_metric = StateFile.try_parse_target_metric(data_file)                          
  File "/storage/git/dvc/dvc/state_file.py", line 130, in try_parse_target_metric         
    return StateFile.parse_target_metric(file_name)                                       
  File "/storage/git/dvc/dvc/state_file.py", line 116, in parse_target_metric             
    lines = open(file_name, 'r').readlines(2)                                             
  File "/home/efiop/virtenvs/python3-dvc/lib64/python3.4/codecs.py", line 319, in decode  
    (result, consumed) = self._buffer_decode(data, self.errors, final)                    
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8b in position 1: invalid start byte



Discussion:

Resolving patch:
diff --git a/dvc/command/merge.py b/dvc/command/merge.py
--- a/dvc/command/merge.py
+++ b/dvc/command/merge.py
@@ -10,37 +10,37 @@ def __init__(self, settings):
         super(CmdMerge, self).__init__(settings)
 
     def print_info(self, targets):
-        for fname in targets:
+        for item in targets:
             Logger.info('Restored original data after merge:')
-            Logger.info(' {}'.format(fname))
+            Logger.info(' {}'.format(item.data.relative))
 
     def collect_targets(self):
         targets = []
         flist = self.git.get_last_merge_changed_files()
-        for fname in flist:
-            try:
-                item = self.settings.path_factory.data_item(fname)
-            except NotInDataDirError:
-                continue
+        items = self.settings.path_factory.to_data_items(flist)[0]
 
+        for item in items:
             try:
                 state = StateFile.load(item, self.git)
             except Exception as ex:
-                Logger.error('Failed to load state file for {}'.format(fname), exc_info=True)
+                Logger.error('Failed to load state file for {}'.format(item.data.relative), exc_info=True)
                 return None
 
             if not state.command == StateFile.COMMAND_IMPORT_FILE:
                 continue
 
-            targets.append(fname)
+            targets.append(item)
 
         return targets
 
     def checkout_targets(self, targets):
-        for fname in targets:
-            self.git.checkout_file_before_last_merge(fname)
+        data = []
+        for item in targets:
+            self.git.checkout_file_before_last_merge(item.data.relative)
+            self.git.checkout_file_before_last_merge(item.state.relative)
+            data.append(item.data.relative)
 
-        msg = 'DVC merge files: {}'.format(' '.join(targets))
+        msg = 'DVC merge files: {}'.format(' '.join(data))
         self.commit_if_needed(msg)
 
     def run(self):
diff --git a/dvc/command/repro.py b/dvc/command/repro.py
--- a/dvc/command/repro.py
+++ b/dvc/command/repro.py
@@ -78,7 +78,7 @@ def repro_data_items(self, data_item_list, recursive, force):
 
         for data_item in data_item_list:
             try:
-                target_commit = self.git.get_target_commit(data_item.data.relative)
+                target_commit = self.git.get_target_commit(data_item.state.relative)
                 if target_commit is None:
                     msg = 'Data item "{}" cannot be reproduced: cannot obtain commit hashsum'
                     Logger.warn(msg.format(data_item.data.relative))
diff --git a/dvc/state_file.py b/dvc/state_file.py
--- a/dvc/state_file.py
+++ b/dvc/state_file.py
@@ -113,7 +113,13 @@ def update_target_metrics(self):
 
     @staticmethod
     def parse_target_metric(file_name):
-        lines = open(file_name).readlines(2)
+        fd = open(file_name, 'r')
+
+        try:
+            lines = fd.readlines(2)
+        except Exception as e:
+            raise StateFileError('Unable to parse target file')
+
         if len(lines) != 1:
             raise StateFileError('file contains more then one line')
 


Test patch: