#3712 download-build: preserve build artefacts last modification time
Merged 2 years ago by tkopecek. Opened 2 years ago by tkopecek.
tkopecek/koji pr3710  into  master

file modified
+9
@@ -607,6 +607,15 @@ 

                      _download_progress(length, pos, filesize)

              if not length and not (quiet or noprogress):

                  _download_progress(pos, pos, filesize)

+             last_modified = response.headers.get('last-modified')

+             if last_modified:

+                 mtime = dateutil.parser.parse(last_modified)

+                 if mtime:

+                     # py 2.6 modifications, see koji.formatTimeLong

+                     if mtime.tzinfo is None:

+                         mtime = mtime.replace(tzinfo=dateutil.tz.gettz())

+                     mtime = mtime.astimezone(dateutil.tz.gettz())

+                     os.utime(relpath, (time.time(), time.mktime(mtime.timetuple())))

      finally:

          f.close()

          if pos == 0:

file modified
+27 -2
@@ -754,7 +754,12 @@ 

              elif dtype == 6:

                  # string (null terminated)

                  end = self.header.find(six.b('\0'), pos)

-                 print("String(%d): %r" % (end - pos, self.header[pos:end]))

+                 try:

+                     print("String(%d): %r" % (end - pos, _decode_item(self.header[pos:end])))

+                 except ValueError:

+                     print('INVALID STRING')

+                     print("String(%d): %r" % (end - pos, self.header[pos:end]))

+                     raise

                  next = end + 1

              elif dtype == 7:

                  print("Data: %s" % hex_string(self.header[pos:pos + count]))
@@ -770,7 +775,11 @@ 

                  # unicode string array

                  for i in range(count):

                      end = self.header.find(six.b('\0'), pos)

-                     print("i18n(%d): %r" % (end - pos, self.header[pos:end]))

+                     try:

+                         print("i18n(%d): %r" % (end - pos, _decode_item(self.header[pos:end])))

+                     except Exception:

+                         print('INVALID STRING')

+                         print("i18n(%d): %r" % (end - pos, self.header[pos:end]))

                      pos = end + 1

                  next = pos

              else:
@@ -807,6 +816,22 @@ 

          elif dtype == 7:

              # raw data

              return self.header[pos:pos + count]

+         elif dtype == 8:

+             # string array

+             result = []

+             for i in range(count):

+                 end = self.header.find(six.b('\0'), pos)

+                 result.append(self.header[pos:end])

+                 pos = end + 1

+             return result

+         elif dtype == 9:

+             # unicode string array

+             result = []

+             for i in range(count):

+                 end = self.header.find(six.b('\0'), pos)

+                 result.append(_decode_item(self.header[pos:end]))

+                 pos = end + 1

+             return result

          else:

              # XXX - not all valid data types are handled

              raise GenericError("Unable to read header data type: %x" % dtype)

@@ -56,9 +56,10 @@ 

          else:

              self.assertEqual(cm.exception.args, (21, 'Is a directory'))

  

+     @mock.patch('os.utime')

      @mock.patch('os.unlink')

      @mock_open()

-     def test_handle_download_file(self, m_open, os_unlink):

+     def test_handle_download_file(self, m_open, os_unlink, os_utime):

          self.reset_mock()

          m_open.return_value.tell.return_value = 0

          rsp_head = self.head.return_value
@@ -66,7 +67,10 @@ 

          rsp_head.headers = {'Content-Length': '5'}

          response = mock.MagicMock()

          self.get_mock.return_value = response

-         response.headers.get.return_value = '5'  # content-length

+         response.headers.get.side_effect = [

+             '5',        # content-length

+             'Thu, 02 Mar 2023 11:21:12 GMT',  # last-modified

+         ]

          response.iter_content.return_value = ['abcde']

  

          rv = download_file("http://url", self.filename)
@@ -76,8 +80,7 @@ 

          self.assertMultiLineEqual(actual, expected)

  

          self.get_mock.assert_called_once()

-         m_open.assert_called_once()

-         response.headers.get.assert_not_called()

+         response.headers.get.assert_called_once()

          response.iter_content.assert_called_once()

          self.assertIsNone(rv)

  
@@ -90,9 +93,9 @@ 

          rsp_head.status_code = 200

          rsp_head.headers = {'Content-Length': str(65536 * 2)}

          response = mock.MagicMock()

-         self.get_mock.return_value = response

          response.headers.get.return_value = None  # content-length

          response.iter_content.return_value = ['a' * 65536, 'b' * 65536]

+         self.get_mock.return_value = response

  

          rv = download_file("http://url", self.filename)

  
@@ -103,19 +106,30 @@ 

  

          self.get_mock.assert_called_once()

          m_open.assert_called_once()

-         response.headers.get.assert_not_called()

+         response.headers.get.assert_called_once()

          response.iter_content.assert_called_once()

          self.assertIsNone(rv)

  

      def test_handle_download_file_with_size(self):

+         response = mock.MagicMock()

+         response.headers.get.side_effect = [

+             '5',        # content-length

+             '2022-01-01',  # last-modified

+         ]

+         self.get_mock.return_value = response

          rv = download_file("http://url", self.filename, size=10, num=8)

          actual = self.stdout.getvalue()

          expected = 'Downloading [8/10]: %s\n\n' % self.filename

          self.assertMultiLineEqual(actual, expected)

          self.get_mock.assert_called_once()

+         self.assertEqual(len(response.headers.get.mock_calls), 2)

          self.assertIsNone(rv)

  

      def test_handle_download_file_quiet_noprogress(self):

+         response = mock.MagicMock()

+         response.headers.get.return_value = None

+         self.get_mock.return_value = response

+ 

          download_file("http://url", self.filename, quiet=True, noprogress=False)

          actual = self.stdout.getvalue()

          expected = ''

Metadata Update from @tkopecek:
- Pull-request tagged with: testing-ready

2 years ago

rebased onto 14eeca5

2 years ago

3 new commits added

  • fix tests
  • fix py26 compatibility
  • download-build: preserve build artefacts last modification time
2 years ago

3 new commits added

  • attempt to decode strings in dump
  • also support get for unicode string arrays
  • RawHeader.get can return also string lists
2 years ago

Metadata Update from @relias-redhat:
- Pull-request tagged with: testing-done

2 years ago

Commit 7c96362 fixes this pull-request

Pull-Request has been merged by tkopecek

2 years ago

Hmm, it looks like most of the changes from #3714 were inadvertently applied here before merging