Merge lp:~andrea.corbellini/software-properties/fix-621977 into lp:software-properties

Proposed by Andrea Corbellini
Status: Needs review
Proposed branch: lp:~andrea.corbellini/software-properties/fix-621977
Merge into: lp:software-properties
Diff against target: 307 lines (+44/-40)
2 files modified
add-apt-repository (+13/-10)
softwareproperties/SoftwareProperties.py (+31/-30)
To merge this branch: bzr merge lp:~andrea.corbellini/software-properties/fix-621977
Reviewer Review Type Date Requested Status
Andrea Corbellini (community) Needs Resubmitting
Barry Warsaw (community) Needs Fixing
Robert Roth (community) Approve
Review via email: mp+134815@code.launchpad.net

Description of the change

This branch fixes bug #621977 in the following way:

1. deb-src lines are added, but commented out, so that Software Properties still lets you enable them later;

2. a new -s, --enable-source command line option is added so that you can add uncommented deb-src line with a single command.

To post a comment you must log in.
Revision history for this message
Robert Roth (evfool) wrote :

The patch looks fine with one minor detail: lots of unchanged lines are added to the diff (probably because tab/spaces usage - whitespace differences). It would be nice if you could set up your editor to use spaces instead of tabs (I think software-properties uses spaces instead of tabs) to avoid harder-to-review diffs, because the reviewer has to filter the real changes.

Other than that: nice solution to comment the source line by default, but leave an option to enable the source with the same command.

review: Approve
Revision history for this message
Andrea Corbellini (andrea.corbellini) wrote :

> The patch looks fine with one minor detail: lots of unchanged lines are added
> to the diff (probably because tab/spaces usage - whitespace differences). It
> would be nice if you could set up your editor to use spaces instead of tabs (I
> think software-properties uses spaces instead of tabs) to avoid harder-to-
> review diffs, because the reviewer has to filter the real changes.

Actually I'm using spaces for indentation. The problem with the diff is caused by the fact that my editor automatically removes trailing whitespace characters. Anyhow, sorry about that :-)

> Other than that: nice solution to comment the source line by default, but
> leave an option to enable the source with the same command.

Thanks!

Revision history for this message
Barry Warsaw (barry) wrote :

The diff looks fine, and while the whitespace cleanups are distracting, I personally appreciate all that trailing whitespace not hurting my eyes :)

I'll go ahead and sponsor this into Raring. Thanks for your contribution to Ubuntu!

review: Approve
Revision history for this message
Barry Warsaw (barry) wrote :

Whoops, this causes some test failures. I think they're shallow -- let's see.

Revision history for this message
Barry Warsaw (barry) wrote :

1 failure, 1 error:

======================================================================
ERROR: test_add_remove_source_by_line (__main__.TestDBus)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_dbus.py", line 248, in test_add_remove_source_by_line
    self.iface.RemoveSource(s.replace("deb", "deb-src"))
  File "/usr/lib/python2.7/dist-packages/dbus/proxies.py", line 145, in __call__
    **keywords)
  File "/usr/lib/python2.7/dist-packages/dbus/connection.py", line 651, in call_blocking
    message, timeout)
DBusException: org.freedesktop.DBus.Python.AttributeError: Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/dbus/service.py", line 707, in _message_cb
    retval = candidate_method(self, *args, **keywords)
  File "../softwareproperties/dbus/SoftwarePropertiesDBus.py", line 278, in RemoveSource
    self.remove_source(_to_unicode(source))
  File "../softwareproperties/SoftwareProperties.py", line 741, in remove_source
    if source.file != apt_pkg.config.find_file("Dir::Etc::sourcelist"):
AttributeError: 'NoneType' object has no attribute 'file'

======================================================================
FAIL: test_enable_enable_disable_source_code_sources (__main__.TestDBus)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test_dbus.py", line 127, in test_enable_enable_disable_source_code_sources
    self.assertFalse("deb-src" in sourceslist)
AssertionError: True is not false

So I think before this is merged you have to decide how to handle this. Marking this Needs Fixing for now.

review: Needs Fixing
Revision history for this message
Andrea Corbellini (andrea.corbellini) wrote :
review: Needs Resubmitting

Unmerged revisions

822. By Andrea Corbellini

Do not enable deb-src lines by default.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'add-apt-repository'
--- add-apt-repository 2012-11-09 12:21:58 +0000
+++ add-apt-repository 2012-11-18 19:27:20 +0000
@@ -33,7 +33,7 @@
33 if len(user_inst.ppas) > 0:33 if len(user_inst.ppas) > 0:
34 # Translators: %(entity)s is either "team" or "user"34 # Translators: %(entity)s is either "team" or "user"
35 print(_("The %(entity)s named '%(user)s' has no PPA named '%(ppa)s'") % {35 print(_("The %(entity)s named '%(user)s' has no PPA named '%(ppa)s'") % {
36 'entity' : entity_name, 36 'entity' : entity_name,
37 'user' : user,37 'user' : user,
38 'ppa' : ppa_name})38 'ppa' : ppa_name})
39 print(_("Please choose from the following available PPAs:"))39 print(_("Please choose from the following available PPAs:"))
@@ -44,7 +44,7 @@
44 else:44 else:
45 # Translators: %(entity)s is either "team" or "user"45 # Translators: %(entity)s is either "team" or "user"
46 print(_("The %(entity)s named '%(user)s' does not have any PPA") % {46 print(_("The %(entity)s named '%(user)s' does not have any PPA") % {
47 'entity' : entity_name, 47 'entity' : entity_name,
48 'user' : user})48 'user' : user})
49 except KeyError:49 except KeyError:
50 pass50 pass
@@ -64,13 +64,13 @@
64 gettext.textdomain("software-properties")64 gettext.textdomain("software-properties")
65 usage = """Usage: %prog <sourceline>65 usage = """Usage: %prog <sourceline>
6666
67%prog is a script for adding apt sources.list entries. 67%prog is a script for adding apt sources.list entries.
68It can be used to add any repository and also provides a shorthand 68It can be used to add any repository and also provides a shorthand
69syntax for adding a Launchpad PPA (Personal Package Archive)69syntax for adding a Launchpad PPA (Personal Package Archive)
70repository.70repository.
7171
72<sourceline> - The apt repository source line to add. This is one of:72<sourceline> - The apt repository source line to add. This is one of:
73 a complete apt line in quotes, 73 a complete apt line in quotes,
74 a repo url and areas in quotes (areas defaults to 'main')74 a repo url and areas in quotes (areas defaults to 'main')
75 a PPA shortcut.75 a PPA shortcut.
76 a distro component76 a distro component
@@ -79,7 +79,7 @@
79 apt-add-repository 'deb http://myserver/path/to/repo stable myrepo'79 apt-add-repository 'deb http://myserver/path/to/repo stable myrepo'
80 apt-add-repository 'http://myserver/path/to/repo myrepo'80 apt-add-repository 'http://myserver/path/to/repo myrepo'
81 apt-add-repository 'https://packages.medibuntu.org free non-free'81 apt-add-repository 'https://packages.medibuntu.org free non-free'
82 apt-add-repository http://extras.ubuntu.com/ubuntu 82 apt-add-repository http://extras.ubuntu.com/ubuntu
83 apt-add-repository ppa:user/repository83 apt-add-repository ppa:user/repository
84 apt-add-repository multiverse84 apt-add-repository multiverse
8585
@@ -87,7 +87,7 @@
87sources.list87sources.list
88"""88"""
89 parser = OptionParser(usage)89 parser = OptionParser(usage)
90 # FIXME: provide a --sources-list-file= option that 90 # FIXME: provide a --sources-list-file= option that
91 # puts the line into a specific file in sources.list.d91 # puts the line into a specific file in sources.list.d
92 parser.add_option ("-m", "--massive-debug", action="store_true",92 parser.add_option ("-m", "--massive-debug", action="store_true",
93 dest="massive_debug", default=False,93 dest="massive_debug", default=False,
@@ -98,6 +98,9 @@
98 parser.add_option("-k", "--keyserver",98 parser.add_option("-k", "--keyserver",
99 dest="keyserver", default=DEFAULT_KEYSERVER,99 dest="keyserver", default=DEFAULT_KEYSERVER,
100 help=_("URL of keyserver. Default: %default"))100 help=_("URL of keyserver. Default: %default"))
101 parser.add_option("-s", "--enable-source", action="store_true",
102 dest="enable_source", default=False,
103 help=_("Allow downloading of the source packages from the repository"))
101 parser.add_option("-y", "--yes", action="store_true",104 parser.add_option("-y", "--yes", action="store_true",
102 dest="assume_yes", default=False,105 dest="assume_yes", default=False,
103 help=_("Assume yes to all queries"))106 help=_("Assume yes to all queries"))
@@ -129,7 +132,7 @@
129 if user.startswith("~"):132 if user.startswith("~"):
130 print(_("Did you mean 'ppa:%s/%s' ?") %(user[1:], ppa_name))133 print(_("Did you mean 'ppa:%s/%s' ?") %(user[1:], ppa_name))
131 sys.exit(1) # Exit because the user cannot be correct134 sys.exit(1) # Exit because the user cannot be correct
132 # If the PPA does not exist, then try to find if the user/team 135 # If the PPA does not exist, then try to find if the user/team
133 # exists. If it exists, list down the PPAs136 # exists. If it exists, list down the PPAs
134 _maybe_suggest_ppa_name_based_on_user(user)137 _maybe_suggest_ppa_name_based_on_user(user)
135 sys.exit(1)138 sys.exit(1)
@@ -142,7 +145,7 @@
142 if "private" in ppa_info and ppa_info["private"]:145 if "private" in ppa_info and ppa_info["private"]:
143 print(_("Adding private PPAs is not supported currently"))146 print(_("Adding private PPAs is not supported currently"))
144 sys.exit(1)147 sys.exit(1)
145 148
146 if options.remove:149 if options.remove:
147 print(_("You are about to remove the following PPA from your system:"))150 print(_("You are about to remove the following PPA from your system:"))
148 else:151 else:
@@ -198,7 +201,7 @@
198 print(_("Error: '%s' doesn't exist in a sourcelist file") % debsrc_line)201 print(_("Error: '%s' doesn't exist in a sourcelist file") % debsrc_line)
199202
200 else:203 else:
201 if not sp.add_source_from_line(line):204 if not sp.add_source_from_line(line, options.enable_source):
202 print(_("Error: '%s' invalid") % line)205 print(_("Error: '%s' invalid") % line)
203 sys.exit(1)206 sys.exit(1)
204 sp.sourceslist.save()207 sp.sourceslist.save()
205208
=== modified file 'softwareproperties/SoftwareProperties.py'
--- softwareproperties/SoftwareProperties.py 2012-10-01 09:24:55 +0000
+++ softwareproperties/SoftwareProperties.py 2012-11-18 19:27:20 +0000
@@ -78,10 +78,10 @@
78 RELEASE_UPGRADES_LTS : 'lts',78 RELEASE_UPGRADES_LTS : 'lts',
79 RELEASE_UPGRADES_NEVER : 'never',79 RELEASE_UPGRADES_NEVER : 'never',
80 }80 }
81 81
82 def __init__(self, datadir=None, options=None, rootdir="/"):82 def __init__(self, datadir=None, options=None, rootdir="/"):
83 """ Provides the core functionality to configure the used software 83 """ Provides the core functionality to configure the used software
84 repositories, the corresponding authentication keys and 84 repositories, the corresponding authentication keys and
85 update automation """85 update automation """
86 self.popconfile = rootdir+"/etc/popularity-contest.conf"86 self.popconfile = rootdir+"/etc/popularity-contest.conf"
8787
@@ -97,7 +97,7 @@
9797
98 self.sourceslist = SourcesList()98 self.sourceslist = SourcesList()
99 self.distro = aptsources.distro.get_distro()99 self.distro = aptsources.distro.get_distro()
100 100
101 self.seen_server = []101 self.seen_server = []
102 self.modified_sourceslist = False102 self.modified_sourceslist = False
103103
@@ -136,8 +136,8 @@
136 self.write_config()136 self.write_config()
137137
138 def get_update_automation_level(self):138 def get_update_automation_level(self):
139 """ Parse the apt cron configuration. Try to fit a predefined use case 139 """ Parse the apt cron configuration. Try to fit a predefined use case
140 and return it. Special case: if the user made a custom 140 and return it. Special case: if the user made a custom
141 configurtation, that we cannot represent it will return None """141 configurtation, that we cannot represent it will return None """
142 if apt_pkg.config.find_i(softwareproperties.CONF_MAP["autoupdate"]) > 0:142 if apt_pkg.config.find_i(softwareproperties.CONF_MAP["autoupdate"]) > 0:
143 # Autodownload143 # Autodownload
@@ -159,9 +159,9 @@
159 return None159 return None
160160
161 def set_update_automation_level(self, state):161 def set_update_automation_level(self, state):
162 """ Set the apt periodic configurtation to the selected 162 """ Set the apt periodic configurtation to the selected
163 update automation level. To synchronize the cache update and the 163 update automation level. To synchronize the cache update and the
164 actual upgrading function, the upgrade function, e.g. unattended, 164 actual upgrading function, the upgrade function, e.g. unattended,
165 will run every day, if enabled. """165 will run every day, if enabled. """
166 if state == softwareproperties.UPDATE_INST_SEC:166 if state == softwareproperties.UPDATE_INST_SEC:
167 apt_pkg.config.set(softwareproperties.CONF_MAP["unattended"], str(1))167 apt_pkg.config.set(softwareproperties.CONF_MAP["unattended"], str(1))
@@ -234,8 +234,8 @@
234 return True234 return True
235235
236 def get_popcon_participation(self):236 def get_popcon_participation(self):
237 """ Will return True if the user wants to participate in the popularity 237 """ Will return True if the user wants to participate in the popularity
238 contest. Otherwise it will return False. Special case: if no 238 contest. Otherwise it will return False. Special case: if no
239 popcon is installed it will return False """239 popcon is installed it will return False """
240 if os.path.exists(self.popconfile):240 if os.path.exists(self.popconfile):
241 lines = open(self.popconfile).read().split("\n")241 lines = open(self.popconfile).read().split("\n")
@@ -275,10 +275,10 @@
275 open(self.popconfile, "w").writelines(lines)275 open(self.popconfile, "w").writelines(lines)
276276
277 def get_source_code_state(self):277 def get_source_code_state(self):
278 """Return True if all distro componets are also available as 278 """Return True if all distro componets are also available as
279 source code. Otherwise return Flase. Special case: If the279 source code. Otherwise return Flase. Special case: If the
280 configuration cannot be represented return None"""280 configuration cannot be represented return None"""
281 281
282 if len(self.distro.source_code_sources) < 1:282 if len(self.distro.source_code_sources) < 1:
283 # we don't have any source code sources, so283 # we don't have any source code sources, so
284 # uncheck the button284 # uncheck the button
@@ -327,7 +327,7 @@
327 print("\n")327 print("\n")
328328
329 def massive_debug_output(self):329 def massive_debug_output(self):
330 """Print the complete sources.list""" 330 """Print the complete sources.list"""
331 print("START SOURCES.LIST:")331 print("START SOURCES.LIST:")
332 for source in self.sourceslist:332 for source in self.sourceslist:
333 print(source.str())333 print(source.str())
@@ -342,12 +342,12 @@
342342
343 def enable_component(self, comp):343 def enable_component(self, comp):
344 """Enable a component of the distro"""344 """Enable a component of the distro"""
345 self.distro.enable_component(comp) 345 self.distro.enable_component(comp)
346 self.set_modified_sourceslist()346 self.set_modified_sourceslist()
347347
348 def disable_component(self, comp):348 def disable_component(self, comp):
349 """Disable a component of the distro"""349 """Disable a component of the distro"""
350 self.distro.disable_component(comp) 350 self.distro.disable_component(comp)
351 self.set_modified_sourceslist()351 self.set_modified_sourceslist()
352352
353 def _find_template_from_string(self, name):353 def _find_template_from_string(self, name):
@@ -391,7 +391,7 @@
391 for source in self.distro.source_code_sources:391 for source in self.distro.source_code_sources:
392 self.sourceslist.remove(source)392 self.sourceslist.remove(source)
393 self.set_modified_sourceslist()393 self.set_modified_sourceslist()
394 394
395 def enable_source_code_sources(self):395 def enable_source_code_sources(self):
396 """Enable source code source for all distro sources"""396 """Enable source code source for all distro sources"""
397 sources = []397 sources = []
@@ -426,7 +426,7 @@
426 for source in self.sourceslist.list:426 for source in self.sourceslist.list:
427 source_bkp = SourceEntry(line=source.line,file=source.file)427 source_bkp = SourceEntry(line=source.line,file=source.file)
428 self.sourceslist_backup.append(source_bkp)428 self.sourceslist_backup.append(source_bkp)
429 429
430 def _find_source_from_string(self, line):430 def _find_source_from_string(self, line):
431 # ensure that we have a current list, it might have been changed underneath431 # ensure that we have a current list, it might have been changed underneath
432 # us432 # us
@@ -456,7 +456,7 @@
456 return False456 return False
457457
458 def revert(self):458 def revert(self):
459 """Revert all settings to the state when software-properties 459 """Revert all settings to the state when software-properties
460 was launched"""460 was launched"""
461 #FIXME: GPG keys are still missing461 #FIXME: GPG keys are still missing
462 self.restore_apt_conf()462 self.restore_apt_conf()
@@ -557,7 +557,7 @@
557 def get_cdrom_sources(self):557 def get_cdrom_sources(self):
558 """Return the list of CDROM based distro sources"""558 """Return the list of CDROM based distro sources"""
559 return self.distro.cdrom_sources559 return self.distro.cdrom_sources
560 560
561 def get_comp_download_state(self, comp):561 def get_comp_download_state(self, comp):
562 """Return a tuple: the first value describes if a component is enabled562 """Return a tuple: the first value describes if a component is enabled
563 in the Internet repositories. The second value describes if the563 in the Internet repositories. The second value describes if the
@@ -567,7 +567,7 @@
567567
568 def get_comp_child_state(self, template):568 def get_comp_child_state(self, template):
569 """Return a tuple: the first value describes if a component is enabled569 """Return a tuple: the first value describes if a component is enabled
570 in one of the child source that matcth the given template. 570 in one of the child source that matcth the given template.
571 The second value describes if the first value is inconsistent."""571 The second value describes if the first value is inconsistent."""
572 comps = []572 comps = []
573 for child in self.distro.child_sources:573 for child in self.distro.child_sources:
@@ -579,17 +579,17 @@
579 return (True, False)579 return (True, False)
580 elif len(comps) > 0 and\580 elif len(comps) > 0 and\
581 len(self.distro.enabled_comps ^ set(comps)) != 0:581 len(self.distro.enabled_comps ^ set(comps)) != 0:
582 # A matching child source does exist but doesn't include all 582 # A matching child source does exist but doesn't include all
583 # enabled distro components583 # enabled distro components
584 return(False, True)584 return(False, True)
585 else:585 else:
586 # There is no corresponding child source at all586 # There is no corresponding child source at all
587 return (False, False)587 return (False, False)
588 588
589 def reload_sourceslist(self):589 def reload_sourceslist(self):
590 self.sourceslist.refresh()590 self.sourceslist.refresh()
591 self.sourceslist_visible=[]591 self.sourceslist_visible=[]
592 self.distro.get_sources(self.sourceslist) 592 self.distro.get_sources(self.sourceslist)
593593
594 def write_config(self):594 def write_config(self):
595 """Write the current apt configuration to file"""595 """Write the current apt configuration to file"""
@@ -634,10 +634,10 @@
634 # and append the updated keys634 # and append the updated keys
635 for i in cnf.list():635 for i in cnf.list():
636 f.write("APT::Periodic::%s \"%s\";\n" % (i, cnf.find_i(i)))636 f.write("APT::Periodic::%s \"%s\";\n" % (i, cnf.find_i(i)))
637 f.close() 637 f.close()
638638
639 def save_sourceslist(self):639 def save_sourceslist(self):
640 """Backup the existing sources.list files and write the current 640 """Backup the existing sources.list files and write the current
641 configuration"""641 configuration"""
642 self.sourceslist.backup(".save")642 self.sourceslist.backup(".save")
643 self.sourceslist.save()643 self.sourceslist.save()
@@ -647,7 +647,7 @@
647 helper that checks if a given line is in the source list647 helper that checks if a given line is in the source list
648 return the channel name or None if not found648 return the channel name or None if not found
649 """649 """
650 srcentry = SourceEntry(srcline) 650 srcentry = SourceEntry(srcline)
651 if os.path.exists(self.CHANNEL_PATH):651 if os.path.exists(self.CHANNEL_PATH):
652 for f in glob.glob("%s/*.list" % self.CHANNEL_PATH):652 for f in glob.glob("%s/*.list" % self.CHANNEL_PATH):
653 for line in open(f):653 for line in open(f):
@@ -696,14 +696,15 @@
696 line = "deb %s %s %s" % ( repo, self.distro.codename, areas )696 line = "deb %s %s %s" % ( repo, self.distro.codename, areas )
697 return line697 return line
698698
699 def add_source_from_line(self, line):699 def add_source_from_line(self, line, enable_debsrc=False):
700 """700 """
701 Add a source with the given apt line and auto-add701 Add a source with the given apt line and auto-add
702 signing key if we have it in the whitelist702 signing key if we have it in the whitelist
703 """703 """
704 (deb_line, file) = expand_ppa_line(line.strip(), self.distro.codename)704 (deb_line, file) = expand_ppa_line(line.strip(), self.distro.codename)
705 deb_line = self.expand_http_line(deb_line)705 deb_line = self.expand_http_line(deb_line)
706 debsrc_line = 'deb-src' + deb_line[3:]706 debsrc_entry_type = 'deb-src' if enable_debsrc else '#deb-src'
707 debsrc_line = debsrc_entry_type + deb_line[3:]
707 new_deb_entry = SourceEntry(deb_line, file)708 new_deb_entry = SourceEntry(deb_line, file)
708 new_debsrc_entry = SourceEntry(debsrc_line, file)709 new_debsrc_entry = SourceEntry(debsrc_line, file)
709 if new_deb_entry.invalid or new_debsrc_entry.invalid:710 if new_deb_entry.invalid or new_debsrc_entry.invalid:
@@ -716,7 +717,7 @@
716 comment=new_deb_entry.comment,717 comment=new_deb_entry.comment,
717 file=new_deb_entry.file,718 file=new_deb_entry.file,
718 architectures=new_deb_entry.architectures)719 architectures=new_deb_entry.architectures)
719 self.sourceslist.add(new_debsrc_entry.type,720 self.sourceslist.add(debsrc_entry_type,
720 new_debsrc_entry.uri,721 new_debsrc_entry.uri,
721 new_debsrc_entry.dist,722 new_debsrc_entry.dist,
722 new_debsrc_entry.comps,723 new_debsrc_entry.comps,

Subscribers

People subscribed via source and target branches

to status/vote changes: